# DOM Baum in JavaScript document.body.childNodes[1]



## BodyLAB (3. Sep 2021)

Hallo zusammen,

ich muss mich gerade in JavaScript einarbeiten und scheitere schon an den einfachen Sachen :-( 

Hier mal ein Beispiel:

```
<!DOCTYPE html>
<html lang="de">

<head>
    <meta charset="UTF-8">
    <title>Baum Test</title>

    <script src="baum.js"></script>

</head>

<body>
    <h1>Hallo DOM</h1>
    <p>Ein <strong><em>kurzes</em></strong> Beispiel</p>
</body>
</html>
```

Nun möchte ich mir nur im document.body das <h1> und <p> Element ausgeben lassen.
Wenn ich es so mache geht es:

```
"use strict";

window.onload = () => {
    
    console.log(document.body.firstChild.tagName);
    console.log(document.body.lastChild.tagName);
    console.log(document.body.childNodes[1].tagName);
    console.log(document.body.childNodes[3].tagName);
}
```

Wieso childNodes[1] ? Fängt doch normal bei 0 an zu zählen :-( versteht das jemand? Hab es mit FireFox und Chrom getestet und geht beides nur mit 1 und 3, + 2 für jedes weiter Element. Bei 0, 2, etc. kommt undefined.

Dann habe ich mich auch noch etwas gefragt und zwar wie bekomme ich denn den body ohne document.body also so in der Art:
document.firstChild.nextSibling.childNodes[2]

Auch hier muss ich childNodes[2] machen? Des weiteren wieso horizontal durchlaufen? mit nextSibling bekommt man doch die Knoten auf der Horizontale. document.firstChild sollte doch HTML sein oder?  
Oh das ist <!DOCTYPE html> nicht <html>. So kommt man auf <html>
document.firstChild.nextSibling

Dann verstehe ich gerade aber nichts mehr. Dachte das ganze wäre eine Baumstruktur, kann es sein das die ersten Elemente alle Horizontal angeordnet sind?


----------



## mihe7 (3. Sep 2021)

Ja, das ist ein Baum, in dem das Document den Wurzelknoten darstellt. Allerdings ist es ein Baum von Knoten (Node) und nicht jeder Node ist auch ein Element. So gibt es z. B. Textnodes (kein Element), in Deinem Fall der Leerraum zwischen z. B. dem body- und dem h1-Tag. Wenn Du die Leerzeichen entfernst, also `<body><h1>Hallo Dom!</h1>` schreibst, dann sollte der erste Kindknoten von body auch h1 sein.


----------



## Mart (4. Sep 2021)

```
<!DOCTYPE html>



<body>
<h1>Hallo DOM</h1>
<p>Ein <strong><em>kurzes</em></strong> Beispiel</p>
</body>
<head>
<meta charset="UTF-8">
    <title>Baum Test</title>
<html lang="de">
</head>
<script>

    window.onload = () => {
        for( let ins of document.body.childNodes)
        {
        console.log(ins);
        }
    }
</script>
</html>
```
ich schmeiss es dir einfach mal so hin ... ich gedenke nicht dass du und javascript euch einig seit was "document.body" bedeutet 


und ja ... document.body != <body></body>



seit html 5 gibt es mehrere möglichkeiten für das umschließende tag

<!DOCTYPE HTML>
<HTML>
<html>

sind alles richtige sachen



informiere dich mal über selektoren eg
querySelector
getElementBy.... 

da wirst du schon was finden das deine Fragen lüftet


----------



## Mart (4. Sep 2021)

mihe7 hat gesagt.:


> in Deinem Fall der Leerraum zwischen z. B. dem body- und dem h1-Tag. Wenn Du die Leerzeichen entfernst, also `<body><h1>Hallo Dom!</h1>` schreibst, dann sollte der erste Kindknoten von body auch h1 sein.


nicht ganz... da document.body nicht dem node <body> entspricht ... es entspricht dem was man im browser sieht 
hätte er den body node raus geholt wäre auch eine sinnvolle node liste raus gekommen 
hier kommt aber eine Node liste raus die ansich unnützlich ist wegen den line breaks und leeren strings


----------



## mihe7 (4. Sep 2021)

Mart hat gesagt.:


> nicht ganz... da document.body nicht dem node <body> entspricht ... es entspricht dem was man im browser sieht
> hätte er den body node raus geholt wäre auch eine sinnvolle node liste raus gekommen
> hier kommt aber eine Node liste raus die ansich unnützlich ist wegen den line breaks und leeren strings


Ich weiß nicht, was Du mir sagen willst. Jeder Node, der kein Blatt ist, enthält andere Nodes (childNodes), wie das in einem Baum halt so üblich ist. Es gibt verschiedene Typen von Nodes, für das Dokument, Elemente, Attribute, Text usw. 

HTML wird geparst, wobei ein Baum entsteht. Dieser Baum muss nicht 1:1 mit dem HTML-Code übereinstimmen. Beispielsweise muss man keinen html-Tag angeben, im Baum wird man dennoch ein html-Element vorfinden.

Der Wurzelknoten eines HTML-Dokuments wird per document referenziert und enthält insbesondere das html-Element. Dieses enthält wiederum das body-Element. Der Browser stellt letztlich den Baum dar, dadurch wirkt sich eine Manipulation am Baum auch auf die Darstellung aus.

Das body-Element enthält neben Elementen eben auch andere Nodes anderer Typen, z. B. für Text. Allerdings wird nicht jedes Whitespace auch in einen Textnode übersetzt - in der Spezifikation zum DOM findet sich dazu die nette Aussage: "Note that, due to the magic that is HTML parsing, not all ASCII whitespace were turned into Text nodes, but the general concept is clear. Markup goes in, a tree of nodes comes out." (https://dom.spec.whatwg.org/#introduction-to-the-dom)

Umgekehrt finden sich Textnodes, wo man keine erwarten würde. Beispielsweise wird aus

```
<body><div>X</div></body>
```
ein Baum, der am Ende einen Textknoten mit einem Newline-Zeichen enthält:

```
document
|
+-- html
    |
    +-- body
        |
        +-- div
        |   |
        |   +-- #text ("X")
        +-- #text ("\n")
```
Der erste Kindknoten von body ist hier das div.

Bei

```
<body>
  <div>X</div>
</body>
```
ist der erste Kindknoten dagegen ein Textknoten mit einem Text der Länge 3 (ein Newline gefolgt von zwei Leerzeichen).


----------



## BodyLAB (7. Sep 2021)

Okay danke für eure Antworten.
Jetzt habe ich das wenigstens etwas besser verstanden  

Kann mir vielleicht jemand noch kurz erklären wieso man nextSibling Das nächste Kind des Elternknotens benötigt? 
Geht das nicht auch mit dem Array childNodes?


----------



## mihe7 (7. Sep 2021)

BasBeg hat gesagt.:


> Geht das nicht auch mit dem Array childNodes?


Sicher geht das, nur wäre das relativ kompliziert, wenn Du nur einen Knoten gegeben hast und schöner zu lesen ist es auch.


----------



## Mart (8. Sep 2021)

BasBeg hat gesagt.:


> Geht das nicht auch mit dem Array childNodes?


warum gibts denn java ... assembler gibts doch schon zum programmieren


----------



## BodyLAB (8. Sep 2021)

Hab noch eine Frage an euch.
Wie kann ich nun den ganzen Baum rekursiv durchlaufen?

Hier wäre mein Versuch:

```
<html>

<head>
    <title>DOM-Demo</title>
    <script>
        window.onload = () => {
           
        function recursiveRun(node) {
                if (node.type == 1)
                    console.log(node.tagName);
                else {
                    for (let i = 0; i < node.childNodes.length; i++)
                        recursiveRun(node.childNodes[i]);
                }
           }
            let rootNode = document.body;
            recursiveRun(rootNode);
    </script>
</head>

<body id="alles">
    <h3 id="Ueberschrift">DomBaum</h3><img src="ball.gif" id="Ball1" /><img src="ball.gif" id="Ball2" /><img
        src="ball.gif" id="Ball3" /><img src="ball.gif" id="Ball4" />
    <div>
        <ul>
            <li></li>
        </ul>
    </div>
</body>

</html>
```

Ausgegeben wird nichts. Wenn ich die Ausgabe in die for Schleife schreibe gibt er mir fast alles aus bis auf das LI Element :-( Wenn ich doch das UL Element habe und lande dann in der Schleife sollte mir dort doch das childNodes Array eine länge von größer 0 haben.
Wieso wird das LI Element verschluckt und oben kommt keine Ausgabe?


----------



## BodyLAB (8. Sep 2021)

Okay oben hab ich einen Fehler gemacht bei node.type das muss natürlich node.nodeType heißen.
Wieso merkert JS nicht echt hässlich!

So hier ein neuer Versuch doch jetzt geht er natürlich nicht in die Rekursion =D

```
function recursiveRun(node) {
                if (node.nodeType != 1 ){
                    for (let i = 0; i < node.childNodes.length; i++) {
                        recursiveRun(node.childNodes[i]);
                    }
                }
                else
                    console.log(node.tagName);
            }
```



*So geht es nun aber nicht schön!*

```
function recursiveRun(node) {
                if (node.nodeType == null) {
                   return;
                }
                else {
                    if (node.nodeType == 1)
                        console.log(node.nodeName);

                    for (let i = 0; i < node.childNodes.length; i++) {
                        recursiveRun(node.childNodes[i]);
                    }
                }

            }
```


----------



## mihe7 (8. Sep 2021)

BasBeg hat gesagt.:


> Wieso merkert JS nicht echt hässlich!


Weil das Ergebnis undefined ist


----------

