Fabian: Events im Firefox

Hallo,
ich habe da ein paar Schwierigkeiten mit den Events im Firefox...
Und zwar sieht es folgendermaßen aus:

  
<input type="text" onKeyUp="checkEnter();">  

  
function checkEnter(evt)  
{  
if (!evt)  
  evt = window.event;  
if (evt.keyCode == 13)  
  {  
  alert('Enter');  
  return false;  
  }  
}  

So, mein lieber Internet Explorer macht da keine Probleme mit..
Firefox hingegen bleibt davon unbeeindruckt und macht gar nix.
Wenn ich dann aber in die Konsole vom Firefox schaue steht da folgendes:
"TypeError: evt is undefined"

Was kann ich da tun?

Fabian

  1. Mahlzeit,

    "TypeError: evt is undefined"

    Was kann ich da tun?

    Wenn die Funktion einen Parameter erwartet, du aber keinen angibst, passiert sowas ;)

    --
    42
    1. Wenn die Funktion einen Parameter erwartet, du aber keinen angibst, passiert sowas ;)

      Aber solche Event-Funktionen werden doch überlicherweise so geschrieben oder? http://de.selfhtml.org/javascript/objekte/event.htm@title=(Selfhtml)

      Wenn nicht so wie sonst?

      Fabian

      1. Mahlzeit,

        Aber solche Event-Funktionen werden doch überlicherweise so geschrieben oder? http://de.selfhtml.org/javascript/objekte/event.htm@title=(Selfhtml)

        Dieser Artikel ist gefühlte 200 Jahre alt.

        Wenn nicht so wie sonst?

        Entweder übergibst du beim Aufruf einen Parameter oder du änderst deine Funktion so, dass sie keinen erwartet.

        --
        42
        1. Dieser Artikel ist gefühlte 200 Jahre alt.

          Entweder übergibst du beim Aufruf einen Parameter oder du änderst deine Funktion so, dass sie keinen erwartet.

          Bekäme ich bitte ein Beispiel wie das mit solchen Funktionen 'heute' aussieht?
              (habe einfach mal evt als Parameter weggelassen und eine Variable var evt = window.event; hingeschrieben ... war wohl keine Lösung - jetzt fliegen mir die 'TypeError: window.event is undefined' nur so um die Ohren)

          Fabian

  2. Meine Herren!

    <input type="text" onKeyUp="checkEnter();">

    Der EventHandler (checkEnter) wird hier ohne Parameter aufgerufen. Ich würde den EventHandler auch gar nicht im HTML registrieren, sondern mit JavaScript selbst. Das entspricht eher einer guten Trennung von Inhalt und Verhalten.

    HTML
    <input id="meinInput">

    JavaScript

    var inputElement = document.getElementById('meinInput');  
      
    inputElement.onkeyup = checkEnter;  
      
    // Oder noch schöner  
      
    inputElement.addEventListener('keyup', checkEnter );
    

    Wie du siehst, wird die Funktion checkEnter im Code gar nicht aufgerufen. Das macht der Browser aber automatisch, wenn das Event ausgelöst wird und wenn er das macht ruft er die Funtkion mit dem Ereignis-Objekt als Parameter auf. Unter der Haube passiert also sinngemäß irgendwo sowas: checkEnter( keyUpEvent );

    Im übrigen solltest du zweimal darüber nachdenken, ob du Standard-Funktionalität von Formular-Feldern anrühren möchtest. Viele Nutzer (mich eingeschlossen) reagieren darauf allergisch – in einigen Fällen ist aber sinnvoll. Du solltest dir die Frage stellen, was der Nutzer erwarten würde, wenn er die Enter-Taste drückt. In den meisten Fällen erwartet er wohl, dass das Formular abgeschickt wird.

    --
    “All right, then, I'll go to hell.” – Huck Finn
    1. var inputElement = document.getElementById('meinInput');

      inputElement.addEventListener('keyup', checkEnter );

        
      Also.. jetzt check ich was nicht.  
      Habe meinen Code jetzt umgestaltet und das Event onKeyUp mit addEventListener in's Javascript geschrieben. Jetzt funktioniert das Event sogar.. (und zwar mit derselben Funktion die M. und die Firefox Konsole bemängelt haben  (Die Konsole schweigt jetzt...)):  
      ~~~javascript
        
      function checkEnter(evt)  
      {  
      if (!evt)  
        evt = window.event;  
      if (evt.keyCode == 13)  
        {  
        alert('Enter');  
        return false;  
        }  
      }  
      
      

      Zum Schluss möchte ich noch einmal auch diese Funktion eingehen. M. hat den Selfhtml Artikel ja beinahe als 'mittelalterlich' beschrieben. Also ich kenne nur diesen Weg mit einem Parameter der nicht gesetzt wird aber dann durch if (!evt) dem window.event zugewiesen wird.  (Frage nebenbei: wieso nicht einfach den Parameter und if (!evt) ~~   weglassen und einfach if (window.event.~~   schreiben?)
      Wie sähe denn so eine Funktion nach M.'s Beschreibung aus?
      "Entweder übergibst du beim Aufruf einen Parameter oder du änderst deine Funktion so, dass sie keinen erwartet."

      Fabian

      1. Hallo,

        Habe meinen Code jetzt umgestaltet und das Event onKeyUp mit addEventListener in's Javascript geschrieben.

        'keyup', bitte. In Kleinbuchstaben und ohne 'on'. Im Code steht's ja auch richtig.

        Jetzt funktioniert das Event sogar.. (und zwar mit derselben Funktion die M. und die Firefox Konsole bemängelt haben  (Die Konsole schweigt jetzt...)):

        Was ja nach der Erklärung von 1UP auch logisch und nachvollziehbar ist, oder nicht?

        function checkEnter(evt)

        {
        if (!evt)
          evt = window.event;
        if (evt.keyCode == 13)
          {
          alert('Enter');
          return false;
          }
        }

        
        >   
        > Zum Schluss möchte ich noch einmal auch diese Funktion eingehen. M. hat den Selfhtml Artikel ja beinahe als 'mittelalterlich' beschrieben. Also ich kenne nur diesen Weg mit einem Parameter der nicht gesetzt wird aber dann durch if (!evt) dem window.event zugewiesen wird.  (Frage nebenbei: wieso nicht einfach den Parameter und if (!evt) ~~   weglassen und einfach if (window.event.~~   schreiben?)  
          
        Weil window.event nur in alten IEs existiert, die hier eine "Exotenlösung" realisiert haben: Alte IEs haben das Event als globales Objekt an window gebunden, während es die anderen als Parameter übergeben.  
          
        Ciao,  
         Martin  
        
        -- 
        F: Wer ist der Herrscher über Wasser, Wind und Wellen?  
        A: Der Friseur.  
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        
      2. Meine Herren!

        var inputElement = document.getElementById('meinInput');

        inputElement.addEventListener('keyup', checkEnter );

        
        >   
        > Also.. jetzt check ich was nicht.  
        > Habe meinen Code jetzt umgestaltet und das Event onKeyUp mit addEventListener in's Javascript geschrieben. Jetzt funktioniert das Event sogar.  
          
        Ja, weil die Funkion auf diese Weise vom Browser automatisch mit einem Parameter aufgerufen wird. Das passiert alles vom Programmier versteckt. Man sagt dem Browser nur welche Funktion er aufrufen soll (addEventListener), den eigentlichen Funktionsaufruf macht dann der Browser. Und der ruft die Funktion dann \_mit\_ Parameter auf.  
          
        
        > Also ich kenne nur diesen Weg mit einem Parameter der nicht gesetzt wird aber dann durch if (!evt) dem window.event zugewiesen wird.  
          
        Das `if (!evt) evt = window.event;`{:.language-javascript} ist Hack, den alte InternetExplorer gebraucht haben. Bei InternetExplorern war es nämlich so, dass das Event nicht als Parameter übermittelt wurde, stattdessen wurde eine globale Variable `event`{:.language-javascript} benutzt. In JavaScript können sind globale Variablen das gleiche wie Eigenschaften des window-Objekts. Deswegen kann man immer, wenn man eine globale Variable benutzt, statt `meineGlobaleVariable`{:.language-javascript} auch `window.meineGlobaleVariable`{:.language-javascript} schreiben.  
          
        
        > (Frage nebenbei: wieso nicht einfach den Parameter und if (!evt) ~~   weglassen und einfach if (window.event.~~   schreiben?)  
          
        Weil der Weg über die globale Variable veraltet ist. Ein Funktionsparameter ist die neuere und saubere Variante.  
        
        -- 
        “All right, then, I'll go to hell.” – Huck Finn
        
        1. Erstmal ein großes Dankeschön! Das hat schon einige Fragen beantwortet.

          Um sicherzugehen dass ich es jetzt kapiert habe eine allerletzte Frage:

          Weil der Weg über die globale Variable veraltet ist. Ein Funktionsparameter ist die neuere und saubere Variante.

          Sähe die "neuere und saubere Variante" so aus? :

            
          window.onload = function() {  
              document.getElementById('meinInput').addEventListener('click', meinInputEvent);  
          };  
            
          function meinInputEvent(e)  
          {  
          // Für Leute die einen veralteten Internet Explorer haben  
          e = e || window.event;  
            
          // Eigentliche Funktion  
          if (e.keyCode == 13)  
            {  
            alert('Du hast auf Enter geklickt');  
            return false;  
            }  
          }  
          
          

          Ich hoffe das ist jetzt die "moderne Variante" sonst bitte korrigieren.

          Fabian

          1. Hallo,

            window.onload = function() {

            document.getElementById('meinInput').addEventListener('click', meinInputEvent);
            };

            function meinInputEvent(e)
            {
            // Für Leute die einen veralteten Internet Explorer haben
            e = e || window.event;

            // Eigentliche Funktion
            if (e.keyCode == 13)
              {
              alert('Du hast auf Enter geklickt');
              return false;
              }
            }

              
            das ist ganz bestimmt "sauber": Keine Vermischung von HTML und Javascript, keine globalen Variablen (bis auf den Zugriff auf window.event, der für alte IEs nötig ist). Nur ein logischer Fehler fällt auf: Du registrierst deinen Eventhandler für das click-Ereignis - ein click-Event hat aber keine (sinnvolle) Informationen in keyCode.  
            Vermutlich meintest du 'keyup' oder 'keypress' als auslösendes Event.  
              
            Und noch etwas: Der onload-Handler des window-Objekts löst erst aus, wenn auch alle untergeordneten Ressourcen (Bilder, Scripts, Stylesheets) fertig geladen sind. Das kann unter Umständen eine Weile dauern. In der Zeit ist deine Eventhandler-Funktion dann noch nicht "scharf".  
            Der pragmatische Kompromiss ist, die Initialisierung der Eventhandler nicht erst 'onload' zu machen, sondern diese eine Script-Zeile "einfach so" am Ende des Dokuments, also vor dem schließenden body-Tag zu notieren.  
              
            So long,  
             Martin  
            
            -- 
            Ein Patriot ist jemand, der bereit ist, sein Land gegen seine Regierung zu verteidigen.  
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            
            1. Nur ein logischer Fehler fällt auf: Du registrierst deinen Eventhandler für das click-Ereignis - ein click-Event hat aber keine (sinnvolle) Informationen in keyCode.
              Vermutlich meintest du 'keyup' oder 'keypress' als auslösendes Event.

              Ups, 'keyup' gedacht aber 'click' geschrieben..

              Der pragmatische Kompromiss ist, die Initialisierung der Eventhandler nicht erst 'onload' zu machen, sondern diese eine Script-Zeile "einfach so" am Ende des Dokuments, also vor dem schließenden body-Tag zu notieren.

              Alles klar. Vielen Dank für den Tipp.

              Fabian

          2. Meine Herren!

            e = e || window.event;

            Was diesen Hack angeht, hab ich mich ein wenig zu kurz gefasst. Dieser Hack wurde von dem Event-System benötigt, wie es in InternetExplorern 4-6 implementiert war. Da gab es auch input.addEventListener() noch gar nicht. Da gab es nur input.onkeyup. Wenn du dich also für das neue (Standard)Event-System entscheidest, kannst du dir diesen Hack auch sparen, denn dann entfällt die Unterstützung für die (Ur)Zeitgenossen IE4-6 sowieso. Mehr zum Thema, kann man in JavaScript The Defenitive Guide nachlesen.

            Und du solltest dich aus stilistischen Gründen für EIN Event-System entscheiden. Das hilft deinen Code in diesem Punkt konsistent zu halten.

            du könntest statt dem hier:

            window.onload = function() {  
                document.getElementById('meinInput').addEventListener('keyup', meinInputEvent);  
            };
            

            das hier benutzen:

            window.addEventListener('load', function() {  
                document.getElementById('meinInput').addEventListener('keyup', meinInputEvent);  
            });
            

            Oder, in Hinblick auf Martins Kritik, auch das hier:

            document.addEventListener('DOMContentLoaded', function() {  
                document.getElementById('meinInput').addEventListener('click', meinInputEvent);  
            });
            

            Das DOMContentLoaded-Ereignis wird ausgelöst, nachdem der ganze HTML-Quelltext geparst wurde. Im Gegensatz zu dem load-Ereignis wird nicht zusätzlich darauf gewartetet, dass alle Bilder und andere Resourcen vollständig runtergeladen sind.

            Das Skript am Ende des Dokuments zu platzieren macht aber auch aus anderen, praktischen Gründen Sinn: Das Rendering der Seite wird nämlich unterbrochen, wenn der Browser beim Parsen über einen JavaScript-Quelltext stößt. Wenn man den Browser bei diesem Vorgang so spät wie möglich unterbricht, bekommt der Nutzer schon früher etwas zu sehen.

            --
            “All right, then, I'll go to hell.” – Huck Finn