Bart: Problem bei Setzen und Ändern des Focus

Hallo,

Ich habe ein Formular, in dem Werte eingetragen werden.
Für jeden Wert gibt es ein Feld, in das absolute Werte eingetragen werden sollen, und ein Feld, in das Veränderungen des absoluten Wertes eingetragen werden können.

Wenn man eine Veränderung eingibt, und mit "Tab" weiterspringt, so soll die Veränderung zu dem absoluten Wert dazugerechenet werden (und gleich angezeigt werden), das Feld der Veränderung soll geleert werden, und der Focus soll zurück auf das Feld mit der Veränderung gesetzt werden (damit man noch eine Veränderung eingeben kann).

So sieht der entsprechende Teil des Quelltexts aus:

<script type="text/javascript">  
	function calculate (id) {  
		var wert = (document.getElementById("wert" + id).value >= 0) ? document.getElementById("wert" + id).value : 0;  
		var ver = document.getElementById("ver" + id).value;  
		if (ver != "") {  
			wert = wert - ver;  
			ver = "";  
  
			document.getElementById("wert" + id).value = wert;  
			document.getElementById("ver" + id).value = ver;  
			document.forms["odform"].elements["ver" + id].focus();  
		}  
	}  
</script>
  
<form name="odform" id="odform" enctype="multipart/form-data" method="post" action="index.php">  
<input type="text" id="wert1" name="wert1" size="6" value="">  
<input type="text" id="ver1" name="ver1" size="6" onchange="calculate(1)" value="">  
<br>  
<input type="text" id="wert2" name="wert2" size="6" value="">  
<input type="text" id="ver2" name="ver2" size="6" onchange="calculate(2)" value="">  
<br>  
<input type="submit" value="Senden" name="senden">  
</form>

2 Probleme treten dabei auf:

1. Es wird nicht immer richtig gerechnet (mit dem Problem wollte ich mich später befassen, wenn jemand etwas dazu sagen möchte, freue ich mich dennoch darüber (für Kommata habe ich immer einen Punkt benutzt)).

2. Der Focus wird nicht gesetzt. Wenn ich in das Feld "ver1" etwas eingebe, und dann mit "Tab" weiterspringe, wird zwar (falsch) gerechnet, und das Feld "ver1" wird auch geleert, doch der Focus landet auf dem Feld "wert2", und nicht auf "ver1".

Gewünschte Browser-Unterstützung: mindestens IE und FF

Ich wäre euch sehr dankbar, wenn ihr mir bei meinem Problem helfen könntet!

MfG, Bart

  1. Hi,

    1. Es wird nicht immer richtig gerechnet (mit dem Problem wollte ich mich später befassen, wenn jemand etwas dazu sagen möchte, freue ich mich dennoch darüber (für Kommata habe ich immer einen Punkt benutzt)).

    Aus Formularfeldern liest du immer Strings aus - bevor du mit diesen rechnen kannst, musst du sie in Zahlen umwandeln; Stichworte parseInt/parseFloat.

    Und eine 0 davor zu hängen, kann auch schnell problematisch werden - Stichwort Oktalsystem.
    Trenne sauber zwischen den reinen Zahlenwerten und den Berechungen mit diesen, und der Formatierung bei der *Ausgabe*.

    1. Der Focus wird nicht gesetzt. Wenn ich in das Feld "ver1" etwas eingebe, und dann mit "Tab" weiterspringe, wird zwar (falsch) gerechnet, und das Feld "ver1" wird auch geleert, doch der Focus landet auf dem Feld "wert2", und nicht auf "ver1".

    Natürlich, das ist die „normale“ Reihenfolge, die sich aus der Anordnung der Felder in deinem Formular ergibt.
    Entweder gibst du die Reihenfolge per tabindex vor, oder du setzt selbst per Script den Fokus.

    Pass' dabei aber bitte auf, dass du nicht etwas zusammenbastelst, was der normalen Formularhandhabung, die der Benutzer gewohnt ist, vollkommen zuwider läuft.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Danke für deine Antwort, ChrisB!

      Aus Formularfeldern liest du immer Strings aus - bevor du mit diesen rechnen kannst, musst du sie in Zahlen umwandeln; Stichworte parseInt/parseFloat.

      Und eine 0 davor zu hängen, kann auch schnell problematisch werden - Stichwort Oktalsystem.
      Trenne sauber zwischen den reinen Zahlenwerten und den Berechungen mit diesen, und der Formatierung bei der *Ausgabe*.

      Das erklärt eine ganze Menge. Mit JS arbeite ich nicht so viel. Deswegen denke ich nie daran, dass man aus Strings erst Zahlen machen mus bzw. umgekehrt...

      Natürlich, das ist die „normale“ Reihenfolge, die sich aus der Anordnung der Felder in deinem Formular ergibt.
      Entweder gibst du die Reihenfolge per tabindex vor, oder du setzt selbst per Script den Fokus.

      Ich setze doch den Fokus per Script:
      document.forms["odform"].elements["ver" + id].focus()

      Das Problem dabei ist, dass der Fokus nicht auf das Feld gesetzt werden kann, aus dem der Fokus kommt.
      Wenn der Fokus aus dem Feld "ver1" kommt, und ich ihn per Script auf "wert1" oder "ver2" setzen lasse (nach der normalen Reihenfolge würde er ja auf "wert2" gehen), dann funktioniert das.
      Warum aber kann ich den Fokus per Script nicht auf das Feld setzen lassen, aus dem er kommt? Bzw. Wie kann man das machen?

      1. Hallo,

        Aus Formularfeldern liest du immer Strings aus - bevor du mit diesen rechnen kannst, musst du sie in Zahlen umwandeln; Stichworte parseInt/parseFloat.
        [...]
        Das erklärt eine ganze Menge. Mit JS arbeite ich nicht so viel. Deswegen denke ich nie daran, dass man aus Strings erst Zahlen machen mus bzw. umgekehrt...

        gibt es andere Sprachen, in denen das nicht so ist?

        Ich setze doch den Fokus per Script:
        document.forms["odform"].elements["ver" + id].focus()
        Das Problem dabei ist, dass der Fokus nicht auf das Feld gesetzt werden kann, aus dem der Fokus kommt.

        Damit kann es zwar auch zusammenhängen; eine solche Einschränkung ist mir aber nur im Zusammenhang mit dem Eventhandler onblur bekannt. Der spricht an, wenn das Feld den Focus verliert. Wenn man den Focus nun in der Handlerfunktion wieder auf ebendieses Feld zurücksetzt, produziert man eine Art Deadlock - und AFAIK verhindern die meisten Browser das inzwischen.

        Aber du hast hier nicht onblur, sondern onchange. Ich vermute da ein ganz anderes Problem. Ich vermute nämlich, dass der Focus in dem Moment, wo onchange reagiert, immer noch auf dem gleichen Feld liegt, und erst *nach* dem onchange wechselt.

        Vielleicht solltest du den Focuswechsel erst nach einer kurzen Verzögerung auslösen, wenn die browserinterne Event-Bearbeitung fertig ist.

        So long,
         Martin

        --
        Viele Fachleute vertreten die Ansicht, jedes Feature eines Programms, das sich nicht auf Wunsch abstellen lässt, sei ein Bug.
        Außer bei Microsoft. Da ist es umgekehrt.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Aus Formularfeldern liest du immer Strings aus - bevor du mit diesen rechnen kannst, musst du sie in Zahlen umwandeln; Stichworte parseInt/parseFloat.
          [...]
          Das erklärt eine ganze Menge. Mit JS arbeite ich nicht so viel. Deswegen denke ich nie daran, dass man aus Strings erst Zahlen machen mus bzw. umgekehrt...

          gibt es andere Sprachen, in denen das nicht so ist?

          PHP? Zumindest habe ich da noch keine Probleme bekommen.

          Vielleicht solltest du den Focuswechsel erst nach einer kurzen Verzögerung auslösen, wenn die browserinterne Event-Bearbeitung fertig ist.

          Das ist es! Besonders der FF hat erst den Fokus verloren, dadurch musste er die JS-Funktionen ausführen, und dann hat er den Fokus neu gesetzt (durch die Tab-Taste ausgelöst). Mit einer Pause von nur 50 Millisekunden ist mein Problem gelöst!

          Vielen Danke für eure Hilfe!

        2. Hi,

          Deswegen denke ich nie daran, dass man aus Strings erst Zahlen machen mus bzw. umgekehrt...

          gibt es andere Sprachen, in denen das nicht so ist?

          Wie schon gesagt, PHP hat 'ne Menge „Magie“ eingebaut, was autoamtische Typkonvertierung angeht.
          Aber in JS liegt der Fall ja auch anders - da ist der Operator + sowohl für Addition als auch für Stringverkettung zuständig, je nach Kontext; es *kann* also im Zweifelsfall gar nicht sicher entschieden werden, welche Funktionalität die gemeinte ist.
          Dieses „Problem“ hat PHP nicht, weil da Additions- und Stringverkettungsoperator zwei verschiedene (Zeichen) sind.

          MfG ChrisB

          --
          RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
      2. Das Problem dabei ist, dass der Fokus nicht auf das Feld gesetzt werden kann, aus dem der Fokus kommt.
        Wenn der Fokus aus dem Feld "ver1" kommt, und ich ihn per Script auf "wert1" oder "ver2" setzen lasse (nach der normalen Reihenfolge würde er ja auf "wert2" gehen), dann funktioniert das.
        Warum aber kann ich den Fokus per Script nicht auf das Feld setzen lassen, aus dem er kommt? Bzw. Wie kann man das machen?

        Du reagierst doch derzeit auf onchange, feuert das nicht schon während man etwas eingibt? Für das von dir beschriebene Ereignis verwende ich onblur.
        Dabei dürftest du aber das Problem bekommen, dass man nie wieder den Cursor aus dem Feld bekommt ^^.
        Weil ich das fast nie mache, weiß ich gerade nicht mehr wie das geht, aber konnte man nicht indem man false returnt das Ereignis verhindern oder so ähnlich? Also in deinem Fall das Verlassen des Formular-Feldes.
        Ich bin mir da aber furchtbar unsicher, also nagel mich nicht drauf fest, hier ein anderer Vorschlag:

        Schreib eine zweite Funktion, die das onfocus-Event des Elements, welches als nächstes in der Tabreihenfolge kommt abfängt und setze von dort aus deinen focus();

        Nebenbei: Wenn du möchtest kannst du das type-Attribut auf number ändern. Alte Browser stellen es immernoch als Textfeld dar, moderne (derzeit glaube ich nur Opera) als Zahlen-Benutzereingabe-Element (wahrscheinlich ein Spinner).

        --
        sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ_de:] zu:) fl:( ss:| ls:[ js:(
        1. [latex]Mae  govannen![/latex]

          Du reagierst doch derzeit auf onchange, feuert das nicht schon während man etwas eingibt?

          Nein:

          The change event occurs when a control loses the input focus and its value has been modified since gaining focus. This event is valid for INPUT, SELECT, and TEXTAREA. element. W3C

          Also wenn der Focus geändert wird (wie blur) UND sich der Wert geändert hat. Aus diesem Grund ist blur auch oft nicht das passende Event, da dies auch feuert, wenn das Feld unverändert bleibt (z.B. beim "durchtabben" per Tastatur)

          Cü,

          Kai

          --
          Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
          in Richtung "Mess up the Web".(suit)
          Foren-Stylesheet
        2. Du reagierst doch derzeit auf onchange, feuert das nicht schon während man etwas eingibt? Für das von dir beschriebene Ereignis verwende ich onblur.
          Dabei dürftest du aber das Problem bekommen, dass man nie wieder den Cursor aus dem Feld bekommt ^^.

          Ich überprüfe ja erst, ob in dem Feld etwas drin steht. Wenn nichts drinsteht, dann darf der Browser sein Tab ausführen wie er es gewohtn ist (also einfach in das nächste Feld den Fokus setzen).

          Das Beispiel zu onblur sieht dem, was ich möchte schon sehr ähnlich. Das Problem dabei ist allerdings: Den Fokus zu setzen funktioniert bei Firefox nicht! Mit dem IE kein Problem.

          Weil ich das fast nie mache, weiß ich gerade nicht mehr wie das geht, aber konnte man nicht indem man false returnt das Ereignis verhindern oder so ähnlich? Also in deinem Fall das Verlassen des Formular-Feldes.
          Ich bin mir da aber furchtbar unsicher, also nagel mich nicht drauf fest, hier ein anderer Vorschlag:

          Schreib eine zweite Funktion, die das onfocus-Event des Elements, welches als nächstes in der Tabreihenfolge kommt abfängt und setze von dort aus deinen focus();

          Sowas habe ich auch schon versucht:
          z.B. mit onkeypress, und dann überprüfen ob Tab gedrückt wurde. Aber: Das funktioniert mit Firefox nicht. Der IE hat mir (zum Testen) immer ausgegeben, welcher Tastencode gedrückt wurde (z.B. 9 für Tab), FF hat nicht reagiert, bzw. nicht den Tastencode ausgegeben.

          Was ich auch noch probiert habe: Bei Tab in ein neues Feld schreiben, aus welchem Feld der Fokus kam, den Fokus dann auf diese Feld setzen, und dann überprüfen: Wenn das neue Feld den Focus bekommt (onfocus), das Feld auslesen, und den Focus auf das entsprechende Feld setzen.
          Das Auslesen hat auch noch funktioniert, den Focus zu setzen aber nicht.

          Scheinbar hat FF eine andere Priorität beim abarbeiten.

          MfG, Bart

    2. Aus Formularfeldern liest du immer Strings aus - bevor du mit diesen rechnen kannst, musst du sie in Zahlen umwandeln; Stichworte parseInt/parseFloat.

      Das stimmt zwar als Faustregel und dient der Fehlervermeidung. Aber es hängt ganz von den verwendeten Operatoren und den Operandentypen ab, ob man explizit Typen umwandeln *muss*. In den Berechnungen, die Bart durchführt, werden die Strings automatisch zu Number-Werten umgewandelt. Das sind str >= 0 und str1 - str2. In diesen Fällen ist eine explizite Typumwandlung nicht nötig, da das Ergebnis eindeutig und zuverlässig ist.

      Der genannten +-Operator ist da tatsächlich heikler, aber das Ergebnis auch vorhersehbar: Ist einer der Operanden ein String, castet er den anderen nach String und hängt sie aneinander, andernfalls castet er beide nach Number und addiert sie. formularwert + number ergibt also immer einen String, hier ist eine explizite Typumwandlung nötig, wenn man eine Addition will.

      Und eine 0 davor zu hängen, kann auch schnell problematisch werden - Stichwort Oktalsystem.

      Dieses Problem besteht nur bei parseInt ohne ausdrücklichen zweiten Parameter. Nicht bei der automatischen Konvertierung mittels ToNumber - welche man mit Number() explizit durchführen kann. Diese erkennt Dezimal- und Hexadezimalwerte (letztere mit 0x-Prefix). Auch nicht bei parseFloat, welche immer zur Basis 10 arbeitet.

      parseFloat ist die toleranteste und hinsichtlich des Zahlensystems sicherste Variante, wenn man nicht ausdrücklich Ganzzahlen braucht. Sie geht allerdings von ».« als Dezimaltrenner aus, d.h. »,« wird als Zahlenende angesehen.

      Mathias

    1. Es wird nicht immer richtig gerechnet (mit dem Problem wollte ich mich später befassen, wenn jemand etwas dazu sagen möchte, freue ich mich dennoch darüber (für Kommata habe ich immer einen Punkt benutzt)).

    Wann wird nicht richtig gerechnet? Bei welchen Eingaben kommt ein falsches Ergebnis heraus?

    Mathias