JavaScript/Tutorials/DOM/Was ist das DOM
Das DOM ist eigentlich eine Schnittstelle zwischen JavaScript und HTML-Dokumenten, der Name Document Object Model bezieht sich auf das zugrundeliegende Objektmodell.
Ein HTML-Dokument besteht ja eigentlich nur aus reinem Text, der erst vom Browser ausgelesen und geparst wird. Die einzelnen Elemente werden so in einer Baumstruktur als Unterobjekte des window-Objekts dargestellt.
Dieses Tutorial zeigt, wie Sie mit JavaScript nun beliebige Elemente im Elementbaum ansprechen und diese verändern, entfernen und mit Anwenderereignissen verknüpfen können.
Elementknoten ansprechen
Erinnern Sie sich noch an unser "Hallo Welt"-Beispiel? Die Nachteile einer Textausgabe mittels alert
sind vor allem die Speicherbelastung des Browsers sowie die mangelnde Gestaltungsmöglichkeit des Ausgabefensters.
<output id="info"></output>
<script>
'use strict';
let text = 'Hallo Welt!';
document.getElementById('info').innerText = text;
</script>
Das Script ist nun in eine Webseite eingebunden. Teil dieser Webseite ist ein (noch) leeres output-Element mit der id info
.
Anstelle der Ausgabe mit alert
wird mit document.getElementById
das output-Element über seine id info
angesprochen und mit innerText mit dem auszugebenden Text gefüllt.
Ein weiterer Vorteil dieser Methode ist die Möglichkeit den Ausgabetext beliebig mit CSS zu gestalten.
Dies war die früher übliche Methode, mit JavaScript auf einzelne Elemente zuzugreifen. Da man nicht genau wusste, welche Elemente später als Zugriffspunkte benötigt würden, wurden sicherheitshalber viele id-Attribute vergeben, die das HTML-Markup (womöglich noch in Verbindung mit präsentationsbezogenen Klassennamen ) unnötig aufblähten.
- Verwenden Sie die passenden Elemente und nutzen Sie deren browsereigene Funktionalität!
- Setzen Sie ids und Klassennamen nur sparsam ein.
Da diese Art des Elementzugriffs eigentlich umständlich war, entwickelten Frameworks wie jQuery eine Methode, die den direkten Zugriff auf Elemente über ihren Tag-Namen oder über Klassen und Attribute ermöglichte. Diese querySelector-Methode wurde in natives JavaScript übernommen und wird von allen Browsern verstanden.
Im Folgenden verwenden wir die vielseitigere querySelector()-Methode. Sie benötigt als Parameter einen „normalen“ CSS-Selektor und ist daher vielseitiger als das traditionelle getElementById().
<output></output>
<script>
'use strict';
let text = 'Hallo Welt!';
document.querySelector('output').innerText = text;
</script>
Das (noch) leere output-Element wird über die querySelector()-Methode angesprochen und mit innerText mit dem auszugebenden Text gefüllt.
document.getElementById()
, das nur Elemente anspricht, die ein eindeutiges, unverwechselbares id-Universalattribut besitzen, sucht die querySelector-Methode nach den im CSS üblichen Selektoren wie Elemente, Klassen und IDs, aber auch ARIA-Attributen, wie wir später sehen werden.Sie spricht das erste gefundene Element an. Mit QuerySelectorAll könnten Sie alle vorhandenen Vorkommen ansprechen.
Mit diesen Methoden können Sie auf das DOM (und dessen Elementknoten) einer Webseite zugreifen:
- querySelector: gibt das erste Element zurück, das dem angegebenen CSS-Selektor entspricht
- querySelectorAll: gibt eine Liste von Elementen zurück, die dem angegebenen CSS-Selektor entsprechen
- getElementsByClassName: gibt eine Liste von Elementen zurück, die der angegebenen Klasse entsprechen
- getElementById: gibt das Element zurück, das die angegebene id besitzt.
- getElementsByTagName: gibt eine Liste von Elementen zurück, die den angegebenen Namen haben.
Textknoten ansprechen
Die meisten Elemente wie Überschriften, Absätze, Links und Buttons enthalten neben möglichen Kind-Elementen noch Textknoten mit dem eigentlichen Inhalt der Webseite.
Im oberen Beispiel wurde dieser Textknoten mit innerText verändert:
document.querySelector('#info').innerText = text;
Des Weiteren existiert mit innerHTML eine weitere Methode, mit der Sie nicht nur Text, sondern sogar weitere HTML-Kindelemente einfügen können.
document.querySelector('#info').innerHTML = '<strong>' + text + '</strong>';
mehrere Elemente gleichzeitig ansprechen
Die querySelector()-Methode gibt das erste Element, auf den der Selektor zutrifft, zurück - alle anderen werden ignoriert. Um mehrere Elemente zu selektieren, kann man die querySelectorAll()-Methode verwenden.
document.querySelectorAll('article img') // alle img-Elemente innerhalb von article
document.querySelectorAll('h2, h3') // alle h2 + h3 Überschriften
document.querySelectorAll('input[type="number"]') //alle inputs mit type="number"
document.querySelectorAll('tr:nth-child(odd)') // alle Tabellenreihen mit ungeradem Index
Die querySelectorAll()-Methode gibt nun eine statische NodeList zurück. Diese ist trotz aller Ähnlichkeit kein Array, kann aber in aktuellen Browsern mit einer for...of-Schleife durchlaufen werden. Darüber hinaus unterstützen die Browser auch von Arrays bekannte forEach-Methode, auch wenn die DOM-Spezifikation das nicht vorschreibt. Die mit allen Browsern kompatible Lösung ist, eine NodeList mit einer Zählschleife zu durchlaufen:
const elements = document.querySelectorAll('article > .beispiel');
for (let index = 0; index < elements.length; index++) {
elements[index].classList.add('geändert');
}
Einfacher ist es mit einer for...of-Schleife:
document.getElementById('changer').addEventListener('click', changeClasses);
function changeClasses() {
const elements = document.querySelectorAll('article > .beispiel');
for (let element of elements)
element.classList.add('geändert');
});
}
Im Beispiel werden bei click auf den Button alle Elemente mit der Klasse .beispiel
, die direkte Kindelemente eines <article>
sind, ermittelt. Die NodeList mit dem Suchergebnis wird in elements
gespeichert. NodeList-Objekte sind iterierbar, deshalb kann man die for...of-Schleife nutzen, um die gefundenen Elemente nacheinander zu verarbeiten. Im Schleifenrumpf erhalten die Suchtreffer mit classList.add eine weitere Klasse geändert
.
text
von zwei Zeichenketten umschlossen, in denen sich das Markup für ein strong-Element befindet. Wenn der Code ausgeführt wird, ändert sich nicht nur der Textknoten, sondern es wird ein strong-Element in den Elementbaum eingefügt.