Harlequin: onChange -> alert -> focus

Hi,

ich kämpfe hier mit einem seltsamen Problem:

Im onChange eines Editfeldes rufe ich ein Javascriptfunktion auf, die die Eingabe auf ein Vielfaches eines bestimmten Wertes überprüft (dient als Zeitraster). Dort soll je nach eingestellten Modus entweder abgerundet oder eine Alertbox mit einem Hinweis ausgegeben werden. Nach dem Hinweis soll der Cursor wieder in dem Editfeld stehen, damit der Benutzer die Eingabe korrigieren muss. Im IE klappt das einwandfrei, aber im Firefox springt der Cursor trotzdem ins nächste Feld...

Code:

function TimeEdit_RoundTime ()
{
    // nur für Längen, die Teiler von 60 sind
    var minute = parseInt(document.getElementById(this.ID+"_Minute").value, 10);
    if (this.UnitMode == this.UnitModeRoundDown)
    {
        minute -= minute % this.unitLength;
        document.getElementById(this.ID+"_Minute").value = minute;
    }
    else if ((minute % this.unitLength) != 0)
    {
        if (this.OnWarn != null)
            eval (this.OnWarn)
        document.getElementById(this.ID+"_Minute").focus();
    }
}

wobei this.onWarn den Funktionsaufruf für den Alert enthält.

Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

Gruß,

Harlequin

  1. hi,

    if (this.OnWarn != null)
                eval (this.OnWarn)

    Was enthält die Objekteigenschaft OnWarn?

    Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

    Hast du bereits verifiziert, dass es _nicht_ an deinem eval()-Gehampel liegt?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. hi,

      if (this.OnWarn != null)
                  eval (this.OnWarn)

      Was enthält die Objekteigenschaft OnWarn?

      OnWarn = "UnitWarn();"

      function UnitWarn ()
      {
          alert(rasterErrorMsg);
          return true;
      }

      rasterErrorMsg enthält einen String der per C# dynamisch generiert wird (wegen Übersetzungen).
      Die Vorgehensweise ist deshalb so umständlich, weil das Editfeld ein generisches Control in C# ist, welches von sich aus nicht wissen kann, was es nun genau bei einer Zeitrasterverletzung machen soll.

      Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

      Hast du bereits verifiziert, dass es _nicht_ an deinem eval()-Gehampel liegt?

      Die eval()-Sache wird korrekt ausgeführt und auch die JavaScript-Konsole meldet nichts. Im JS-Debugger des VisualStudio (IE) läuft alles exakt so ab wie ich es haben möchte.

      Ich werd mal verscuhen den focus() mit setTimeout zu verzögern evtl. ergibt sich da was neues...

      Gruß,

      Harlequin

      1. if (this.OnWarn != null)
                    eval (this.OnWarn)

        Was enthält die Objekteigenschaft OnWarn?

        OnWarn = "UnitWarn();"

        Einfahcer und vor allem ohne eval wäre es, wenn du den puren String mit dem Funktionsbezeichner übergibst:

        OnWarn = "UnitWarn"

        Dann geht nämlich:

        if(typeof window[OnWarn] == 'function') windowOnWarn;

        Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

        wegen dem Fehler im anderen Thread, das ist ein etwas älterer Bug im Firefox und hat nichts mit deinem Problem zu tun. Du rufst aber die Funktion falsch auf, so sollte es gehen:
         window.setTimeout ( function() { document.getElementById(this.ID + '_Minute').focus();},1);

        Struppi.

        1. hi,

          Einfahcer und vor allem ohne eval wäre es, wenn du den puren String mit dem Funktionsbezeichner übergibst:

          OnWarn = "UnitWarn"

          Dann geht nämlich:

          if(typeof window[OnWarn] == 'function') windowOnWarn;

          Wobei es hier vermutlich eher beide Male this.OnWarn sein sollte - der ursprüngliche Code legt ja den Anschein nahe, dass OnWarn hier eine Eigenschaft des Objektes sein soll, auf welchem der Event ausgelöst wurde.

          gruß,
          wahsaga

          --
          /voodoo.css:
          #GeorgeWBush { position:absolute; bottom:-6ft; }
          1. Hi,

            if(typeof window[OnWarn] == 'function') windowOnWarn;

            Wobei es hier vermutlich eher beide Male this.OnWarn sein sollte - der ursprüngliche Code legt ja den Anschein nahe, dass OnWarn hier eine Eigenschaft des Objektes sein soll, auf welchem der Event ausgelöst wurde.

            Korrekt... aber danke für den Tip, der eval ist jetzt draußen.

            Gruß,

            Harlequin

        2. Hi,

          Einfahcer und vor allem ohne eval wäre es, wenn du den puren String mit dem Funktionsbezeichner übergibst:

          OnWarn = "UnitWarn"

          Dann geht nämlich:

          if(typeof window[OnWarn] == 'function') windowOnWarn;

          Kannte ich noch nicht, aber funktioniert einwandfrei.

          Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

          wegen dem Fehler im anderen Thread, das ist ein etwas älterer Bug im Firefox und hat nichts mit deinem Problem zu tun. Du rufst aber die Funktion falsch auf, so sollte es gehen:
          window.setTimeout ( function() { document.getElementById(this.ID + '_Minute').focus();},1);

          a) so funktioniert der Aufruf leider nicht, da this.ID zum Ausführungszeitpunkt scheinbar nichtmehr gültig ist.

          b) das Problem tritt auch dann auf (wenn in der JS-Konsole der Fehler wegen dem nicht gefundenen Element steht). Sobald ich mit dem Cursor in einem Editfeld mit falschen Wert stehe und ein anderes Fenster anklicke (z.B. wechsel zur JS-Konsole) erscheint die Alert-Box und danach ist der Cursor im FF weg und es sind keine Eingaben mehr möglich. Nach nochmaligen wechseln zu einer anderen Applikation und zurück ist der Cursor zwar wieder da, aber evtl in einem anderen Textfeld und der falsche Wert steht immer noch da (eigentlich ein Zustand den ich nicht will...)
          Evtl. doch ein Problem mit der Exception?

          Gruß,

          Harlequin

          1. Hi,

            noch ein paar Informationen, da ich hier noch immer damit rumkämpfe...

            wegen dem Fehler im anderen Thread, das ist ein etwas älterer Bug im Firefox und hat nichts mit deinem Problem zu tun. Du rufst aber die Funktion falsch auf, so sollte es gehen:
            window.setTimeout ( function() { document.getElementById(this.ID + '_Minute').focus();},1);

            a) so funktioniert der Aufruf leider nicht, da this.ID zum Ausführungszeitpunkt scheinbar nichtmehr gültig ist.

            Gibts hier eine Lösung? Wobei meine bisherige Variante eigentlich immer funktioniert hat... oder sind da irgendwelche Probleme damit zu erwarten?

            b) das Problem tritt auch dann auf (wenn in der JS-Konsole der Fehler wegen dem nicht gefundenen Element steht). Sobald ich mit dem Cursor in einem Editfeld mit falschen Wert stehe und ein anderes Fenster anklicke (z.B. wechsel zur JS-Konsole) erscheint die Alert-Box und danach ist der Cursor im FF weg und es sind keine Eingaben mehr möglich. Nach nochmaligen wechseln zu einer anderen Applikation und zurück ist der Cursor zwar wieder da, aber evtl in einem anderen Textfeld und der falsche Wert steht immer noch da (eigentlich ein Zustand den ich nicht will...)

            Das Problem scheint dadurch ausgelöst zu werden, dass ich die Funktion nicht über onChange sondern über onBlur aufrufe, wegen einem Problem im IE wo onChange nicht funktioniert hat... Scheinbar hat der Firefox ein Problem mit der Verarbeitung von onBlur, wenn die ganze Applikation den Fokus verliert. Jemand eine Idee für eine Lösung? Oder hilft hier nur eine Untrescheidung von IE/Rest um entweder onBlur oder onChange zu verwenden?

            Evtl. doch ein Problem mit der Exception?

            Die Exception kommt auch mit onChange, ist somit nicht auslöser des Problems.

            Gruß,

            Harlequin

            1. hi,

              window.setTimeout ( function() { document.getElementById(this.ID + '_Minute').focus();},1);

              a) so funktioniert der Aufruf leider nicht, da this.ID zum Ausführungszeitpunkt scheinbar nichtmehr gültig ist.

              Gibts hier eine Lösung?

              Merke dir die ID doch vorher in einer im globalen Scope verfügbaren Variablen.

              Das Problem scheint dadurch ausgelöst zu werden, dass ich die Funktion nicht über onChange sondern über onBlur aufrufe, wegen einem Problem im IE wo onChange nicht funktioniert hat... Scheinbar hat der Firefox ein Problem mit der Verarbeitung von onBlur, wenn die ganze Applikation den Fokus verliert. Jemand eine Idee für eine Lösung? Oder hilft hier nur eine Untrescheidung von IE/Rest um entweder onBlur oder onChange zu verwenden?

              Hm, onChange und onBlur dürften doch sowieso fast "Hand in Hand" gehen - schließlich feuert onChange doch in den gängigen Implementierungen erst dann, wenn das Element den Fokus verliert.

              Du könntest schaun, ob onChange im FF vor onBlur feuert - wenn ja, reagiere auf onChange, und cancle dabei den onBlur-Event.
              Wenn im IE onChange nicht feuert, bleibt dort dann ja immer noch der onBlur erhalten.

              gruß,
              wahsaga

              --
              /voodoo.css:
              #GeorgeWBush { position:absolute; bottom:-6ft; }
              1. Hi,

                Merke dir die ID doch vorher in einer im globalen Scope verfügbaren Variablen.

                Manchmal sieht man die einfachsten Dinge nicht...

                Hm, onChange und onBlur dürften doch sowieso fast "Hand in Hand" gehen - schließlich feuert onChange doch in den gängigen Implementierungen erst dann, wenn das Element den Fokus verliert.

                Beim Testen hab ich festgestellt das mir onChange sowieso nicht weiterhilft, da es beim 2.Versuch das Feld zu verlassen nicht mehr feuert, weil der Wert ja nicht geändert wurde...

                Du könntest schaun, ob onChange im FF vor onBlur feuert - wenn ja, reagiere auf onChange, und cancle dabei den onBlur-Event.
                Wenn im IE onChange nicht feuert, bleibt dort dann ja immer noch der onBlur erhalten.

                So wie es aussieht muss ich das Konzept überarbeiten, da ich im onBlur keine Alertbox aufmachen darf, ohne das der Firefox dabei durcheinander kommt. Ich denk ich werd einfach einen Hinweistext über dem Submitbutton einblenden und den Submit des Formulars verhindern (mit einer Alertbox als Hinweis). Das kommt dem Ziel noch am nähesten...

                Gruß,

                Harlequin

  2. if (this.OnWarn != null)
                eval (this.OnWarn)

    Wozu das eval "gehampel"?

    document.getElementById(this.ID+"_Minute").focus();
        }
    }

    wobei this.onWarn den Funktionsaufruf für den Alert enthält.

    Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

    Ja stimmt, den Fehler hat ich ebenfalls schon, es bleibt nichts anderes übrig, als den focus() aufruf in setTimeout() zu verpacken.

    Struppi.

    1. if (this.OnWarn != null)
                  eval (this.OnWarn)

      Wozu das eval "gehampel"?

      Siehe andere Antwort. Es handelt sich um ein C#-Control das erst zur Laufzeit gesagt bekommt was es eigentlich tun soll.

      Ich vermute, dass hier irgendein Timingproblem vorliegt, dass verhindert dass der Fokus korrekt gesetzt wird... Kann mir jemand helfen?

      Ja stimmt, den Fehler hat ich ebenfalls schon, es bleibt nichts anderes übrig, als den focus() aufruf in setTimeout() zu verpacken.

      Habe ich gerade probiert... funktioniert solange, bis ich mit einem 'falschen' Wert im Editfeld die Anwendung wechsel...

      Fehler: [Exception... "'Die Erlaubnis für das Setzen der Eigenschaft XULElement.selectedIndex wurde verweigert' when calling method: [nsIAutoCompletePopup::selectedIndex]"  nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)"  location: "JS frame :: http://localhost/webterm_aspx/timeedit.js :: <TOP_LEVEL> :: line 169"  data: no]
      Quelldatei: http://localhost/webterm_aspx/timeedit.js
      Zeile: 169

      Die Zeile 169 enthält:
              window.setTimeout ("document.getElementById('"+this.ID+"_Minute').focus();",1);

      Hm... sieht gar nicht gut aus :-(

      Gruß,

      Harlequin