J. Nanninga: DOM-kompatibles "attachEvent"

In Mozilla klappt folgender Code einwandfrei, im MSIE 6 nicht. Was soll der Code machen? Wenn der User in ein <input type="text" /> fokussiert, soll der Text darin verschwinden, wenn er es verlässt, soll der alte Text erscheinen oder der neu eingetragene bleiben.
Jedes dieser inputs hat eine id und ein value, die immer gleich sind.

var ids = new Array("name","password",...); // die ids der inputs, die einen event kriegen sollen.

for(i = 0;i < ids.length;i++) { //die ids werden einzeln durchgegangen
  if(document.getElementById(ids[i])) { // hier geht's für Mozilla weiter
    if(document.getElementById(ids[i]).addEventListener) {
      document.getElementById(ids[i]).addEventListener("focus",ci,true); // Event wirt "geaddet"
      document.getElementById(ids[i]).addEventListener("blur",co,true);
    } else {
      if(document.getElementById(ids[i]).attachEvent) { // hier geht's für MSIE weiter
        document.getElementById(ids[i]).attachEvent("focus",ci); // Event wird "attacht" (dies scheint auch zu funktionieren, denn attachEvent gibt hier - ich habs getestet - true zurück.
        document.getElementById(ids[i]).attachEvent("blur",co);
      }
    }
  }
}

function ci() {
  if(this.value == this.id) // hier könnte der Fehler liegen. Ich weiß, this an dieser Stelle ist zumindest heikel.. hilft event.srcElement ?
    this.value = ""; // Inhalt wird auf "" gesetzt. Hierdurch entsteht ünrigens ein weiterer Bug - diesmal in Mozilla: die AutoComplete-Funktion von Mozilla kommt offenbar nicht mit auf diese Art geleerten Feldern zurecht...
}

function co() {
  if(this.value == "")
    this.value = this.id; // Inhalt wird, wenn er nicht geändert wurde, wieder auf den Ursprungswert gesetzt.
}

Wie gesagt, bei Mozilla (Firefox und Firebird) funktionierts astrein. In MSIE dagegen passiert einfach nichts! Selbst, wenn in der Funktion co() nur alert("lol"); steht.. dies wird dann wahllos beim Laden der Seite ausgelöst..
Zum Schluss: Es muss DOM-kompatibel bleiben, also nix mit onFocus oder onBlur :)

  1. Hallo J.,

    In Mozilla klappt folgender Code einwandfrei, im MSIE 6 nicht. Was soll der Code machen? Wenn der User in ein <input type="text" /> fokussiert, soll der Text darin verschwinden, wenn er es verlässt, soll der alte Text erscheinen oder der neu eingetragene bleiben.
    Jedes dieser inputs hat eine id und ein value, die immer gleich sind.

    defaultValue existiert... http://selfhtml.teamone.de/javascript/objekte/elements.htm#default_value

    Ich würde es so lösen:

    <html>
    <head>
    <script type="text/javascript">

    var ids=new Array('a', 'b', 'c');

    function ci (e) {
     if (!e) var e=window.event; // gemäß DOM ist das Event-Objekt im Funktionsparameter e, im MSIE stattdessen in window.event
     elem=(e.srcElement) ? e.srcElement : e.target; // srcElement für MSIE, target für W3C-DOM-Browser
     if (elem.value==elem.defaultValue) elem.value='';
    }

    function co (e) {
     if (!e) var e=window.event;
     elem=(e.srcElement) ? e.srcElement : e.target;
     if (elem.value=='') elem.value=elem.defaultValue;
    }

    function init () {
     for (i=0; i<ids.length; i++) {
        if (elem=document.getElementById(ids[i])) { // getElementById muss nur einmal ausgeführt werden
           if (elem.addEventListener) {
              elem.addEventListener("focus", ci, true);
              elem.addEventListener("blur", co, true);
           } else {
              if (elem.attachEvent) {
                 elem.attachEvent("onfocus", ci); // mit »on« im Eventnamen
                 elem.attachEvent("onblur", co);
              }
           }
        }
     }
    }
    window.onload=init; // hier wäre natürlich wieder attachEvent/addEventListener möglich, wenn du darauf bestehst
    </script>
    </head>
    <body>

    <form action="bla">
    <p><input type="text" name="a" id="a" value="text1" /></p>
    <p><input type="text" name="b" id="b" value="text2" /></p>
    <p><input type="text" name="c" id="c" value="text3" /></p>
    </form>

    </body>
    </html>

    Siehe insgesamt http://www.quirksmode.org/js/contents.html#events ff. (hilft einem sehr weiter!)

    if(this.value == this.id) // hier könnte der Fehler liegen. Ich weiß, this an dieser Stelle ist zumindest heikel.. hilft event.srcElement ?

    Ja, srcElement hilft. Und für W3C-DOM-kompatible Browser würde ich event.target statt this verwenden.

    Wie gesagt, bei Mozilla (Firefox und Firebird) funktionierts astrein. In MSIE dagegen passiert einfach nichts!

    Das ist klar, für den MSIE musst du die Eventnamen mit »on« davor notieren und this als Verweis auf das Element, das den Event ausgelöst hat, versteht er auch nicht.

    Selbst, wenn in der Funktion co() nur alert("lol"); steht.. dies wird dann wahllos beim Laden der Seite ausgelöst..

    Hm, das verstehe ich nicht.

    Zum Schluss: Es muss DOM-kompatibel bleiben, also nix mit onFocus oder onBlur :)

    Wieso? Old-School-mäßig ohne attachEvent/addEventListener wäre es viel kompatibler.

    Mathias

    1. Eine Ergänzung:

      elem.addEventListener("focus", ci, true);
                elem.addEventListener("blur", co, true);

      Opera 7 sollte Event Capturing und Bubbling (siehe http://www.quirksmode.org/js/events_order.html) eigentlich richtig unterscheiden, sodass es sowohl mit true als auch false als dritten Parameter funktionieren sollte, schließlich ist die Event-Reihenfolge hier nicht relevant. Komischerweise macht Opera eine Ausnahme für Formularfelder: Der Event wird bei true (= Event feuert in der Bubbling-Phase) gar nicht gefeuert. Mit false funktioniert es aber. Also würde ich vorschlagen, hier jeweils false zu notieren. Es sollte abgesehen von diesem Opera-Problem keinen Unterschied machen, es sei denn, du hast noch andere Events, die in einer bestimmten Reihenfolge ausgelöst werden müssen, und du hast absichtlich true gewählt.

      Mathias

      1. Moin,

        Komischerweise macht Opera eine Ausnahme für Formularfelder: Der Event wird bei true (= Event feuert in der Bubbling-Phase) gar nicht gefeuert.

        Nitpick: der dritte Parameter von addEventListener() trägt den Namen useCapture und true bedeutet, dass das Event in der Capture-Phase feuern soll, false heisst Bubble-Phase.

        --
        Henryk Plötz
        Grüße aus Berlin
        ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
        ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~