Navigation im DOM: die Beziehung zwischen den Elementen
Wenn keine CSS-Selektoren für den direkten Zugriff zur Verfügung stehen, kann Javascript die Verwandtschaftsbeziehungen der Elemente für den Zugriff auf Elemente und die Navigation im Dokument nutzen.
Alte und neue Selektoren
childNodes, firstChild, lastChild, nextSibling, previousSibling und parentNode sind alte Methoden bzw. Eigenschaften aus der Frühzeit des DOM. Weil sie nicht nur echte Elemente, sondern auch Füllmaterial erreichen, wurde sie um präzisiere Methoden und Eigenschaften ergänzt.
children ()
Alle Elementknoten, die direkte Kinder eines Elements sind, in der Reihenfolge, wie sie im Code des Dokuments vorkommen. Zu children zählen nur Elementknoten, also weder Text- noch Kommentarknoten.
Veraltete Version: childNodes
firstElementChild
Das erste Child-Element mit nodeType 1. Text und Kommentare sind keine Element-Nodes.
Veraltete Version: firstChild
lastElementChild
Das letzte Child-Element mit nodeType 1. Text und Kommentare sind keine Element-Nodes.
Veraltete Version: lastChild
nextElementSibling
Verweis auf das nächste Kind-Element desselben Elternknotens. Zu nextElementSibling zählen nur Elementknoten, nicht aber Text- und Kommentarknoten.
Veraltete Version: nextSibling
previousElementSibling
Verweis auf das vorangehende Kind-Element desselben Elternknotens. Zu previousElementSibling zählen nur Elementknoten, nicht aber Text- und Kommentarknoten.
Veraltete Version: previousSibling
parentElement
Elternelement des aktuellen Node. parentElement gibt null zurück, wenn der Elternknoten kein Elementknoten ist (document.documentElement.parentElement). In den meisten Fällen gibt es aber kein Unterschied zu parentNode.
Veraltete Version: parentNode
Die alten Techniken sind nur sinnvoll, wenn tatsächlich auch »leere Knoten« (Leerzeichen, Kommentare, Zeilenumbrüche) aus dem HTML-Markup eine Rolle spielen.
children – direkte Nachfolger des Elements
Javascript children gibt nur Elementknoten vom Typ 1 zurück. Leerzeichen, Text und Kommentare gelangen nicht in die NodeList wie mit der älteren Version childNodes.
<div class="bss-slides">
<!-- Slideshow -->
<figure>
<img src="shirt3.png" width="100%" alt="Bild 1" />
<figcaption>Blaues Shirt</figcaption>
</figure>
…
</div>
const items = document.querySelector('.bss-slides').children; console.log ("children", items); const arr = Array.from (items); arr.forEach (item => { console.log (item.innerText); item.style.cssText = "background: ivory; border: 1px solid silver;" });
children gibt eine HTMLCollection zurück, die einem Array sehr ähnlich sieht und auch tatsächlich einen Index hat. Allerdings unterstützt die HTMLCollection keine Methoden höherer Ordnung wie z.B. forEach (), sondern dank Index und length-Eigenschaft eine klassische for- oder die modernere for-of-Iteration. Um wie hier im Beispiel forEach () zu nutzen, wandelt Array.from () die HTMLCollection in ein Array um.
▼ children
▼ HTMLCollection (3)
0 <figure style="background: ivory; border: 1px solid silver;">…</figure>
1 <figure style="background: ivory; border: 1px solid silver;">…</figure>
2 <figure style="background: ivory; border: 1px solid silver;">…</figure>
▼ HTMLCollection Prototype
█ constructor: function()
█ item([index])
█ length
█ namedItem([name])
█ Symbol(Symbol.iterator)()
█ Symbol(Symbol.toStringTag): "HTMLCollection"
▶ Object Prototype
nextElementSibling – das Element danach
previousElementSibling – das Element davor
previousElementSibling gibt das vorangehende Element auf derselben Ebene eines Elements zurück
nextElementSibling gibt das folgende Element auf derselben Ebene eines Elements zurück. Anders als die älteren Gegenstücke nextSibling und previousSibling liefern sie nur Element-Knoten und keine Leerzeichen, Zeilenumbrüche oder Kommentare.
const fruits = document.querySelector(".flexfruit").children; console.log (`vor der Melone ${fruits[1].previousElementSibling.alt}`); console.log (`nach der Melone ${fruits[1].nextElementSibling.alt}`);
vor der Erdbeere Melone
nach der Erdbeere Orange
nextElementSibling und previousElementSibling sind keine Methoden, sondern Eigenschaft des Elements. console.dir () gibt eine Liste aller Eigenschaften des Elements aus. Zu lang, um hier alle aufzuführen, aber einen Blick wert.
console.dir (fruits[1].previousElementSibling);
<img>
█ align: ""
█ alt: ""
█ childElementCount: 0
█ children: HTMLCollection [] (0)
█ className: "Melone"
█ clientHeight: 267
█ clientLeft: 0
█ draggable: false
█ firstElementChild: null
█ hidden: false
█ id: ""
█ onclick: null
█ onresize: null
█ parentElement: <div id="flexfruit">
█ parentNode: <div id="flexfruit">
█ previousElementSibling: #text " "
█ scrollWidth: 126
Das zweite Element, die Erdbeere, hätte auch querySelector mit einem CSS-Selektor erreicht.
const child2 = document.querySelector(".flexfruit img:nth-child(2)");
Es gibt viele Wege zum Element: Wer mit CSS gut vertraut ist, dem wird die CSS-Notation eher liegen, nicht zuletzt, weil die CSS-Nummerierung für viele Web-Designer intuitiver ist.
firstElementChild / lastElementChild
elem.firstElementChild greift auf das erste Kind-Element eines Knotens zu, elem.lastElementChild auf das letzte. Diese Eigenschaften ersetzen die älteren Eigenschaften firstChild und lastChild, die nicht nur Element-Nodes erreichen, sondern auch Leerzeichen, Zeilenumbrüche und Kommentare.
const firstChild = document.querySelector (".flexfruit").firstElementChild; console.log ("firstChild", firstChild); const fruit = document.querySelector (".flexfruit img:first-child"); console.log ("fruit", fruit);
Das erste bzw. letzte Kind-Element eines Parent-Knotens erreicht CSS und damit auch querySelector () mit einem CSS-Selektor.
hasChildNodes
Die Methode hasChildNodes () gibt true zurück, wenn ein Element Kindknoten hat und false, wenn nicht.
const fruits = document.querySelector (".flexfruit"); console.log (fruits.hasChildNodes ()); // [Log] true