wiberg: DOM für IE7: dynamisch attribute setzen

Hi,

ich habe ein Problem mit IE7 (FF funktioniert). Ich kann alle Attribute außer 'name="lol"' dynamisch erstellen. Hier ist die vereinfachte Funktion (Habe hier die wesentlichen Teile gepastet. Die Funktion vereinfach das DOM für mich, weil man nicht mehr für jedes Element so viele Schritte ausführen muss):

function addElement(foo, attributesStr) {
  var newElement = document.createElement(foo);

// ... //

if(attributesStr != null) {

// Hier wird der attributesStr zerlegt, spielt hier keine Rolle...

for(var i = 0; i < attributes.length; ++i) {
      attributes[i] = new Array(tmp[0],tmp[1]);
      newAttribute = document.createAttribute(attributes[i][0]);
      newAttribute.nodeValue = attributes[i][1];
      newElement.setAttributeNode(newAttribute);  // <-- IE7: Nicht implementiert. (?!)
    }
  }

// ... //

where.appendChild(newElement);
}

Das komische: IE7 erstellt trotzdem dynamisch fast alles, was ich will, außer das Attribut "name". Ich kann zum Beispiel folgendes tun:
createElement("div", "foo::bar"); // in HTML: <div foo="bar"></div>
Aber folgendes nicht:
createElement("input", "foo::bar#name::mode#id::mode"); // in HTML: <input foo="bar" id="mode" />

"name" ist kein reserviertes Wort. Für ein funktionierendes Formular brauche ich natürlich "name". Woran könnte es liegen?

  1. hi,

    ich habe ein Problem mit IE7 (FF funktioniert). Ich kann alle Attribute außer 'name="lol"' dynamisch erstellen.

    Das komische: IE7 erstellt trotzdem dynamisch fast alles, was ich will, außer das Attribut "name". Ich kann zum Beispiel folgendes tun:
    createElement("div", "foo::bar"); // in HTML: <div foo="bar"></div>
    Aber folgendes nicht:
    createElement("input", "foo::bar#name::mode#id::mode"); // in HTML: <input foo="bar" id="mode" />

    "name" ist kein reserviertes Wort. Für ein funktionierendes Formular brauche ich natürlich "name". Woran könnte es liegen?

    Am IE.
    Der nimmt dynamisch generierte Elemente nicht in die elements-NodeList auf.

    Lass dir mal innerHTML ausgeben, ob der name da mit drinsteht.
    Und prüfe, ob das Versenden trotzdem klappt. Weiss ich atm nicht.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Am IE.
      Der nimmt dynamisch generierte Elemente nicht in die elements-NodeList auf.

      lol. Wieso nicht?! Kann man die NodeList irgendwie refreshen oder so?

      Lass dir mal innerHTML ausgeben, ob der name da mit drinsteht.
      Und prüfe, ob das Versenden trotzdem klappt. Weiss ich atm nicht.

      bei innerHTML sind die name-Attribute auch nicht drin. Wie kann das angehen? Wie soll man denn da dynamisch was machen?

      OK, vielleicht muss ich einen anderen Ansatz wählen... Wie macht man das denn sonst so, ein dynamisch generiertes Formular?

      gruß,
      wahsaga

      Danke!
      Gruß zurück,
      Wiberg

      1. Hallo,

        bei innerHTML sind die name-Attribute auch nicht drin. Wie kann das angehen? Wie soll man denn da dynamisch was machen?
        OK, vielleicht muss ich einen anderen Ansatz wählen... Wie macht man das denn sonst so, ein dynamisch generiertes Formular?

        Am Besten serverseitig.

        Ansonsten wirst du Formulare wohl oder übel mit innerHTML oder document.write() generieren müssen, wenn du den IE unterstützen musst :-(
        Andere Elemente kannst du hingegen wie gewohnt per appendChild, createElement,… erstellen.

        Übrigens machst du's dir mit createAttribute etc. eigentlich unnötig schwer. Name-Attribute könntest du z.B. auch einfach so setzen:

        Element.name = "Name_des_Elements";

        Diese Schreibweise funzt im IE natürlich auch nicht besser, aber andere Attribute könntest du auf diese Weise setzen. Beachte aber die teilweise abweichenden Schreibweisen (z.B. 'className' statt 'class').

        mfg. Daniel

        1. Hallo,

          bei innerHTML sind die name-Attribute auch nicht drin. Wie kann das angehen? Wie soll man denn da dynamisch was machen?
          OK, vielleicht muss ich einen anderen Ansatz wählen... Wie macht man das denn sonst so, ein dynamisch generiertes Formular?

          Am Besten serverseitig.

          Server seitig ist leider keine Option. Könnte ich zwar, aber geht beim Kunden halt nicht. Vielleicht werde ich auf folgende supi IE Möglichkeit zurückgreifen: Alles in HTML, style=display:none und dann dynamisch ein- und ausblenden. Es muss ja kein schöner Code sien, es muss funktionieren :)

          Ansonsten wirst du Formulare wohl oder übel mit innerHTML oder document.write() generieren müssen, wenn du den IE unterstützen musst :-(
          Andere Elemente kannst du hingegen wie gewohnt per appendChild, createElement,… erstellen.

          Übrigens machst du's dir mit createAttribute etc. eigentlich unnötig schwer. Name-Attribute könntest du z.B. auch einfach so setzen:

          Naja, meine Funktion ist ziemlich flexibel, das geht nämlich so:
          createElement("tagname, zb 'div'", "into (für 'in ein Element'), "before" oder "after", target (einen String für ein Element mit der ID 'target', "id::foo#name::bar", "textNode");
          Der vorletzte Parameter ist entscheidend, man kann unendlich viele Attribute gleich anhängen, z.B. "href::http://www.google.com/#target::_blank", das macht es echt sehr angenehm. Vielleicht nicht sooo elegant, weils ne eigene Syntax benötigt, aber angenehm und sehr schnell. Aber es muss doch noch bessere Möglichkeiten geben! Ich versuche mal, Attribute, die 'name' heißen, herauszufiltern und nachträglich mit element.name ranzuhängen.

          Element.name = "Name_des_Elements";

          Diese Schreibweise funzt im IE natürlich auch nicht besser, aber andere Attribute könntest du auf diese Weise setzen. Beachte aber die teilweise abweichenden Schreibweisen (z.B. 'className' statt 'class').

          mfg. Daniel

          Vielen Dank,
          wiberg

          1. Hallo,

            Vielleicht werde ich auf folgende supi IE Möglichkeit zurückgreifen: Alles in HTML, style=display:none und dann dynamisch ein- und ausblenden.

            Alternativ zu CSS könntest du auch folgendes machen:

            Dein Formular (Beispiel):

              
            <form action="?" id="myForm">  
            <label><input type="radio" name="rb" />Radiobutton 1</label>  
            <label><input type="radio" name="rb" />Radiobutton 2</label>  
            <label><input type="radio" name="rb" />Radiobutton 3</label>  
            </form>
            

            Onload (am besten mit window.onload in Script) machst du dann folgendes:

            var formular = document.forms.myForm.parentNode.removeChild(myForm);

            Damit wird das Formular erstmal entfernt und in eine Variable gespeichert. Ausgeben könntest du es dann z.B. so:

            document.body.appendChild(formular);

            Es muss ja kein schöner Code sien, es muss funktionieren :)

            Das ist mMn keine gute Einstellung. Außerdem solltest du darauf achten, dass die Seite auch ohne JS und/oder ohne CSS[1] bestmöglich funktioniert.

            Übrigens machst du's dir mit createAttribute etc. eigentlich unnötig schwer. Name-Attribute könntest du z.B. auch einfach so setzen:

            Naja, meine Funktion ist ziemlich flexibel, das geht nämlich so:
            createElement("tagname, zb 'div'", "into (für 'in ein Element'), "before" oder "after", target (einen String für ein Element mit der ID 'target', "id::foo#name::bar", "textNode");

            Naja, ganz so weit würde ich es nicht treiben ;-), aber etwas ähnliches habe ich mir auch mal geschrieben:

            HTMLElement.prototype.addElement = function(tagName,Attribute){  
             var el = document.createElement(tagName);  
             for (var att in Attribute){  
              el[att] = Attribute[att];  
             }  
             return this.appendChild(el);  
            }
            

            Um jetzt z.B. ein <p>-Element mit der Klasse „absatz“ und der ID „lastAbsatz“ in dem <body> zu schreiben, müsste ich die Methode so aufrufen:

            document.body.addElement("p",{className:"absatz",id:"lastAbsatz"});

            Der Nachteil an der Methode: sie funzt mal wieder im allseits geliebten IE nicht, weil dieser keinen HTMLElement-Prototyp hat (auch nichts vergleichbares). Klar könnte ich statt dessen auch eine einfache Funktion erstellen, der ich dann den Ausgabeort als Parameter mitteile, aber das würde die ganze Sache unübersichtlicher machen.

            Kurze Erklärung zu dem {x:"x"}: Das ist kein von mir ausgedachter String, sondern eine vereinfachte Möglichkeit, um Objekte zu erstellen.

            Der vorletzte Parameter ist entscheidend, man kann unendlich viele Attribute gleich anhängen, z.B. "href::http://www.google.com/#target::_blank", das macht es echt sehr angenehm. Vielleicht nicht sooo elegant, weils ne eigene Syntax benötigt, aber angenehm und sehr schnell.

            Das „sehr schnell“ bezieht sich wohl auf die Menge des Quellcodes und nicht auf die tatsächliche Verarbeitungsgeschwindigkeit[2] oder? Ich würde dafür richtige Objekte verwenden. Also lieber auch so:

            {href: "http://www.google.com/", target: "_blank"}

            Dann kannst du dir dieses ganze „Gehangel“ durch den String sparen und statt dessen einfach eine kleine for-in verwenden, um die Attribute anzuhängen. Von der Geschwindigkeit her, müsste diese Variante auf jeden Fall schneller sein, als wenn du erst einen String parsen musst.

            [1] d.h. die Seite muss dann nicht unbedingt schön bunt sein, sondern funktionieren.
            [2] Obwohl diese -zugegebener Maßen- nicht unbedingt DIE Rolle spielt.

            mfg. Daniel

            1. Hallo,

              var formular = document.forms.myForm.parentNode.removeChild(myForm);

              Oops, das war nicht ganz richtig. Du müsstest es entweder so:

              var formular = document.forms.myForm.parentNode.removeChild(document.forms.myForm);

              oder so:

                
              var formular = document.forms.myForm;  
              formular = formular.parentNode.removeChild(formular);  
              
              

              schreiben.

              mfg. Daniel

          2. hi,

            Übrigens machst du's dir mit createAttribute etc. eigentlich unnötig schwer. Name-Attribute könntest du z.B. auch einfach so setzen:

            Naja, meine Funktion ist ziemlich flexibel, das geht nämlich so:
            createElement("tagname, zb 'div'", "into (für 'in ein Element'), "before" oder "after", target (einen String für ein Element mit der ID 'target', "id::foo#name::bar", "textNode");
            Der vorletzte Parameter ist entscheidend, man kann unendlich viele Attribute gleich anhängen, z.B. "href::http://www.google.com/#target::_blank", das macht es echt sehr angenehm.

            Das zwingt dich ja trotzdem nicht zur Nutzung von createAttribute.

            element['href'] = xyz;
            element['target'] = abc;

            geht auch. Und da kannst du statt eines Textliterals natürlich auch einen variablen Wert einsetzen.

            gruß,
            wahsaga

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