Felix Riesterer: / (BROWSER) name- und id-Werte-Konflikt im IE

Liebe Spezialisten,

bei der Arbeit an meinem Artikel bin ich auf diese Seite gestoßen, die folgenden Bug im IE beschreibt:

Hat man zwei verschiedene HTML-Elemente, von denen das eine ein name-Attribut (z.B. name="wert") und ein anderes ein ID-Attribut mit jeweils demselben Inhalt hat (also id="wert"), dann liefert document.getElementById("wert") nicht unbedingt wie gewünscht das Element mit der passenden ID, sondern fälschlicherweise das HTML-Element mit einem passenden Wert im name-Attribut, das im Dokument an vorausgehender Stelle notiert ist.

Gibt es dazu sichere Workarounds? Bleibt nur der Hinweis darauf, dass man tunlichst sowohl name-, als auch ID-Attribute mit dokumentweit einmaligen Werten versieht, ja am besten auf das name-Attribut zugunsten des id-Attributes komplett verzichtet?

Liebe Grüße,

Felix Riesterer.

--
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  1. Mahlzeit Felix Riesterer,

    Bleibt nur der Hinweis darauf, dass man tunlichst sowohl name-, als auch ID-Attribute mit dokumentweit einmaligen Werten versieht, ja am besten auf das name-Attribut zugunsten des id-Attributes komplett verzichtet?

    Ersteres ja. Letzteres würde ich nicht tun - AFAIK funktionieren Formular dann nicht mehr ... oder wird dann etwas alternativ der Wert aus dem "id"-Attribut genommen? Ich denke nicht ...

    MfG,
    EKKi

    --
    sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
    1. Lieber EKKi,

      Bleibt nur der Hinweis darauf, dass man tunlichst sowohl name-, als auch ID-Attribute mit dokumentweit einmaligen Werten versieht

      |

      Ersteres ja.

      OK. Dann formuliere ich um:

      , ja am besten

      Am besten ist es, man vergibt immer name- und ID-Attribut zusammen an ein HTML-Element, wobei bei Formularfeldern mit der ID sorgsamer umgegangen werden muss, da manche Formularfelder (Radio-Buttons oder Checkboxen) manchmal gemeinsam ein identisches name-Attribut brauchen, die aber dann keinesfalls alle auch ein identisches ID-Attribut gemeinsam haben dürfen.

      Kommt das jetzt so hin?

      Liebe Grüße,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      1. Mahlzeit Felix Riesterer,

        Kommt das jetzt so hin?

        Perfekt ... genauso mache ich es auch. ;-)

        MfG,
        EKKi

        --
        sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
  2. Liebe Spezialisten,
    Hat man zwei verschiedene HTML-Elemente, von denen das eine ein name-Attribut (z.B. name="wert") und ein anderes ein ID-Attribut mit jeweils demselben Inhalt hat (also id="wert"), dann liefert document.getElementById("wert") nicht unbedingt wie gewünscht das Element mit der passenden ID, sondern fälschlicherweise das HTML-Element mit einem passenden Wert im name-Attribut, das im Dokument an vorausgehender Stelle notiert ist.

    Tatsache. Hatte wohl noch nie den Fall, ist ja interessant konnte es gerade mal reproduzieren.

    Anscheinend nimmt er aber immer das erste im Dokument auftauchende. Sprich, hat man z.B.

    <input type="text" id="Wert" value="Wertrichtig">
    <input type="text" name="Wert" value="Wertfalsch">

    macht er es richtig, aber bei

    <input type="text" name="Wert" value="Wertfalsch">
    <input type="text" id="Wert" value="Wertrichtig">

    schnappt er sich den falschen.

    Bestimmt nur ein Feature vom IE ;) damit die alten Hasen die immer nur name verwenden auch mit dem getElementById arbeiten können.

    Hahaha

  3. gruss Felix,

    Hat man zwei verschiedene HTML - Elemente, von denen das eine ein
    name-Attribut (z.B. name="wert") und ein anderes ein ID-Attribut
    mit jeweils demselben Inhalt hat (also id="wert"), dann liefert
    document.getElementById("wert") nicht unbedingt wie gewünscht das
    Element mit der passenden ID, sondern fälschlicherweise das HTML-
    Element mit einem passenden Wert im name-Attribut, das im Dokument
    an vorausgehender Stelle notiert ist.
    Gibt es dazu sichere Workarounds? ...

    keine ahnung, man koennte sich aber einen ebensolchen bauen.

    wie ueblich der hinweis auf die [http://jconsole.com], in die
    der folgende code zur machbarkeitdemonstration hineinkopiert
    und ausgefuehrt werden sollte:

    //  [Array.generics.iterators.accessors]      - [http://www.pseliger.de/jsExtendedApi/jsApi.Array.mozGenerics.dev.js] september 23-2006:  
    Array.filter = function (obj, fct) {var arr=[];if(typeof fct=="function"){var i,l=(((obj instanceof Array)||((typeof obj.length=="number")&&((typeof obj.item=="function")||(typeof obj.item=="object")||(typeof obj.item=="string")||(obj instanceof window.NodeList)||(obj instanceof window.HTMLCollection))))?(obj.length):(obj.length||0));for(i=0;i<l;++i){if(fct.call(null,(obj[i]||obj.item(i)),i,obj)){arr.push(obj[i]||obj.item(i));}}}return arr;};  
      
      
    (function () {  
      
      
      var sh = (window || this);  // sh : scripting host.  
      var dc = sh.document;        // dc : document.  
      
    //var LNL = dc.getElementsByTagName("*"); // create a *live node list*.  
    //print("LNL.length : " + LNL.length);  
      
      
    //sh.HTMLCollection = (((typeof sh.HTMLCollection != "function") && ((typeof sh.HTMLCollection != "object") || !sh.HTMLCollection))?( { } ):(sh.HTMLCollection));  
      sh.NodeList = (((typeof sh.NodeList!="function")&&((typeof sh.NodeList!="object")||!sh.NodeList))?({}):(sh.NodeList));  
      sh.Node = (((typeof sh.Node!="function")&&((typeof sh.Node!="object")||!sh.Node))?({}):(sh.Node));  
      
      
      dc.getElementById = (function (coreFctById) {  
      
        return (function (str) {  
      
          str = String(str);  
      
        //return coreFctById(str);  
      
        //print("LNL.length : " + LNL.length);  
        //return Array.filter((LNL || document.getElementsByTagName("*")), (function (elm) {  
          return Array.filter(document.getElementsByTagName("*"), (function (elm) {  
      
            return (elm && (typeof elm.id == "string") && (elm.id == str));  
          }))[0];  
        });  
      
      })(dc.getElementById);  
      
      
      delete sh;  
      delete dc;  
      delete arguments.callee;  
      
    })();  
      
    print("document.getElementById : " + document.getElementById);  
    var myElm = document.getElementById("output");  
    print("myElm.id : " + myElm.id);
    

    viel erfolg - peterS. - pseliger@gmx.net

    --
    »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
    Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
    ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
    1. hallo again in die runde, ...

      ... wobei mir gerade einfaellt, dass wenn alle browser mit der referenzierung
      und der lebenserhaltung der LNL(live node list) zurechtkommen, im naechst-
      folgenden schritt ueberprueft werden muss, ob sich das ergebnis dann nicht
      auch direkt mit LNL[str] abgreifen laesst - wenn dem so waere, sparte man
      sich auch gleich noch den ganzen filterprozess und koennte einfach so im
      vorbeigehen vielleicht sogar ein im vergleich zum im DOM implementierten
      schnelleres [getElementById] geschrieben haben. dafuer muesste man aber
      noch 'nen performance-test hinterherschieben.

      so long - peterS. - pseliger@gmx.net

      --
      »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
      Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
      ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
      1. hallo ich schon wieder ...

        das nun viel schlanker daherkommende aber eben noch
        zu testende baby sieht dann folgendermassen aus:

        (function () {  
          
          
          var LNL = document.getElementsByTagName("*");  
          
          
          document.getElementById = (function (coreFctById) {  
          
            return (function (str) {  
          
              return LNL[String(str)];  
            });  
          
          })(document.getElementById);  
          
          
        })();  
          
        print("document.getElementById : " + document.getElementById);  
        var myElm = document.getElementById("output");  
        print("myElm.id : " + myElm.id);
        

        so ... bitte uebernehmen .. ich bin erstmal weg.

        so long - peterS. - pseliger@gmx.net

        --
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
        ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
        1. Hallo,

          return LNL[String(str)];

          Das läuft m.W. auf namedItem hinaus. Aber macht namedItem nicht genau das, was man nicht will, nämlich nach name- und id-Attribut suchen? Oder habe ich hier die Intention missverstanden?

          Mathias

          1. hallo Mathias,

            return LNL[String(str)];

            Das läuft m.W. auf namedItem hinaus. Aber macht namedItem nicht genau das,
            was man nicht will, nämlich nach name- und id-Attribut suchen? Oder habe
            ich hier die Intention missverstanden?

            nein, Du hast die dahintersteckende Absicht voll erkannt. aber weil ich die
            spezifikationen nun mal nicht auswendig dahersagen kann und auch nicht die
            lust hatte, die zeit zum nachlesen aufzubringen, wollte ich das testing dem
            OP oder anderen ueberlassen und schrieb daher auch zwei postings zuvor:

            ... wobei mir gerade einfaellt, dass wenn alle browser mit der
            referenzierung und der lebenserhaltung der LNL(live node list)
            zurechtkommen, im naechstfolgenden schritt ueberprueft werden
            muss, ob sich das ergebnis dann nicht auch direkt mit LNL[str]
            abgreifen laesst ...

            so long - peterS. - pseliger@gmx.net

            --
            »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
            Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
            ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
          2. gruss Mathias,

              
            
            > >       return LNL[String(str)];  
            
            

            Das läuft m.W. auf namedItem hinaus. Aber macht namedItem nicht genau das,
            was man nicht will, nämlich nach name- und id-Attribut suchen? Oder habe
            ich hier die Intention missverstanden?

            ich hab's jetzt mal getestet - die bequem gedachte abkuerzung ueber
            »return LNL[String(str)];« entspricht tatsaechlich »namedItem« und
            entfaellt damit als loesung. es bleibt aber immer noch der zuerst
            vorgestellte patch ueber »Array.filter«.

            so long - peterS. - pseliger@gmx.net

            --
            »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
            Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
            ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]