steffen: Problem im IE Invalid Argument

Hallo Helfer,

ich hab nun soweit mein JS Code fertig und hab ihn aus CSS Gründen im IE testen wollen. Jetzt seh ich, dass er Fehler bringt, mit denen ich nichts anfangen kann.

zum einen handelt es sich um den Befehl "insertBefore". Habe mal eine abgespeckte Version bereitgestellt, in der dieser Fehler auftritt.

<html><head><title>Test</title>  
<script type="text/javascript">  
this.start = function(){  
	var tables = document.getElementsByTagName("table");  
	for (var i=0;i<tables.length;i++){  
	 head(tables[i]);  
	}  
}  
  
this.head = function(table){  
	var head_exist = false;  
	for(var i=0; i<table.childNodes.length; i++){  
		if(table.childNodes[i].nodeName == "thead") head_exist = true;  
	}  
	if(!head_exist){  
		var thead = document.createElement('thead');  
		table.insertBefore(thead, table.childNodes[1]);  
	}  
}  
window.onload = start;  
</script>  
</head><body>  
<table>  
<tr>  
<td>Content</td>  
</tr>  
</table>  
</body></html>

In google fande ich nur so etwas womit ich jedoch nichts anfangen kann :(
Weiß jemand rat?

Danke für eure Hilfe!
Steffen

  1. Hi!

    ich hab nun soweit mein JS Code fertig und hab ihn aus CSS Gründen im IE testen wollen. Jetzt seh ich, dass er Fehler bringt, mit denen ich nichts anfangen kann.

    Der IE 8 hat einen Javascript-Debugger eingebaut. Mit dem kann man sich den Inhalt der Elemente ansehen.

      table.insertBefore(thead, table.childNodes[1]);  
    

    Der Fehler tritt in dieser Zeile auf. Und da sagt mir der Debugger, dass table.childNodes wieviel Elemente hat? Für den Firefox gibt es Firebug, ebenfalls mit Javascript-Debugger. Was liefert der? Und wenn du dir den Inhalt der Childnodes ansiehst, was stellst du dann für beide Browser fest?

    Lo!

    1. Hallo Lo,

      habe ein Screen gemacht:

      Screen

      Dort ist es ebenfalls childNodes[1].

      Getestet im FF 3.6

      mfg Steffen

      1. Hi!

        habe ein Screen gemacht:
        Screen
        Dort ist es ebenfalls childNodes[1].

        Was heißt hier "ebenfalls"? Der IE behandelt Whitespaces zwischen Elementen durchaus unterschiedlich zu anderen Brwosern in Bezug auf dessen Auflistung in der childNodes-Collection.

        Getestet im FF 3.6

        Und im IE? Mit dem hast du ja ein Problem, also solltest du mit ihm testen. Im IE8 kommst du mit F12 an die Entwicklertools.

        Du kannst nicht einfach davon ausgehen, dass das Element 1 in jedem Fall (und Browser) das ist, vor das du den thead hängen kannst. Es gibt noch caption und beliebig viele col oder colgroup, die vor dem thead stehen müssen, wenn vorhanden (nebst unterschiedlicher Anzahl von Whitespace-Textnodes). Um es richtig zu machen, müsste man das tfoot suchen, wenn nicht vorhanden das erste tbody und das thead davor einsortieren.

        Lo!

        1. Du kannst nicht einfach davon ausgehen, dass das Element 1 in jedem Fall (und Browser) das ist, vor das du den thead hängen kannst. Es gibt noch caption und beliebig viele col oder colgroup, die vor dem thead stehen müssen, wenn vorhanden (nebst unterschiedlicher Anzahl von Whitespace-Textnodes). Um es richtig zu machen, müsste man das tfoot suchen, wenn nicht vorhanden das erste tbody und das thead davor einsortieren.

          Nein, um es richtig zu machen fügt man die Elemente direkt dem table Element hinzu. Du musst nichts zu suchen.

          Struppi.

        2. Hi Lo,

          habe deinen Rat umgewandelt (wußte nicht, wieso da nen textnode dahinter steht, aber gut zu wissen.

          Habe nun mal den Code, auf anraten der anderen Helfer umgeschrieben:

          <html><head><title>Test</title>  
          <script type="text/javascript">  
          this.start = function(){  
          	var tables = document.getElementsByTagName("table");  
          	for (var i=0;i<tables.length;i++){  
          	 head(tables[i]);  
          	}  
          }  
            
          this.head = function(table){  
          	var thead = table.getElementsByTagName("thead");  
          	var head_exist = (thead[0] ? true : false);  
          	  
          	  
          	if(!head_exist){  
          		var thead = document.createElement('thead');  
          		var tbody = table.getElementsByTagName("tbody");  
          		table.insertBefore(thead, tbody[0]);  
          	}  
          }  
          window.onload = start;  
          </script>  
          </head><body>  
          <table>  
          <tr>  
          <td>Content</td>  
          </tr>  
          </table>  
          </body></html>
          

          Noch eine Frage am Rande, wie kann ich in dem Developer Tool mir die ChildNodes ausgeben lassen?

          mfg Steffen

          1. Hi!

              table.insertBefore(thead, tbody[0]);  
            

            Das wäre immer noch nicht ganz richtig. Ich hatte zwischenzeitlich noch gefunden, dass es eine spezielle Methode zum Zugriff und gegebenenfalls Erzeugen von thead gibt: createTHead(). Das reduziert deinen Codeaufwand und die Probleme, die richtige Stelle zu finden, drastisch.

            Noch eine Frage am Rande, wie kann ich in dem Developer Tool mir die ChildNodes ausgeben lassen?

            In deinem Fall hielt der Debugger ja schon an der problematischen Stelle an. Und da (in der Lasche Script) gibt es auch ein "Lokale Variablen" auszuwählen. Wenn da nicht das Gesuchte drin ist, kannst du auch noch auf einen Code-Teil rechts-klicken und "Überwachung hinzufügen".

            Lo!

          2. this.start = function(){

            Wozu das this????

            var thead = table.getElementsByTagName("thead");

            Warum getElementsByTagName? (immerhin eine etwas bessere Methode als zu Anfang) Ich hatte dir doch schon thead gezeigt?

              var tbody = table.getElementsByTagName("tbody");  
            

            Auch tbody ist eine Eigenschaft der Tabelle, wofür du nicht extra eine Funktion bemühen musst.

            Struppi.

            1. Hi,

                var tbody = table.getElementsByTagName("tbody");  
              

              Auch tbody ist eine Eigenschaft der Tabelle

              Nein, im Singular nicht ;-)

              MfG ChrisB

              --
              “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
  2. this.start = function(){

    Weißt du warum du hier this benutzt?

    this.head = function(table){
    var head_exist = false;
    for(var i=0; i<table.childNodes.length; i++){
    if(table.childNodes[i].nodeName == "thead") head_exist = true;

    Das ist der umständlichste Weg, den es gibt um ein Element zu finden. und in dem speziellen Fall ganz besonders. Es gibt tHead http://de.selfhtml.org/javascript/objekte/htmlelemente.htm#thead

      var thead = document.createElement('thead');  
      table.insertBefore(thead, table.childNodes[1]);  
    

    Was ist denn deiner Meinung nach childNodes[1]?
    Sicher nicht tBody. table.tBody gibt es zwar, aber warum fügst du den header nicht einfach als child in die Tabelle?
    table.appendChild(thead)

    Struppi.

    1. Hi!

      aber warum fügst du den header nicht einfach als child in die Tabelle?
      table.appendChild(thead)

      Weil es dann ganz hinten, hinter (tfoot und) den tbodys, landen würde und das ist zumindest in HTML nicht erlaubt. Browser sind zwar tolerant, aber darauf zu vertrauen, dass es dann alle Browser intentionsgemäß korrigieren, wäre mir nichts.

      Lo!

      1. Weil es dann ganz hinten, hinter (tfoot und) den tbodys, landen würde und das ist zumindest in HTML nicht erlaubt.

        Seit wann?
        http://de.selfhtml.org/html/referenz/elemente.htm#thead
        Struppi.

        1. Hi!

          Weil es dann ganz hinten, hinter (tfoot und) den tbodys, landen würde und das ist zumindest in HTML nicht erlaubt.
          Seit wann?
          http://de.selfhtml.org/html/referenz/elemente.htm#thead

          Du musst bei den Kindelementen von table schauen. http://de.selfhtml.org/html/referenz/elemente.htm#table

          Lo!

          1. Weil es dann ganz hinten, hinter (tfoot und) den tbodys, landen würde und das ist zumindest in HTML nicht erlaubt.
            Seit wann?
            http://de.selfhtml.org/html/referenz/elemente.htm#thead

            Du musst bei den Kindelementen von table schauen. http://de.selfhtml.org/html/referenz/elemente.htm#table

            OK, es scheint so zu sein, dass die Reihenfolge eine Rolle spielten könnte. Aber wenn man beim W3C nachschaut (thead wird aber nicht explizit erwähnt) ist es nur eine Frage der Anzeige:

            TFOOT must appear before TBODY within a TABLE definition so that user agents can render the foot before receiving all of the (potentially numerous) rows of data. The following summarizes which tags are required and which may be omitted:

            Das heißt es spielt für JS absolut keine Rolle, in welcher Reihenfolge tfoot, thead und tbodies innerhalb der Tabelle stehen, da die Tabelle ja schon gerendert wurde.

            wobei es ja auch egal ist, table.createTHead() macht das ja alles.

            Struppi.

      2. Hi!

        aber warum fügst du den header nicht einfach als child in die Tabelle?
        table.appendChild(thead)

        Weil es dann ganz hinten, hinter (tfoot und) den tbodys, landen würde und das ist zumindest in HTML nicht erlaubt. Browser sind zwar tolerant, aber darauf zu vertrauen, dass es dann alle Browser intentionsgemäß korrigieren, wäre mir nichts.

        Es gibt aber eine noch einfachere Lösung: Das Table-Element kennt seit DOM Level 1 die Methode createTHead(). Die gibt das thead-Element zurück und erzeugt es, wenn es noch nicht vorhanden ist. IE kennt's und der FF auch.

        Lo!