Bobbix: getElementById().getElementById()

Hallo zusammen,

ich möchte mit JavaScript auf ein HTML-Element zugreifen, welches folgende Kriterien erfüllt:

1. Es ist das erste <li>-Kindelement eines <ul>-Elternelements.
2. Es befindet sich innerhalb eines HTML-Elements mit der ID "listenID".
3. Das HTML-Element mit der ID "listenID" befindet sich innerhalb eines HTML-Elements mit der ID "listenIDWrapper".

Theoretisch müsste der Zugriff wie folgt aussehen:

  
document.getElementById("listenIDWrapper").getElementById("listenID").getElementsByTagName("li")[0];  

Das funktioniert aber leider nicht. Ist es nicht möglich, zweimal getElementById anzugeben?

Der komplette Code kann man unter http://jsfiddle.net/zDDkt/1/ sehen.

Vielen Dank vorab für Eure Kommentare und Lösungsvorschläge.

Schöne Grüße

Bobbix

  1. Hallo,

    document.getElementById("listenIDWrapper").getElementById("listenID").getElementsByTagName("li")[0];

    
    >   
    > Das funktioniert aber leider nicht. Ist es nicht möglich, zweimal getElementById anzugeben?  
      
    Nein. getElementById ist eine Methode von Document-Knoten, nicht von Element-Knoten. Bei getElementsByTagName z.B. ist das anders – die Methode existiert bei document und einzelnen Elementen.  
      
    Für solche komplexen Abfragen kannst du [document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector)([All](https://developer.mozilla.org/en-US/docs/Web/API/Document.querySelectorAll)) verwenden. Diese Methoden nehmen CSS-Selektoren entgegen.  
      
    Beispiel:  
      
    `var el = document.querySelector('#listenIDWrapper #listenID li:first-child');`{:.language-javascript}  
      
    [Browserunterstützung](http://caniuse.com/queryselector) beachten. Für ältere Browser würde ich zu etablierten Selektor-Engines wie [Sizzle](http://sizzlejs.com/) raten. Sizzle ist Teil von [jQuery](http://jquery.com/).  
      
    Mathias
    
    -- 
    [Chaplin.js - JavaScript application architecture on top of Backbone.js](http://chaplinjs.org/)
    
    1. Hallo Mathias,

      vielen Dank für Deine ausführliche Antwort. Du hast mir sehr damit geholfen.

      Schöne Grüße

      Bobbix

    2. Beispiel:

      var el = document.querySelector('#listenIDWrapper #listenID li:first-child');

      Irgend jemand sollte noch anmerken dass es nicht sinnvoll ist nach einem Element mit einer ID innerhalb eines Elements mit einer ID zu suchen, weil die ID eineindeutig sein soll -> sonst ist es kein valides HTML.

      var el = document.querySelector('#listenID li:first-child');

      reicht demnach völlig aus, weil #listenID nur genau einmal vorkommen darf.

      Jörg Reinholz

      1. Hi!

        var el = document.querySelector('#listenIDWrapper #listenID li:first-child');

        Irgend jemand sollte noch anmerken dass es nicht sinnvoll ist nach einem Element mit einer ID innerhalb eines Elements mit einer ID zu suchen, weil die ID eineindeutig sein soll -> sonst ist es kein valides HTML.

        Diese Logik verstehe ich nicht. Es ist unter Umständen sinnvoll, nach einem Element mit einer ID innerhalb eines Elements mit einer (anderen) ID zu suchen. Das ist durchaus valides HTML.

        var el = document.querySelector('#listenID li:first-child');

        reicht demnach völlig aus, weil #listenID nur genau einmal vorkommen darf.

        Natürlich kann listenID nur einmal vorkommen, aber es muss deshalb nicht notwendig in listenIDWrapper verschachtelt sein.

        Wenn listenID *immer* in listenIDWrapper verschachtelt ist, ist ein komplexer Selektor mit beiden IDs in der Tat unnötig komplex. Da hast du Recht.

        Wenn man das Element nur finden will, falls es entsprechend verschachtelt ist, dann muss man beide IDs angeben.

        Mathias

        1. Diese Logik verstehe ich nicht. Es ist unter Umständen sinnvoll, nach einem Element mit einer ID innerhalb eines Elements mit einer (anderen) ID zu suchen. Das ist durchaus valides HTML.

          Also, wenn das Element mit der ID "A" innerhalb eines Dokumentes einmal innerhalb eines Elementes "B" vorkommt und noch einmal nicht, dann ist es nicht valide, weil es dann mindestens zwei Elemente mit der ID "A" gibt. Und ich weiß, dass Du weißt, dass ich diesen Fall gemeint habe.

          Natürlich kann listenID nur einmal vorkommen, aber es muss deshalb nicht notwendig in listenIDWrapper verschachtelt sein.

          Jaja. Valide nur im Falle, dass es sich um verschiedene Dokumente handelt, welche den gleichen Stylesheet benutzen.

          Auf deutsch:

          Im Dokument 1:
          Element mit der ID "A" innerhalb eines Elementes "B" soll selektiert werden.

          Im Dokument 2:
          Element mit der ID "A" NICHT innerhalb eines Elementes "B" soll NICHT selektiert werden.

          Das ist dann aber sehr nahe an der Unpflegbarkeit. Da sieht doch recht schnell keiner mehr durch, derlei erhöht später die Kosten.

          Mag natürlich sein, dass es womöglich technische Gründe gibt, weil irgendwas (eine Funktion? ein Objekt?) das Element mit der fixen ID "A" ausgibt. Aber auch das wäre, bei zurückhaltender Bewertung, nicht gerade guter Stil.

          Jörg Reinholz

          1. Hallo,

            Und ich weiß, dass Du weißt, dass ich diesen Fall gemeint habe.

            Was du alles weißt! Da weißt du mehr, als ich weiß.

            Im Dokument 1:
            Element mit der ID "A" innerhalb eines Elementes "B" soll selektiert werden.

            Im Dokument 2:
            Element mit der ID "A" NICHT innerhalb eines Elementes "B" soll NICHT selektiert werden.

            Ich verstehe diesen Satz nicht. Wie sollte ein Selektor aussehen, der diese Verneinung umsetzt?

            Das ist dann aber sehr nahe an der Unpflegbarkeit. Da sieht doch recht schnell keiner mehr durch, derlei erhöht später die Kosten.

            Das sehe ich nicht so. Es kommt recht häufig vor, dass man Styles für ein Element definiert und ein weiteres mal für das Element, wenn es sich in einem bestimmten Kontext befindet. Um einmal von den IDs wegzukommen, ein Beispiel mit Klassen:

            body { background-color: white; }  
            .foo { color: black; }  
              
            .bar { background-color: black; }  
            .bar .foo { color: white; }
            

            Mit IDs geht das natürlich genauso.

            Ich weiß nicht, wieso das »unpflegbar« oder schlechter Stil sein soll, das ist gang und gäbe.

            Mathias

            1. Um einmal von den IDs wegzukommen, ein Beispiel mit Klassen:

              Bei der Verwendung einer Klasse hätte ich nicht so das Problem damit. Aber bei ID's sieht das anders aus. Elemente mit einer ID sind aus meiner Sicht etwas, was man möglichst direkt und bedingungslos adressiert (für Dich: selektiert) - eben weil die Dinger nur einmal vorkommen können.

              Ich behaupte ja auch nicht, dass obiges nicht geht. Ich behaupte nur dass es unschön ist und die Pflegbarkeit ohne jede Not erschwert.

              Jörg Reinholz

  2. Hi,

    document.getElementById("listenIDWrapper").getElementById("listenID").getElementsByTagName("li")[0];

    
    >   
    > Das funktioniert aber leider nicht. Ist es nicht möglich, zweimal getElementById anzugeben?  
      
    Natürlich funktioniert das nicht – getElementById ist eine Methode des document-Objektes, HTML-Element-Objekte haben sie nicht.  
      
    
    > ich möchte mit JavaScript auf ein HTML-Element zugreifen, welches folgende Kriterien erfüllt:  
    >   
    > 1. Es ist das erste <li>-Kindelement eines <ul>-Elternelements.  
    > 2. Es befindet sich innerhalb eines HTML-Elements mit der ID "listenID".  
      
    Dann greife auf "listenID" per ID zu, und hole dir das erste LI-Element.  
      
    
    > 3. Das HTML-Element mit der ID "listenID" befindet sich innerhalb eines HTML-Elements mit der ID "listenIDWrapper".  
      
    Dann schau dir das Elterelement (oder die Vorfahrenelemente, wenn es kein direktes Kindelement ist) an, und vergleiche dessen ID mit "listenIDWrapper".  
      
    Oder nutze querySelectorAll, das CSS-Selektoren versteht.  
      
    MfG ChrisB  
      
    
    -- 
    Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
    
    1. Hallo ChrisB,

      vielen Dank für Deine Antwort und Deine Hilfe.

      Dann schau dir das Elterelement (oder die Vorfahrenelemente, wenn es kein direktes Kindelement ist) an, und vergleiche dessen ID mit "listenIDWrapper".

      Sehr gute Idee, so mache ich es.

        
      if(document.getElementById('listenIDWrapper')) {  
          var ErsterPunkt = document.getElementById("listenID").getElementsByTagName("li")[0];  
      }  
      
      

      Schöne Grüße

      Bobbix

      1. Hi,

        Dann schau dir das Elterelement (oder die Vorfahrenelemente, wenn es kein direktes Kindelement ist) an, und vergleiche dessen ID mit "listenIDWrapper".

        Sehr gute Idee, so mache ich es.

        if(document.getElementById('listenIDWrapper')) {
            var ErsterPunkt = document.getElementById("listenID").getElementsByTagName("li")[0];
        }

          
        Damit hast du aber noch nicht überprüft, ob #listenID auch wirklich Kind oder Nachfahre von #listenIDWrapper ist … wenn du das explizit brauchst, musst du das noch prüfen. (Und wenn nicht, dann kannst du die Abfrage bzgl. #listenIDWrapper auch weglassen.)  
          
        MfG ChrisB  
          
        
        -- 
        Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/