7 Min

DOM-Manipulation in JavaScript: Ein Einsteiger-Guide

Das Document Object Model (DOM) ist eine strukturierte Darstellung einer Webseite, die es Web-Entwicklern ermöglicht, mit HTML- und XML-Dokumenten auf der Website zu interagieren. Es fungiert als Brücke zwischen der statischen Webseite und der dynamischen Manipulation durch JavaScript, wodurch Inhalte und Stilelemente in Echtzeit verändert werden können. Im Frontend-Development können Entwickler das DOM verwenden, um durch JavaScript oder CSS auf einzelne Elemente zuzugreifen, sie zu verändern oder zu löschen, was interaktive User Experiences ermöglicht. Das DOM ist ein entscheidender Bestandteil bei der Erstellung moderner Webanwendungen.

Die drei grundlegenden Operationen auf dem DOM sind:

  1. Elemente ändern
  2. Elemente hinzufügen
  3. Elemente löschen

In diesem Artikel schauen wir uns die drei Operationen nacheinander an.

1. Elemente ändern

Nehmen wir an, wir möchten den Titel der Website “Webdev-Guide.net” ändern. Der Titel Webdev Guide steht im Masthead der Website oben, neben dem Blitz-Icon. Um auf den Titel zuzugreifen, suchen wir in der Dev-Console nach genau dem Element.

Im HTML-Markup der Website sehen wir, dass der Titel ein anchor-link ist, zu sehen am HTML-Element <a class="site-title" href="/">"Webdev Guide"</a>. Um auf das Element zuzugreifen, müssen wir es holen. Das können wir auf verschiedene Arten erledigen. Hier ist eine Möglichkeit:

let elem = document.getElementsByClassName('site-title')[0];
  • document.getElementsByClassName('site-title'): Diese Methode greift auf alle HTML-Elemente im Dokument zu, die die CSS-Klasse site-title enthalten. Sie gibt eine Sammlung von Elementen (HTMLCollection) zurück.

  • [0]: Da die Methode eine HTMLCollection zurückgibt, wird mit [0] auf das erste Element dieser Sammlung zugegriffen.

  • let elem: Dieses Element (das erste mit der Klasse site-title) wird der Variablen elem zugewiesen.

Geben wir dem Titel nun irgendeinen anderen Namen:

elem.innerHTML = "Godzilla was here"

Wenn du den Code in deiner Dev-Console ausführst, sollte der Titel “Webdev Guide” zu “Godzilla was here” updaten.

Hier ist eine andere Möglichkeit, den Titel zu ändern:

document.querySelector(".masthead .site-title").innerText = "Rage against the Machine Learning"

Die Methode document.querySelector(".masthead .site-title") sucht nach dem ersten HTML-Element im Dokument, das mit dem CSS-Selektor übereinstimmt. In diesem Fall wird das erste Element innerhalb eines Containers mit der Klasse .masthead gesucht, das die Klasse .site-title enthält. Der CSS-Selektor ".masthead .site-title" bedeutet, dass site-title ein Nachfahre von masthead ist.

Hier ist noch eine Möglichkeit, den Titel zu ändern:


document.querySelectorAll("a[href='/']")[1].innerHTML = "All fine now?"

  • document.querySelectorAll("a[href='/']"): Diese Methode wählt alle <a>-Elemente (also Links) aus, die ein href-Attribut mit dem Wert '/' haben.

  • [1]: Da wir im DOM zwei anchor-Links haben (der erste anchor ist das Blitz-Icon). selektieren wir nach querySelectorAll das zweite Element aus dieser Liste. Arrays sind nullbasiert, daher ist der Index 1 das zweite Element. Das ist unser .site-title

  • .innerHTML = "All fine now?": Diese Anweisung setzt den HTML-Inhalt des ausgewählten Links (dem zweiten a-Tag mit href='/') auf den Text "All fine now?".

Du siehst: Es gibt mehrere Möglichkeiten, das DOM zu manipulieren.

Schauen wir uns nun an, wie wir neue HTML-Elemente erzeugen und hinzufügen können.

2. Elemente hinzufügen

Wenn wir ein Element hinzufügen wollen, müssen wir das Element zuerst erzeugen und dann mit einer Anweisung, wo wir das Element platzieren wollen, ins DOM hinzufügen:

// Wir erzeugen ein neues Element:
let elem = document.createElement("div")
elem.innerHTML = "New Content coming Soon!"

// Wir selektieren das Element, dem wir das das neue Element prependen wollen: 
let icon = document.querySelector("a[href='/']")

// Wir fügen das neue Element hinzu:
icon.parentNode.insertBefore(elem, icon.nextSibling)

Im Masthead der Website sollte jetzt das neue Element auftauchen.

Warum ist icon.parentNode.insertBefore(elem, icon.nextSibling) eine so umständlich formulierte Anweisung? Es ist ein ständiges Problem im DOM als auch in allen Node-basierten Datenstrukturen allgemein:

Nimm dir irgendein Element im Dokument. Das Element weiß nur von sich selbst. Wenn du links oder rechts neben dem Dokument etwas ausführen möchtest, musst du das Parent-Element auswählen. Child-Elemente haben keinen Zugriff auf die Parent-Element, aber Parent-Elemente haben Zugriff auf ihre Child-Element. Wenn du Elemente dem DOM hinzufügen möchtest, musst du also das Parent Element finden. Das erledigst du mit icon.parentNode.

Die grundsätzliche Syntax zum hinzufügen von Elementen lautet:

referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);

Where referenceNode is the node you want to put newNode after. If referenceNode is the last child within its parent element, that’s fine, because referenceNode.nextSibling will be null and insertBefore handles that case by adding to the end of the list.

3. Elemente löschen

Das Entfernen von Elementen aus dem DOM ist simpel:

element.remove()

Sagen wir, dass wir das Icon vom DOM löschen wollen. Das machen wir mit:

let logo = document.querySelector(".site-logo")
logo.remove()

Wir hätten das logo auch verbergen können mit:

let logo = document.querySelector(".site-logo")
logo.style.visibility = "hidden"

Doch damit verbliebe das Logo nur unsichtbar im DOM, wohingegen das Kommando logo.remove() eine expliziten Löschung des Elementes vom DOM bewirkt.

Falls deine Console einen Fehler meldet: Cannot read properties of null liegt das vermutlich daran, dass du das Element logo bereits gelöscht hast und somit auf null zuzugreifen versuchst. Um den Fehler zu beheben, lade das Fenster, indem du F5 drückst, oder in der Console document.location.reload eintippst, und probiere es nochmal.


Ein praktisches Beispiel

Die Beispiele, die ich nannte, sind für das Verständnis des DOMs zwar wichtig, aber nicht wirklich praktisch. Hier habe ich ein praktisches Beispiel für dich:

javascript:(function() {
  var h = document.getElementsByTagName("head")[0];
  var s = document.createElement("style");
  s.setAttribute("type", "text/css");
  s.appendChild(document.createTextNode(`
	  html { 
		  -webkit-filter: invert(100%) hue-rotate(180deg) contrast(70%) !important; 
		  background: #fff;
	  } 
	  
	  .line-content {
		  background-color: #fefefe;
	  }`
	));
  h.appendChild(s);
})();

Verstehst du, was in diesem Code passiert?

Falls du dich fragst, ob du den Code abtippen sollst, oder ob es genügt, den Code in deine Console zu Copy-Pasten: Copy-Pasten ist erlaubt, doch kopiere niemals Code, den du nicht verstehst. Als Webdeveloper musst du wissen, was du tust, erst Recht wenn der Code gefährlich wird. Den obigen Code kannst du bedenklos in deine Dev-Console Copy-Pasten, denn der Code ist ungefährlich (Oder etwa nicht? ;))

Der Code bewirkt Folgendes:

  1. Selbstaufrufende Funktion: Der Code ist in einer selbstaufrufenden anonymen Funktion gekapselt, was bedeutet, dass er sofort nach seiner Definition ausgeführt wird, ohne dass eine weitere Anweisung zum Aufruf der Funktion erforderlich ist. Du erkennst selbstaufrufende Funktionen daran, dass direkt nach der schließenden geschweiften Klammer } (In diesem Fall })) ein Funktionsaufruf über () erfolgt.

  2. head-Element ermitteln: Mit document.getElementsByTagName("head")[0] wird das erste <head>-Element des Dokuments ausgewählt. Im <head>-Bereich werden normalerweise Metadaten, Skripte und Stylesheets der Webseite geladen.

  3. Neues <style>-Element erstellen: Der Code erstellt ein neues <style>-Element mit document.createElement("style"). Dies ist ein HTML-Tag, das verwendet wird, um CSS-Regeln direkt in das Dokument einzubetten.

  4. CSS-Regeln definieren: Mit s.appendChild(document.createTextNode(...)) werden die CSS-Regeln in das erstellte <style>-Element eingefügt. Die Regeln beinhalten:

    • Invertierung und Farbanpassung: Die html-Regel wendet einen CSS-Filter an, der den gesamten Inhalt der Seite invertiert, die Farbtöne um 180 Grad verschiebt und den Kontrast auf 70 % reduziert. Dies verändert die gesamte Darstellung der Webseite erheblich, ähnlich wie bei einem “Dark Mode”.
    • Hintergrundfarbe der .line-content-Klasse: Es wird eine spezifische Regel für Elemente mit der Klasse .line-content hinzugefügt, die ihre Hintergrundfarbe auf ein helles Grau (#fefefe) setzt.
  5. Einfügen des <style>-Elements: Das erstellte <style>-Element mit den neuen CSS-Regeln wird in das <head>-Element der Webseite eingefügt, wodurch die definierten Styles sofort auf die Seite angewendet werden.

Ergebnis

  • Die gesamte Webseite wird farblich invertiert (weiße Flächen werden schwarz, und umgekehrt), die Farben werden angepasst, und Elemente mit der Klasse .line-content bekommen eine weiße Hintergrundfarbe.
  • Dieser Code könnte verwendet werden, um eine Art “Dark Mode” oder einen speziellen visuellen Filter auf eine Webseite anzuwenden.

Für Websites, die nur im Bright-Theme daherkommen, mag so ein Dark-Theme Switcher praktisch sein, doch mit dem nächsten Page-Refresh (F5) wird das Theme zurückgesetzt, und wir müssen die Funktion ein weiteres Mal in die Dev-Console eingeben und ausführen, um in den Genuss unseres Dark-Themes zu kommen. Wäre es nicht praktischer, wenn unser Dark-Theme Switcher für alle Websites, die wir mit unserem WebBrowser besuchen, verfügbar ist, sozusagen global und immer verfügbar? Das erreichen wir über Bookmarklets:

Bookmarklets

Das Bookmarklet ist der kleine Bruder des Browser-Plug-ins. Er wird als Bookmark gespeichert und führt Javascript auf der Page aus, auf der man sich gerade befindet. Wir werden unser Dark-Theme als Bookmarklet verfügbar machen. Und zwar so:

  1. Neues Lesezeichen hinzufügen:
    1. Navigiere zum Lesezeichen-Manager deines Webbrowsers. In den meisten Browsern erreichst du das über Strg+Umschalt+O, oder du klickst im Browsermenü auf „Lesezeichen“ und dann „Lesezeichen-Manager“ auswählen
    2. Klicke mit der rechten Maustaste in die Lesezeichenleiste oder den Ordner, in den du das Bookmarklet einfügen möchtest, und wähle „Neues Lesezeichen hinzufügen“ oder „Seite hinzufügen“ aus.
  2. Konfiguriere das Lesezeichen:
    1. Gib im Feld „Name“ einen Namen ein.
    2. Im Feld „URL“ fügst du den Javascript Code ein. Wichtig: Setze javascript: an den Anfang, also: javascript:(function() {..., um dem Webbrowser zu sagen, dass der Bookmark kein gewöhnliches Lesezeichen, sondern Javascript-Code ist.
    3. Speichere das Lesezeichen: Klicke auf „Speichern“ oder „Fertig“, um das Bookmarklet zu deiner Lesezeichenleiste oder Ordner hinzuzufügen.

Das Dark-Theme ist jetzt verfügbar für jede Website, die du besuchst. Gehe auf irgendeine Website und klicke auf das Bookmarklet, das du soeben hinzugefügt hast. Manche Website wirken im Dark Theme ganz schön hässlich, doch du wirst feststellen, dass webdev-guide.net im Dark-Theme einfach stylisch rüberkommt!

Updated: