Nicholas: onchange Attribut zur Laufzeit über DOM ändern geht nicht im IE

Hi,
ich hab versucht mit dem folgenden Code einem neuen Select-Element ein onchange-Attribut mit JS Funktion zu setzen. Klappt im Firefox ganz wunderbar, aber der IE tut mal gar nix und wirft nichmal ne Fehlermeldung. :(

var select = document.createElement("select");
...
attrib = document.createAttribute("onchange");
attrib.nodeValue = "update(" + id + ");";
select.setAttributeNode(attrib);
...
cell.appendChild(elementselect);

Irgendjemand ne Idee?

Nicholas

PS: Hab auch schon select.onchange = "update(" + id + ");"; probiert. Bringt leider nix...

  1. Vollvergessen:
    Geht mit einem Firefox 1.5
    Geht nicht mit IE 6.0.2800

  2. Hallo Nicholas.

    var select = document.createElement("select");

    ...
    attrib = document.createAttribute("onchange");
    attrib.nodeValue = "update(" + id + ");";
    select.setAttributeNode(attrib);

      
    Der IE weigert sich standhaft, den umständlichen Weg zu gehen, wenn es einen einfacheren gibt:  
      
    ~~~javascript
    select.onchange = function() {  
      update(id);  
    };
    

    Einen schönen Mittwoch noch.

    Gruß, Ashura

    --
    sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
    „It is required that HTML be a common language between all platforms. This implies no device-specific markup, or anything which requires control over fonts or colors, for example. This is in keeping with the SGML ideal.“
    [HTML Design Constraints: Logical Markup]
    1. Hallo,

      var select = document.createElement("select");

      ...
      attrib = document.createAttribute("onchange");
      attrib.nodeValue = "update(" + id + ");";
      select.setAttributeNode(attrib);

        
      
      > ~~~javascript
      
      select.onchange = function() {  
      
      >   update(id);  
      > };
      
      

      Achtung! Böse Falle. ;-) Die beiden Codebeispiele sind nicht identisch. Im ersten wird die Funktion update mit dem _Wert_ der Variable id als Argument aufgerufen, also bspw.: var id=5; ... attrib.nodeValue = "update(" + id + ");";, dann wird update(5) aufgerufen.

      Im zweiten Beispiel wird die Funktion update mit der Variablen id als Argument aufgerufen, also update(id). Die Variable id ist dabei, wenn sie nicht global ist, aus dem Gültigkeitsbereich der Funktion, welche das select.onchange = function() {update(id);}; ausführt.

      Eventuell muss hier also, je nach Art und Bedeutung der Variablen id, ein Function Object erzeugt werden.

      Hier mal ein Beispiel, welches den Unterschied zeigt:

        
      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  
              "http://www.w3.org/TR/html4/strict.dtd">  
      <html>  
      <head>  
      <title>Titel</title>  
      <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">  
      <script language="JavaScript">  
      <!--  
      var id = 6;  
        
      function update(id) {  
        alert(id);  
      }  
        
      function init() {  
       var a = document.forms[0].tf1  
       var b = document.forms[0].tf2  
       var id = 123;  
       a.onchange = function() {update(id);};  
       //a.onchange = new Function("update(" + id+ ")");  
        
       id = 456;  
       b.onchange = function() {update(id);};  
       //b.onchange = new Function("update(" + id+ ")");  
      }  
        
      window.onload = init;  
      //-->  
      </script>  
      </head>  
      <body>  
      <form action="#" method="get">  
      <input type="Text" name="tf1" value="" size="20" maxlength="20">  
      <input type="Text" name="tf2" value="" size="20" maxlength="20">  
      <input type="Text" name="tf3" value="" size="20" maxlength="20">  
      </form>  
      </body>  
      </html>  
      
      

      Im jetzigen Zustand wird als Wert für id _immer_ 456 übergeben werden, weil immer update(id) aufgerufen wird. Kommentiert man die .onchange = function() {update(id);}; aus und löscht die Kommentarzeichen vor .onchange = new Function("update(" + id+ ")");, dann wird bei a.onchange update(123) und bei b.onchange update(456) aufgerufen.

      viele Grüße

      Axel

      1. Ja, den Unterschied hab ich schon gemerkt...
        Da muß man auch erstmal drauf kommen... :-)

        Aber vielen Dank für die ganzen Tipps. Funktioniert jetzt gut.

        Nicholas

      2. Hallo,

        Achtung! Böse Falle. ;-) Die beiden Codebeispiele sind nicht identisch. Im ersten wird die Funktion update mit dem _Wert_ der Variable id als Argument aufgerufen, also bspw.: var id=5; ... attrib.nodeValue = "update(" + id + ");";, dann wird update(5) aufgerufen.

        Im zweiten Beispiel wird die Funktion update mit der Variablen id als Argument aufgerufen, also update(id). Die Variable id ist dabei, wenn sie nicht global ist, aus dem Gültigkeitsbereich der Funktion, welche das select.onchange = function() {update(id);}; ausführt.

        Eventuell muss hier also, je nach Art und Bedeutung der Variablen id, ein Function Object erzeugt werden.

        Kleine Erbsenzählerei:

        »new Function(...)« erzeugt genauso ein Function-Objekt wie die Function-Expresson »function (...) {...}«.

        Der Unterschied ist, dass erstere Methode keine Closure erzeugt. Sprich, die erzeugte Funktion hat keinen Zugriff auf die Variablen der Funktion, in der sie erzeugt wurde.

        <script language="JavaScript">
        <!--

        (Übrigens, bitte kein code lang=html verwenden und dann den JavaScrpt-Code durch einen Kommentar komplett ausgrauen - das ist nicht so toll lesbar. Dafür gibts code lang=javascript, das man in der anderen code-Auszeichnung verwenden kann.)

        function init() {

        var a = document.forms[0].tf1
        var b = document.forms[0].tf2
        var id = 123;
        a.onchange = function() {update(id);};
        //a.onchange = new Function("update(" + id+ ")");

        id = 456;
        b.onchange = function() {update(id);};
        //b.onchange = new Function("update(" + id+ ")");
        }

          
        Genau, die erste Notation erzeugt eine [Closure](http://blog.morrisjohns.com/javascript_closures_for_dummies), die zweite jeweils nicht.  
          
        Die Variable id in den erzeugten onchange-Funktionen und die in der init-Funktion sind identisch, sie verweisen intern auf dieselbe Speicherstelle - auch nach dem Ablauf der init-Funktion.  
          
        Ein anderes Beispiel:  
          
        ~~~html
        <script type="text/javascript">  
        [code lang=javascript]function init () {  
         var i = 0;  
         document.getElementById("button1").onclick = function () {  
          alert(i);  
          i++  
         };  
         document.getElementById("button2").onclick = function () {  
          alert(i);  
          i++  
         };  
         i = 1;  
        }  
        window.onload = init;
        

        </script>
        <button id="button1">A</button>
        <button id="button2">B</button>[/code]

        (Das doppelte Notieren der Funktion ist nicht nötig, hier zur Anschaulichkeit.)

        Das kann man sich nicht erklären, ohne Closures zu verstehen. i ist keine globale Variable, aber beide Funktionen haben auf ein und dieselbe i-Variable Zugriff. Und der Wert beim ersten Ausführen ist der Wert, den die Variable am Ende der Funktion hatte, in der die Closure notiert wurde.

        Mathias