bleibert: ungültige Werte bei Eigenschaften abfangen

Hallo zusammen!

Ich möchte bei einer Tabelle abfragen, ob ein <thead> vorhanden (und wenn ja, wieviele Zeilen er umfasst - das klappt soweit) und dann eine Variable entsprechend setzen. Im Script wollte ich das so umsetzen:

var theadrownum = 0; //number of rows in thead  
if (document.getElementsByTagName("thead")[0].nodeName == "THEAD") theadrownum = document.getElementsByTagName("thead")[0].lastChild.previousSibling.rowIndex + 1;

Solange ein <thead> vorhanden ist, kein Problem. Nur wenn kein <thead> da ist, dann spuckt

document.getElementsByTagName("thead")[0].nodeName

irgendwas Blödes aus, was zur Folge hat, dass das ganze Skript nicht mehr ausgeführt wird. Wie mache ich es anders? Kann ich eine geeignete Eigenschaft abfragen? Oder kann ich den Fehler irgendwie abfangen?

Viele Grüße,
Dennis.

  1. Hallo,

    if (document.getElementsByTagName("thead")[0].nodeName == "THEAD") // ..

    Die Methode "getElementsByTagName" findet nur Elemente, die den angegebenen Tag-Namen haben - eine nochmalige Prüfung der "nodeName"-Eigenschaft ist unnötig.
    Um festzustellen ob überhaupt ein <thead> vorhanden ist kannst Du die "length"-Eigenschaft der HTMLCollection abfragen, welche die Methode zurückgibt.

    Gruss,
    Worf

    1. Um festzustellen ob überhaupt ein <thead> vorhanden ist kannst Du die "length"-Eigenschaft der HTMLCollection abfragen, welche die Methode zurückgibt.

      Probier ich, Danke!

      Viele Grüße,
      Dennis.

  2. @@bleibert:

    nuqneH

    if (document.getElementsByTagName("thead")[0].nodeName == "THEAD")

    document.getElementsByTagName("thead") liefert alle Elemente des Typs thead,
    document.getElementsByTagName("thead")[0] liefert das erste Element des Typs thead,
    document.getElementsByTagName("thead")[0].nodeName liefert den Typen des ersten Elements des Typs thead.

    Du erkennst die Unsinnigkeit des Vergleichs mit "THEAD"?

    Solange ein <thead> vorhanden ist, kein Problem. Nur wenn kein <thead> da ist, dann spuckt

    document.getElementsByTagName("thead")[0].nodeName

    irgendwas Blödes aus

    Wenn die Nodelist document.getElementsByTagName("thead") leer ist, gibt es kein Element mit dem Index 0. Und was es nicht gibt, kann auch nicht die Eigenschaft nodeName haben.

    Du willst prüfen, ob die Nodelist leer ist:

    if (document.getElementsByTagName("thead"))

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. document.getElementsByTagName("thead") liefert alle Elemente des Typs thead,
      document.getElementsByTagName("thead")[0] liefert das erste Element des Typs thead,
      document.getElementsByTagName("thead")[0].nodeName liefert den Typen des ersten Elements des Typs thead.

      Das war mir so noch nicht klar, Danke für die Erklärung!

      Wenn die Nodelist document.getElementsByTagName("thead") leer ist, gibt es kein Element mit dem Index 0. Und was es nicht gibt, kann auch nicht die Eigenschaft nodeName haben.

      Genau, und das wollte ich dann nutzen, um eine Bedimgung für die if Abfrage zu haben. Ich wusste nicht, wie ich sonst die Existenz abfragen sollte.

      if (document.getElementsByTagName("thead"))

      Ist klar, vielen Dank!
      Dennis.

    2. @@Gunnar Bittersmann:

      nuqneH

      Du willst prüfen, ob die Nodelist leer ist:
      if (document.getElementsByTagName("thead"))

      if (document.getElementsByTagName("thead").length), wie 1UnitedPower sagte.

      Qapla'

      --
      „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
  3. Hi,

    var theadrownum = 0; //number of rows in thead

    if (document.getElementsByTagName("thead")[0].nodeName == "THEAD") theadrownum = document.getElementsByTagName("thead")[0].lastChild.previousSibling.rowIndex + 1;

    
    >   
    > Solange ein <thead> vorhanden ist, kein Problem.  
      
    doch, schon. Du suchst im ganzen Dokument nach thead-Elementen und nimmst dann einfach das erste davon. Willst du die Suche nicht lieber auf eine bestimmte Tabelle beschränken?  
      
    
    > Nur wenn kein <thead> da ist, dann spuckt  
    >   
    > `document.getElementsByTagName("thead")[0].nodeName`{:.language-javascript}  
    >   
    > irgendwas Blödes aus, ...  
      
    Ja, nämlich null. Das ist so definiert. Also darfst du nicht einfach auf eine Eigenschaft des vermeintlichen Objekts zugreifen, bevor du weißt, ob diese Eigenschaft überhaupt existiert. Prüfe zuerst, ob überhaupt ein thead existiert, und dann erst, wieviele tr-Elemente er enthält:  
      
    ~~~javascript
    var thead = theTable.getElementsByTagName("thead");  
    var theadrows = (thead ? thead[0].getElementsByTagName("tr").length : 0);
    

    Eventuell geht das noch einfacher, wenn man die DOM-Repräsentation des table-Elements verwendet - ich weiß, dass man damit komfortabel auf rows[] zugreifen kann. Ich weiß aber nicht genau, ob und wie die thead- oder tbody-Elemente da abgebildet werden.

    So long,
     Martin

    --
    Wenn ein Räuber eine deutsche Amtsstube überfällt, welchen Satz kann er sich dann sparen?
    "Keine Bewegung!"
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Nur wenn kein <thead> da ist, dann spuckt

      document.getElementsByTagName("thead")[0].nodeName

      irgendwas Blödes aus, ...

      Ja, nämlich null. Das ist so definiert.

      Um ganz präzise zu sein nicht null, sondern undefined.

      1. Hallo,

        Nur wenn kein <thead> da ist, dann spuckt
        document.getElementsByTagName("thead")[0].nodeName
        irgendwas Blödes aus, ...

        Ja, nämlich null. Das ist so definiert.

        Um ganz präzise zu sein nicht null, sondern undefined.

        ja, sorry - da war ich sowohl beim Lesen, als auch beim Schreiben zu oberflächlich. Ich wollte sagen: Die diversen getElement[s]By-Methoden geben null zurück, wenn sie das Gesuchte nicht finden.
        An einem null-Wert nochmal auf eine Eigenschaft zuzugreifen, ergibt natürlich undefined.

        Am praktischen Ergebnis ändert das aber hier nichts.

        Ciao,
         Martin

        --
        Küssen ist die schönste Methode, eine Frau zum Schweigen zu bringen.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. ja, sorry - da war ich sowohl beim Lesen, als auch beim Schreiben zu oberflächlich.

          Ich auch ;)

        2. ja, sorry - da war ich sowohl beim Lesen, als auch beim Schreiben zu oberflächlich. Ich wollte sagen: Die diversen getElement[s]By-Methoden geben null zurück, wenn sie das Gesuchte nicht finden.
          An einem null-Wert nochmal auf eine Eigenschaft zuzugreifen, ergibt natürlich undefined.

          Aha aha aha. Jetzt ist mir das ganze ein wenig klarer. Null ist nicht schlimm, aber bei undefined steigt das Skript dann aus?

          Viele Grüße,
          Dennis.

          1. Aha aha aha. Jetzt ist mir das ganze ein wenig klarer. Null ist nicht schlimm, aber bei undefined steigt das Skript dann aus?

            Nein, die Geschichte ist leider noch etwas komplizierter. Ob du bei null oder bei undefined versuchst auf eine Eigenschaft zuzugreifen, beides wirft einen Fehler:

              
            ull.foo // TypeError: Cannot read property 'fo' of null  
            undefined.foo // TypeError: Cannot read property 'foo' of undefined  
            null == undefined // true  
            null === undefined // false  
            
            

            Stackoverflow Diskussion: http://stackoverflow.com/questions/6429225/javascript-null-or-undefined

        3. Hallo,

          ja, sorry - da war ich sowohl beim Lesen, als auch beim Schreiben zu oberflächlich. Ich wollte sagen: Die diversen getElement[s]By-Methoden geben null zurück, wenn sie das Gesuchte nicht finden.

          Nicht ganz: Die getElementsByName-Methode gibt immer eine NodeList (bzw. HTMLCollection, je nach Implementierung) zurück, ggf. ist diese leer.
          Erst der Versuch, auf ein nicht vorhandenes Element daraus zugreifen zu wollen, ergibt einen Fehler ("Returns null if the index is out of range.") - dieser Fall ist auch gegeben, wenn auf das Element mit dem Index 0 zugegriffen wird, die Liste/Collection jedoch leer ist.
          Die getElementById-Methode liefert als Ergebnis null, wenn das Element nicht gefunden werden konnte.

          Gruss,
          Worf

      2. Nur wenn kein <thead> da ist, dann spuckt

        document.getElementsByTagName("thead")[0].nodeName

        irgendwas Blödes aus, ...

        Ja, nämlich null. Das ist so definiert.

        Um ganz präzise zu sein nicht null, sondern undefined.

        Was quatsch ich da? So spät ist es doch noch nicht.

        Das obige wäre die Ausgabe des Ausdrucks:

        document.getElementsByTagName("thead")[0];

        Versucht man eine Eigenschaft des Wertes undefined anzusprechen erhält man stattdessen folgenden Fehler:

        TypeError: Cannot read property 'nodeName' of undefined

        Wie auch immer, die Essenz aus "Der Martin"s Beitrag stimmte ja schon.

        --
        Hey Girl,
        i wish you were asynchronous, so you'd give me a callback.
        1. Versucht man eine Eigenschaft des Wertes undefined anzusprechen erhält man stattdessen folgenden Fehler:

          TypeError: Cannot read property 'nodeName' of undefined

          Und dann steigt der Browser aus und bricht das Skript ab?

          Viele Grüße,
          Dennis.

          1. TypeError: Cannot read property 'nodeName' of undefined

            Und dann steigt der Browser aus und bricht das Skript ab?

            Exakt, wie der Name schon sagt handelt es sich nämlich bei "TypeError" um einen "echten" Fehler, wohingegen null oder undefined Werte (undefined ist zusätzlich ein Typ) vorgesehene Sprachkonstrukte sind.

            Um rauszufinden, ob dein Skript Fehler wirft, kannst du die Entwickler-Tools deines Browsers nutzen. In Firefox und Chrome kannst du diese mit CTRL (STRG) + i öffnen, im Internetexplorer mit F12.

    2. doch, schon. Du suchst im ganzen Dokument nach thead-Elementen und nimmst dann einfach das erste davon. Willst du die Suche nicht lieber auf eine bestimmte Tabelle beschränken?

      Hmmm... damit habe ich mich noch nicht befasst, ich gehe fürs erste mal von einer Tabelle aus.

      Ja, nämlich null. Das ist so definiert.

      Das dachte ich mir, so wie hier beschrieben:
      http://de.selfhtml.org/javascript/objekte/node.htm#next_sibling@title=nextSibling
      Dort wird doch auch null produziert, ohne dass das Skript aussteigt. Wieso?

      Prüfe zuerst, ob überhaupt ein thead existiert, und dann erst, wieviele tr-Elemente er enthält:

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

      var theadrows = (thead ? thead[0].getElementsByTagName("tr").length : 0);

        
      Damit probier ich mal ein wenig rum.  
      Vielen Dank und viele Grüße,  
      Dennis  
      
      
    3. 
      > var thead = theTable.getElementsByTagName("thead");  
      > var theadrows = (thead ? thead[0].getElementsByTagName("tr").length : 0);
      
      

      Das muss ich nochmal kurz intervenieren. (Vielleicht gehe ich langsam doch besser schlafen, wenn man sich schon selbser mehrmals in kürzester Zeit dabei ertappt, wie die Konzentration nachlässt)

      Ein leeres Array, sowie eine leere NodeList, sind in Javascript "truly"-Werte, evaluieren in if-statements also zu true.

      Richtig müsste es also lauten:

      var thead = theTable.getElementsByTagName("thead");  
      var theadrows = thead.length ? thead[0].getElementsByTagName("tr").length : 0;
      
      1. Richtig müsste es also lauten:

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

        var theadrows = thead.length ? thead[0].getElementsByTagName("tr").length : 0;

          
        Fehlt da nicht die Klammer um thead.length?  
        Und warum geht das nicht:  
          
        `var rownum = document.getElementsByTagName("tbody").childNodes.length;`{:.language-javascript}  
          
        getElementsByTagName ist doch eine Methode vom nodes Objekt, und childNodes eine Eigenschaft davon. Hier klappt das doch auch:  
          
        `var Anzahl = document.getElementById("derText").childNodes.length;`{:.language-javascript}  
          
        <http://de.selfhtml.org/javascript/objekte/node.htm#child_nodes@title=childNodes>  
          
        Wo ist da der Unterschied? bei mir kommt immer ein Fehler:  
        TypeError: 'undefined' is not an object (evaluating 'document.getElementsByTagName("tbody").childNodes.length')  
          
        Viele Grüße,  
        Dennis.
        
        1. Hallo

          Wo ist da der Unterschied?

          Das eine ist getElementById, das andere getElementsByTagName

          Gruß
          Kalk

          1. Wo ist da der Unterschied?
            Das eine ist getElementById, das andere getElementsByTagName

            Das sehe ich auch. *warum* geht hier getElementsByTagName nicht?
            1UnitedPower schreibt doch oben auch:

            [code lang=javascript]var thead = theTable.getElementsByTagName("thead");  
            var theadrows = thead.length ? thead[0].getElementsByTagName("tr").length : 0;
            ~~~[/code]  
            Was ist da genau der Unterschied, wieso das klappt, und meins nicht? Hängt's am `getElementsByTagName("tbody").childNodes`{:.language-javascript}? Oder liegt das an `theTable`{:.language-javascript} - was ist das überhaupt? Ist das ein selbst definiertes Objekt?  
              
            Viele Grüße,  
            Dennis.
            
            1. Okay,

              getElementById

              liefert ein eindeutiges Ergebnis, da ja jede id nur einmal vorkommen darf.

              getElementsByTagName("tbody")

              könnte mehrere Ergebnisse liefern, weil es ja mehrere tbody-Elemente geben könnte. Daher funktioniert

              getElementsByTagName("thead")[0].childNodes.length

              was sich dann auf das erste tbody-Element bezieht.

              Viele Grüße,
              Dennis.

        2. Und warum geht das nicht:

          var rownum = document.getElementsByTagName("tbody").childNodes.length;

          Weil getElementsByTagName eine NodeList liefert.

          getElementsByTagName ist doch eine Methode vom nodes Objekt, und childNodes eine Eigenschaft davon.

          Aber getElementsByTagName gibt kein Node-Objekt zurück

          Hier klappt das doch auch:

          getElementById liefert ein Element zurück, das ist abgeleitet von Node
          Für sowas gibt es eine Doku

          var Anzahl = document.getElementById("derText").childNodes.length;

          Weil die NodeList keine Eigenschaft childNodes hat ist diese undefined
          und undefined.length wirft den Fehler

          TypeError: 'undefined' is not an object (evaluating 'document.getElementsByTagName("tbody").childNodes.length')