WMP Webstandards

Das Document Object Model

zurück zur Übersicht

Nach oben

Javascript und HTML

Javascript in HTML zu verwenden, macht meist nur dann Sinn, wenn es in der Lage ist, den Inhalt einer Seite anzupassen und zu verändern.

Zu diesem Zweck gibt es zwei gebräuchliche Methoden:

Beide Methoden funktionieren einwandfrei und sind mittlerweile auch sehr kompatibel.

Nach oben

Nachteile

Leider haben nur beide Methoden einen großen Nachteil: Sie sind HTML spezifisch. innerHTML ist schon vom Namen her auf HTML bezogen. Auf XML Dokumente lässt sich damit also nicht zugreifen.

Nach oben

Das Document Object Model

Die w3c definiert das Document Object Model als "plattform- und sprachunabhängige Schnittstelle, die es Programmen und Scripten erlaubt, dynamisch Einfluss auf Inhalt, Struktur und Style von Dokumenten zu nehmen." Weiter heißt es, "Ein Dokument könne verarbeitet und das Resultat dieser Verarbeitung wieder in die präsentierte Seite einfließen."

Grob gesprochen ist das w3c DOM also der Versuch, eine einheitliche Schnittstelle für den Zugriff auf XML Dokumente zu erhalten. Wenngleich es vorrangig um (X)HTML geht, kann man es also auch zum Zugriff auf (andere) XML Daten verwenden.

Nach oben

XHTML

Will ein Entwickler XHTML verwenden, ist er auf das Document Object Model angewiesen: Als XML Sprache verfügt XHTML nicht mehr über die überholten Methoden zur Veränderung von Inhalten.

Das DOM ist hier also nicht nur Option, sondern einzige sinnvolle Möglichkeit zur Änderung von Dokumenten.

Diese Inkompatibilität macht sich nur bemerkbar, wenn man XHTML mit korrektem Content-Type, also nicht als text/html ausliefert.

Nach oben

Warum dieser Artikel?

Ich werde im Folgenden die Grundsätze des Document Object Models erläutern.

Ich werde dabei versuchen, Anfängern wie Fortgeschrittenen einen guten Zugang zur Materie zu verschaffen.

Minimale Javascript Kenntnisse sollten allerdings vorhanden sein.

Nach oben

Inhalt

Nach oben

Knotenpunkte

Der Idee von XML entsprechend unterteilt das DOM ein Dokument in Nodes (engl. Knoten) - jedes Element eines Dokuments ist ein eines Objekt.
Der Code

<p>
  Text
</p>

Enthält 2 Nodes: Zum einen den Absatz "p", zum anderen die so genannte Textnode "Text".

Nach oben

Zugriff auf Objekte

Jeder dieser Knotenpunkte besitzt mehrere Möglichkeiten, auf Kind- und Elternelemente zuzugreifen:

objekt.firstChild.parentNode würde also wieder auf objekt verweisen.

Der Internet Explorer interpretiert bei den Childnodes leider anders als andere Browser: Für ihn sind Leerstellen zwischen Tagnamen keine Textnodes. Das führt dazu, dass Firefox und Opera body.firstChild meist eine Textnode darstellt (Mit den Leerzeichen am Anfang eines HTML Body als Wert), man im Internet Explorer dagegen das erste Element zurückgegeben bekommt. Eine Lösung dieses Problems werde ich im unteren Beispiel aufführen.

Letztlich gibt es zwei sehr bekannte Methoden, auf Objekte zuzugreifen:

<body>
<div id="abs1">
  <p>
    Foobar
  </p>
</div>
 
<script type="text/javascript">
  var abs1 = document.getElementById("abs1");
     
  // Das erste Kindelement laden, dass kein leeres
  // Textelement ist
  // 3 steht für eine Textnode
  if(abs1.firstChild.nodeType == 3)
    myChild = abs1.childNodes[1];
  else
    myChild = abs1.firstChild;
     
  // myChild ist nun in jedem Fall das <p> Element
  // Dessen erstes Kindelement ist eine Textnode,
  // deren Wert "Foobar" sein sollte:
  alert(myChild.firstChild.nodeValue);
     
  // Wer aufgepasst hat, sollte nun auch wissen,
  // dass der Inhalt eines Knotens in der
  // Eigenschaft nodeValue steckt ;)
</script>
</body>
Nach oben

Neue Objekte erstellen

Neue Objekte zu erstellen ist denkbar einfach: Man kann entweder völlig neue Elemente erstellen oder bestehende kopieren.

Neue Objekte erstellt man über document.createElement(); als Parameter übergibt man den Namen des zu erstellenden Elements, z.B. p

Kopieren kann man Objekte über deren cloneNode() Methode, der man als Pareter übergeben kann, ob Kindknoten mitkopiert werden sollten. Hier sollte fast immer true angegeben werden.

neuerParagraph = document.createElement("p");
kopieDavon = neuerParagraph.cloneNode(true);

Auch TextNodes müssen erstellt werden, dafür bietet das document Objekt eine Funktion:

textNode = document.createTextNode("Text");

Als Parameter kann man einen Text übergeben.

Nach oben

Objekte einfügen

Sowohl Textnodes als auch Absätze bringen wenig, wenn man sie nicht ineinander, bzw. den Absatz in das Dokument einbauen kann.

Hierfür bietet das DOM mehrere Funktionen:

Verwirrt? Vielleicht verhilft ein Beispiel zu besserem Verständnis:

<script type="text/javascript">
  // Absatz erstellen
  Absatz = document.createElement("p");
 
  // Text für den Inhalt erstellen
  Text = document.createTextNode("Inhalt von Absatz 1");
 
  // Text einfügen
  Absatz.appendChild(Text);
 
  // Absatz in das Dokument einfügen
  document.body.appendChild(Absatz);
 
  // Einen neuen Absatz erstellen
  Absatz2 = document.createElement("p");
 
  // Wiederum einen Text einfügen
  Absatz2.appendChild(document.createTextNode("Absatz 2"));
 
  // Diesen Absatz vor dem ersten Absatz einfügen
  document.body.insertBefore(Absatz2, Absatz);
 
  // An den ersten Absatz eine weitere Textnode anfügen:
  Absatz.appendChild(document.createTextNode("Text"));
</script>
Nach oben

Objekte ändern

Natürlich kann man auch Objekte im Nachhinein ändern. Das geschieht über deren Eigenschaften.

Texte ändert man über die nodeValue Eigenschaft. Für weitere Attribute verwendet man die bekannten JS Möglichkeiten.

Das folgende Beispiel orientiert sich am Beispiel aus dem vorherigen Abschnitt:

<script type="text/javascript"> 
  // Referenz auf den ersten Textabschnitt des
  // Absatzes holen
  Text = Absatz.firstChild;
 
  // Text ändern
  Text.nodeValue = "Anderer Text";
  // Dies ändert nichts am Text "Text", der später
  // angefügt wurde, da er in einer anderen Node
  // abgelegt ist!!
 
  // Das Aussehen des Absatzes per CSS ändern
  Absatz.style.fontFamily = "monospace";
</script>
Nach oben

Objekte löschen

Um Objekte wieder zu löschen, muss man sie an die removeChild Methode des Elternelementes übergeben:

<script type="text/javascript"> 
  Absatz.removeChild(Absatz.lastChild);
  document.body.removeChild(Absatz2);
</script>

(Denkbar einfach, oder?)

Nach oben

Weitere Funktionen

Das DOM bietet noch weitere Funktionen zum Zugriff auf Elemente, die jedoch weniger häufig genutzt werden. Hier eine Übersicht über weitere wichtige Funktionen des Document Objektes. Für noch mehr Funktionen lies dich am Besten durch die Links.

Funktion Beschreibung
setAttribute Set ein Attribut für eine Node (z.B. href bei Links)
createElementNS Erstellt ein Element in einem anderen Namespace
replaceChild Ersetzt eine Node durch eine andere
Nach oben

Aufwändig?

Wenn du das alles ziemlich aufwändig findest, muss ich dir leider recht geben: Das sehe ich auch so.

Dennoch macht das DOM der w3c Sinn; und in XHTML hat man ohnehin keine andere Wahl, als es zu nutzen.

Von daher lohnt es auch nicht, sich zu beschweren :)

Nach oben

Sprachliche Anmerkung

Auch die browserspezifischen Zugriffsmodelle werden im Sprachgebrauch DOM genannt. Korrekterweise ist auch das w3c DOM unterteilt in mehrere Ebenen. Wenn man von "dem DOM" redet, ist aber meist das XML Modell der w3c gemeint.

Nach oben

Kommentare







07.05.2005 Löschen

fphilipe

Super Artikel.
Jedoch finde ich wenn du schon von XML sprichst, solltest du auch die XML Variante von createElement(), nämlich createElementNS(), ansprechen.

07.05.2005 Löschen

Pberndt

createElementNS ist nicht die XML Variante sondern lediglich die Variante für das Erstellen von Objekten in anderen Namespaces.. Hast aber recht, ich sollte zumindest einen Verweis darauf anlegen. Genau so auf createAttribute und replaceChild. Ich bau wohl heut nachmittag noch eine Methodenreferenz für das Document Objekt ein.

22.08.2006 Löschen

curi

Zu dem Code sollte vielleicht jedesmal noch ein Beispiel (?).
Wäre dann vielleicht anschaulicher :)

31.05.2007 Löschen

dipser

Ich hab mal einen Konverter von XML zu DOM geschrieben. Ich dachte auch, dass die gängigen Methoden einfach zu kompliziert sind, daher dachte ich, man muss doch enfach XML/XHTML an eine Funktion übergeben können und diese erzeugt für einen den DOM Knoten, wie auch innerHTML das tut. (innerHTML ist aber kein anerkannter Standard... wers braucht :D)
- renegat.org

Von pberndt. Letzte Änderung am 15.05.2005