Chris: [object HTMLliElement] ie streikt

Hi.

Wenn man Stunden damit verbringt einen kleinen für einem völlig sinnlosen Fehler zu suchen und einfach nichts findet, wendet man sich hoffnungsvoll an eine Forum.

Ich lade li Objekte mit weiterem HTML code darin aus einer ArrayList und stelle diese in dreier Schritten dar. Bei initialisierung der Seite werden im ie und im ff die ersten drei Elemente der ArrayList ohne Probleme dargestellt. Sobald ich aber ein zweites mal die selben Elemente aufzurufen versuche (mache dies mit einer links rechts Pfeil-Navi...) und die entsprechenden Indexe der ArrayList abfrage. Gibt diese mir im IE zwar ein Objekt zurück, ich kann es aber nicht mit appendChild einem anderen Objekt hinzufügen. FF klappt ohne prob.

Ich denke bis jetzt hat noch niemand begriffen, was mein Problem ist.

Eigentlich kann man obenstehendes vernachlässigen.

Die arrListS enthält N htmlObjekte mit folgendem Inhalt:
<li id="slide_2"><div class="selectorDiv" id="divHSERVER_2" onclick="selectTipSERVER(2);"> <b>192.168.3.123</b><br /><b>[ Obelix ]</b><br />UNIXSOLARIS</div></li>

var myNodeB = arrListS.get(nextNode);
ulContainer.appendChild(myNodeB);

im FF alert(myNodeB.innerHTML) = HTML Code alles OK
im IE alert(myNodeB.innerHTML) = nichts leer

im FF ulContainer.appendChild(myNodeB) = neues element in ulContainer
im IE ulContainer.appendChild(myNodeB) = <li id="slide_2">ohne inhalt</li> element im ulContainer

wenn ich myNodeB.childNodes[0].id mache erhalte ich im IE divHSERVER_2 was absolut korrekt ist. Ich kann also manuell auf die Knotenstruktur des Objektes zugreiffen, dieses jedoch nicht als ganze Einheit mit appendChild an ein anderes Objekt übergeben.

Ich kann mir nicht erklären was das Problem ist. Muss ich vielleich das Objekt Klonen oder neu parsen oder noch schlimmer manuel alle Kinder mit deren attributen durchlaufen und danach ein neues Objekt kreieren?

Kann mir jemand kritische Fragen stellen, damit ich vielleicht auf das Problem komme, oder wenns geht vielleicht sogar einen Tipp geben?

Daaaanke

  1. Lieber Chris,

    Ich denke bis jetzt hat noch niemand begriffen, was mein Problem ist.

    richtig.

    Eigentlich kann man obenstehendes vernachlässigen.

    Warum schreibst Du es dann?

    Die arrListS enthält N htmlObjekte mit folgendem Inhalt:
    <li id="slide_2"><div class="selectorDiv" id="divHSERVER_2" onclick="selectTipSERVER(2);"> <b>192.168.3.123</b><br /><b>[ Obelix ]</b><br />UNIXSOLARIS</div></li>

    Ich lese hier HTML-Code, der gut auch ein String sein kann. Von daher weiß ich nicht wirklich, ob arrListS tatsächlich HTML-Objekte enthält. Zumal diese <li>-Elemente als innerHTML kein <li>-Tag besitzen!

    Übrigens: Woher kommen diese "htmlObjekte"? Waren die zuvor aus dem Dokument referenziert worden (wo sie auch stehen), oder hast Du die alle per document.createElement() erstellt?

    var myNodeB = arrListS.get(nextNode);

    Was ist nextNode? Ist das ein Objekt oder ein numerischer Wert? Wird aus Deinem Beispiel nicht klar!

    ulContainer.appendChild(myNodeB);

    im FF alert(myNodeB.innerHTML) = HTML Code alles OK
    im IE alert(myNodeB.innerHTML) = nichts leer

    Das unterschiedliche Verhalten im IE mag daher rühren, dass Deine arrListS-Inhalte eben keine ordnungsgemäß erstellten Listen-Elemente sind. Ich habe auch festgestellt, dass man im IE immer genau aufpassen muss, in welchem document-Objekt (z.B. bei Frames hat man eventuell mehrere zur Auswahl) man ein HTML-Element created hat. Ich hatte schon den Fall, dass ich im Iframe ein HTML-Element dynamisch erzeugen und einhängen wollte, was im FF problemlos gelang, im IE aber nicht, da ich mit "document.createElement()" aus dem parentFrame ein HTML-Element erzeugt hatte, das mich der IE aber nicht im document des Iframes einhängen lassen wollte.

    im FF ulContainer.appendChild(myNodeB) = neues element in ulContainer
    im IE ulContainer.appendChild(myNodeB) = <li id="slide_2">ohne inhalt</li> element im ulContainer

    Nicht gerade nachvollziehbar, aber vielleicht gibt es eine Erklärung, wenn Du endlich verrätst, wie die li-Elementobjekte entstanden sind (vor allem wo!) und wo das ul-Elementobjekt ist, in welches sie eingehängt werden sollen.

    wenn ich myNodeB.childNodes[0].id mache erhalte ich im IE divHSERVER_2 was absolut korrekt ist. Ich kann also manuell auf die Knotenstruktur des Objektes zugreiffen, dieses jedoch nicht als ganze Einheit mit appendChild an ein anderes Objekt übergeben.

    Das kommt darauf an, was in arrListS steht. Im IE steht da offensichtlich nicht wirklich alles, sondern nur die Hülle eines li-Elementobjektes.

    Du hast nicht zufällig ein Testbeispiel, das man online begutachten könnte?

    Liebe Grüße aus Ellwangen,

    Felix Riesterer.

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

      Danke für deine Antwort. Ich versuche mal darauf einzugehen.

      Übrigens: Woher kommen diese "htmlObjekte"? Waren die zuvor aus dem Dokument referenziert worden (wo sie auch stehen), oder hast Du die alle per document.createElement() erstellt?

      function initArrayListS(intID) {
        arrListS = new ArrayList();
        var getListNodes = document.getElementById('serveritemCarrier');
        if(getListNodes) {
          for(var i=0;i<getListNodes.childNodes.length;i++) {
            if(getListNodes.childNodes[i].id) {
              if(getListNodes.childNodes[i].id.split("_")[0] == "slide") {
                arrListS.add(getListNodes.childNodes[i]);
                getListNodes.removeChild(getListNodes.childNodes[i]);
                i=i-1;
              }
            }
          }

      }

      displayListS(actFirstNodeS);
      }

      Das UL Element mit der id="serveritemCarrier" wird durch eine Ajax Funktion beim Laden der Seite gefüllt. Sagen wir mal mit 10 LI elementen mit Inhalt.

      Ich entferne also objekt für objekt aus diesem UL und fürge diese als HTMLli objekte in die ArrayList ein.

      var myNodeB = arrListS.get(nextNode);

      Was ist nextNode? Ist das ein Objekt oder ein numerischer Wert? Wird aus Deinem Beispiel nicht klar!

      ich habe eine art slideshow wo nur 3 elemente dargestellt werden. das heisst alle 10 sind im array aber jeweils nur 3 sicht bar und ich kann mit navigation von links nach rechts durch das array navigieren und entsprechend die richtigen elemente anzeigen.

      //actFirstNodeS = position im array an der gestartet wird

      function displayListS(actFirstNodeS) {
        actFirstNodeS = parseInt(actFirstNodeS);

      var ulContainer = document.getElementById('serveritemCarrier');

      if(ulContainer) {
          //clear the container
          ulContainer.innerHTML="";

      var myLength = arrListS.length(); //gibt in unserem bsp 10 zurück

      // pos 1
          var myNodeA = arrListS.get(actFirstNodeS);
          ulContainer.appendChild(myNodeA);

      // pos 2
          if((actFirstNodeS+1) < myLength) {
            var nextNode = actFirstNodeS+1;
          } else {
            var nextNode = 0;
          }

      var myNodeB = arrListS.get(nextNode);
          ulContainer.appendChild(myNodeB);

      // pos 3
          if((nextNode+1) < myLength) {
            nextNode = nextNode+1;
          } else {
            nextNode = 0;
          }

      var myNodeC = arrListS.get(nextNode);
          ulContainer.appendChild(myNodeC);
        }
      }

      Du hast nicht zufällig ein Testbeispiel, das man online begutachten könnte?

      nein es ist eine firmeninterne entwicklung :/

      Ich kann mir nicht gut vorstellen, dass der IE irgendwo streikt, weil das HTML nicht ganz valide ist, weil ich der meinung bin das das HTML in meinem ersten posting des LI Elementes OK ist?

      Danke und Gruss
      Chris

      1. if(getListNodes.childNodes[i].id) {

        Du solltest entweder auf childNodes verzichten und eindeutigere Objekte verwenden oder du überprüfst ob der Knoten wirklich das ist was du erwartest.

        var myLength = arrListS.length(); //gibt in unserem bsp 10 zurück

        length ist keine Funktion, das sollte ein Fehler ergeben.

        Struppi.

        1. Lieber Struppi,

          var myLength = arrListS.length(); //gibt in unserem bsp 10 zurück

          length ist keine Funktion, das sollte ein Fehler ergeben.

          im Grunde könntest Du Recht haben. Jedoch ist in der nun bekannt gewordenen Konstruktor-Funktion ersichtlich geworden, dass length hier zu einer Memberfunktion "umgebaut" wurde. Also gibt es keinen Fehler.

          Liebe Grüße aus Ellwangen,

          Felix Riesterer.

          --
          ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      2. Lieber Chris,

        ich weiß zwar noch immer nicht was ein ArrayList-Objekt ist und kann, aber das nur nebenbei.

        Was mich insgesamt verunsichert, ist die Tatsache, warum Du <li>-Elemente aus einer <ul> entfernst, um dann diese Elemente wieder einzufügen. Wäre es nicht sinnvoller, mittels einer per JavaScript zugewiesenen Klasse diese <li>-Elemente einfach zu "behandeln"? Damit kannst Du ausgewählten <li>-Elementen eine bestimmte Klasse zuweisen, während die restlichen eine andere Klasse erhalten.

        Ich versuche einmal deine Funktion zu verstehen:

        function initArrayListS(intID) {  
          arrListS = new ArrayList();  
        /* Wie gesagt, dieses Objekt ist mir fremd. ArrayList gehört nicht zum regulären Sprachumfang von JavaScript... */  
          
          var getListNodes = document.getElementById('serveritemCarrier');  
        /* Warum nennen wir das gemeinte HTML-Elementobjekt hier nicht auch "ulContainer", so wie später? Das hilft, Deinen Code zu verstehen... */  
          
          if(getListNodes) {  
            for(var i=0;i<getListNodes.childNodes.length;i++) {  
        /* Warum nicht so?  
            var listNodes = document.getElementById("serveritemCarrier").getElementsByTagName("li");  
        Da kann man jetzt auch durch die gefundenen <li>-Elemente durchiterieren. Das ist auch für einen "Außenstehenden" schneller begreifbar. */  
          
              if(getListNodes.childNodes[i].id) {  
        /* Aha, die Teile müssen eine passende ID haben? Gibt es darinnen denn auch <li>-Elemente, die ausscheiden? */  
          
                if(getListNodes.childNodes[i].id.split("_")[0] == "slide") {  
        /* Anscheinend... nur wenn da "slide_xyz..." in der ID steht, werden sie genommen... */  
          
                  arrListS.add(getListNodes.childNodes[i]);  
        /* Das ist eine Methode des ArrayList-Objektes, das ich ja nicht kenne... */  
          
                  getListNodes.removeChild(getListNodes.childNodes[i]);  
        /* Warum entfernst Du hier das <li>-Element, wenn Du doch später mit innerHTML eh alles platt machst? Das ist in meinen Augen unnötig. */  
          
                  i=i-1;  
        /* Tja, das bräuchtest Du nicht, wenn Du mit getElementsByTagName arbeitetest und anschließend die Elemente nicht einzeln entferntest. */  
          
                }  
              }  
            }  
          
          }  
          
          displayListS(actFirstNodeS);  
        /* Woher kommt diese Funktion? Und was ist "actFirstNodeS"? */  
        }
        

        Vielleicht ist Dein Ansatz hier tatsächlich nicht anders lösbar, aber mir scheint doch sehr, dass Du in der <ul id="serveritemCarrier"> eher die nichtbenötigten Elemente entfernen solltest, um nur die benötigten zu belassen (das bedeutet auch, nicht-<li>-Elemente wie Textnodes aus der <ul> zu entfernen!), und um diese dann dynamisch mit Klassen zu versehen. Das sollte dann auch im dümmsten Browser wie dem IE klappen.

        Liebe Grüße aus Ellwangen,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. Lieber Felix.
          Danke nochmals, dass du dich so intensiv mit meinem Problem auseinandersetzt.

          Was mich insgesamt verunsichert, ist die Tatsache, warum Du <li>-Elemente aus einer <ul> entfernst, um dann diese Elemente wieder einzufügen. Wäre es nicht sinnvoller, mittels einer per JavaScript zugewiesenen Klasse diese <li>-Elemente einfach zu "behandeln"? Damit kannst Du ausgewählten <li>-Elementen eine bestimmte Klasse zuweisen, während die restlichen eine andere Klasse erhalten.

          Hmm dieser Gedanke macht mir Angst, da der Ansatz viel einfacher ist :D und meine komplizierte Lösung vielleicht einfach ersetzen könnte...

          Da ich ja zu beginn eh alle LI's lade, könnte ich einfach mit display:none; die nicht benötigten verstecken. *hmmm* ich werde der Sache mal nachgehen.

          Dann schulde ich euch wohl noch meine ArrayList :) sorry war wohl etwas verwirrend.

          function ArrayList() {
            this.arr = new Array();
            this.add = function(myObj){
              this.arr[this.arr.length] = myObj;
            }
            this.length = function (){
              return this.arr.length;
            }
            this.get = function (myIndex){
              return this.arr[myIndex];
            }
            this.set = function (myObj, myIndex){
              this.arr[myIndex] = myObj;
            }
          }

          Ich versuche einmal deine Funktion zu verstehen:

          var getListNodes = document.getElementById('serveritemCarrier');
          /* Warum nennen wir das gemeinte HTML-Elementobjekt hier nicht auch "ulContainer", so wie später? Das hilft, Deinen Code zu verstehen... */

          wäre devintiv sprechender...

          /* Warum nicht so?
          var listNodes = document.getElementById("serveritemCarrier").getElementsByTagName("li");
          Da kann man jetzt auch durch die gefundenen <li>-Elemente durchiterieren. Das ist auch für einen "Außenstehenden" schneller begreifbar. */

          hmm ja das getElementsByTagName. Ich weiss auch nicht warum ich das nie verwende. Ist eigentlich hier klar die beste Lösung

          if(getListNodes.childNodes[i].id) {
          /* Aha, die Teile müssen eine passende ID haben? Gibt es darinnen denn auch <li>-Elemente, die ausscheiden? */

          richtig erkannt. die LI haben eine ID und wie slide_1 etc... weil wenn ich ja nach links und rechts klicke in meiner "slideshow" müssen andere Elemente dargestellt werden. übrigens mache ich einen endless loop, sprich wenn man nach rechts klickt und das letzte Element erscheint, kommt automatisch wieder das erste Element. Also eine art Karussell.

          getListNodes.removeChild(getListNodes.childNodes[i]);
          /* Warum entfernst Du hier das <li>-Element, wenn Du doch später mit innerHTML eh alles platt machst? Das ist in meinen Augen unnötig. */

          Das stimmt, es ist aber säuberer die DOM Struktur durch Node-Operationen zu verändern, anstatt innerHTML zu verwenden.

          displayListS(actFirstNodeS);
          /* Woher kommt diese Funktion? Und was ist "actFirstNodeS"? */
          }[/code]

          Die erste Funktion war um die ArrayList zu initieren und ihr die Objekte zuzuweisen. Die zweite Funktion displayListS() managed das Darstellen der Elemente. actFirstNodeS ist eine globale Variable, die die erste ID des darzustellenden Objekts beinhaltet.

          Klar der technische Ansatz ist hier zu hinterfragen, in FireFox funktioniert es tadellos, leider im IE eben nicht. Und IE ist mir wichtiger :/ Darum muss ich wohl das Ganze nochmals überdenken.

          1. Klar der technische Ansatz ist hier zu hinterfragen, in FireFox funktioniert es tadellos, leider im IE eben nicht. Und IE ist mir wichtiger :/ Darum muss ich wohl das Ganze nochmals überdenken.

            Wie schon gesagt, das Problem ist childNodes, da die Browser unterschiedliche Auffasung davon haben welche Nodes in die Liste kommen und welche nicht.

            Struppi.

            1. Lieber Struppi,

              Wie schon gesagt, das Problem ist childNodes, da die Browser unterschiedliche Auffasung davon haben welche Nodes in die Liste kommen und welche nicht.

              aber wenn er doch explizit childNodes mit einer passenden ID herausfiltert, dann sollte das doch wohl egal sein.

              Liebe Grüße aus Ellwangen,

              Felix Riesterer.

              --
              ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
          2. Lieber Chris,

            ich vermute, das Ganze ist eine Art Karrussell-Slideshow wie bei Apple (Ipod etc.)

            Hmm dieser Gedanke macht mir Angst, da der Ansatz viel einfacher ist :D und meine komplizierte Lösung vielleicht einfach ersetzen könnte...

            Keine Angst vor Vereinfachungen, wenn sie sinnvoll sind!

            Da ich ja zu beginn eh alle LI's lade, könnte ich einfach mit display:none; die nicht benötigten verstecken. *hmmm* ich werde der Sache mal nachgehen.

            Nö. Vergib Klassen! Dadurch kannst Du Dir viele element.style.-Geschichten sparen. Die <li>-Elemente, die Du nicht sehen willst, bekommen einfach eine entsprechende Klasse, in der dann natürlich display:none steht. Wenn Du das dirket über das style-Objekt machst, dann musst Du das wieder rückgängig machen, wenn denn das <li>-Element plötzlich doch sichtbar werden soll. - Nimm Klassen!

            Dann schulde ich euch wohl noch meine ArrayList :) sorry war wohl etwas verwirrend.

            Also im Grundegenommen ist das nur ein Wrapper für das JavaScript-eigene Array-Objekt, dem diverse Funktionalitäten angedichtet wurden (wie z.B. add()), was ja ganz sinnvoll ist, wenn man verstärkt mit Arrays arbeitet. ich hatte mir im Wesentlichen sowas schon gedacht.

            hmm ja das getElementsByTagName. Ich weiss auch nicht warum ich das nie verwende. Ist eigentlich hier klar die beste Lösung

            Es vereinfacht Deinen Code außerdem. Deine Lösung mag in machen Kontexten sinnvoller und eleganter sein, ich finde sie hier aber unnötig umständlich. Außerdem lauern hier "Fehler", da der IE Textknoten anders behandelt, als der Firefox (oder eben "richtige Browser"). Ein Zeilenumbruch im Quelltext kann daher bereits im FF als Textknoten (und somit child-Element) eines Elementobjektes gewertet werden. Beispiel:

            <ul> <-hier entsteht ein Textknoten im FF bestehend aus Zeilenumbruch und Leerzeichen! Im IE dagegen nicht...
                <li>

            richtig erkannt. die LI haben eine ID und wie slide_1 etc... weil wenn ich ja nach links und rechts klicke in meiner "slideshow" müssen andere Elemente dargestellt werden.

            Muss das über die Vergabe einer ID erfolgen? Kannst Du die Slideshow nicht als großes Objekt anlegen, das intern einen Zähler hat, welches der Bilder gerade angezeigt wird, sodass im Prinzip klar sein muss, welches Bild danach, bzw. davor kommt? Das erspart Dir auch hässliche globale Variablen.

            Das stimmt, es ist aber säuberer die DOM Struktur durch Node-Operationen zu verändern, anstatt innerHTML zu verwenden.

            Das mag sein. Da Du aber sinnvollerweise das aus der <ul> löschst, was für die Karrussell-Galerie eben nicht benötigt wird, bist Du sogar dazu gezwungen.

            Die erste Funktion war um die ArrayList zu initieren und ihr die Objekte zuzuweisen. Die zweite Funktion displayListS() managed das Darstellen der Elemente. actFirstNodeS ist eine globale Variable, die die erste ID des darzustellenden Objekts beinhaltet.

            Wie gesagt, ich fände es sinnvoller, wenn Du ein großes Objekt Slideshow anlegst, das als Factory für Slideshow-Objekte dient (also eine Knstruktor-Funktion wie Deine ArrayList-Funktion). Darin sollte dann jede Slideshow selbst steuern, was sie hat und kann, also interne Zählervariablen und interne Funktionen (also Methoden) beinhalten.

            Klar der technische Ansatz ist hier zu hinterfragen, in FireFox funktioniert es tadellos, leider im IE eben nicht. Und IE ist mir wichtiger :/ Darum muss ich wohl das Ganze nochmals überdenken.

            Poste doch einmal eine Testseite, damit man sich das anschauen kann! Firmeninterne Entwicklung hin oder her, letzten Endes kannst Du doch mittels Lizenz und Copyright den Code unfrei machen!

            Liebe Grüße aus Ellwangen,

            Felix Riesterer.

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