Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einleitung
2 Webbrowser
3 JavaScript einbauen
4 Programmieren mit JavaScript
5 Datum
6 Zufall
7 Browserinformationen
8 Fenster
9 Formulare
10 Frames und Iframes
11 Grafiken
12 Cookies
13 Objekte und Arrays
14 Ereignisbehandlung
15 Fehlerbehandlung
16 DOM
17 DHTML und CSS
18 AJAX
19 XML
20 Web Services
21 AJAX-Frameworks
22 Plugins
23 Multimedia
24 Java
25 Serverseitige Technologien
26 JavaScript goes .NET
27 Code schützen
28 Top Secret: Passwortschutz
29 Signierte Skripte
30 JavaScript und Sicherheit
31 Navigation
32 Warenkorb
33 JavaScript-Bibliotheken
34 Referenz
35 Quellen im Web
36 Die Zukunft von JavaScript
Index
Download: - ZIP, ca. 9,2 MB
Buch bestellen
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> / JavaScript und AJAX | vor >>
JavaScript und AJAX von Christian Wenz Das umfassende Handbuch
JavaScript und AJAX 839 S., mit DVD, 39,90 Euro Galileo Computing ISBN 3-89842-859-1 |
| Kapitel 16 DOM
|  | 16.1 Der DOM-Baum
|  | 16.2 Navigation im Baum
|  | 16.3 Den Baum modifizieren
|  |  | 16.3.1 Wichtige Methoden
|  |  | 16.3.2 Zugriff auf einzelne Elemente
|  |  | 16.3.3 Zugriff auf Tags
|  |  | 16.3.4 Beispiele
## 16.3 Den Baum modifizieren Der große Vorteil von DOM gegenüber DHTML und den früheren DOM-Implementierungen besteht darin, dass man Elemente nicht nur ändern, sondern auch entfernen und sogar neue Elemente einfügen kann. Die Baumstruktur ist hier von großem Vorteil, da das Löschen eines Knotens nicht die Baumintegrität gefährdet. ### 16.3.1 Wichtige Methoden In der folgenden Tabelle sehen Sie eine grobe Übersicht über die verschiedenen Methoden.

Tabelle 16.3 Methoden zur Veränderung des DOM-Baums

Methode | Syntax | Beschreibung
appendChild | Vater.appendChild(Kind) | Hängt Kind als Kindknoten an Vater an.
cloneNode | Original.cloneNode (alles) | Erzeugt einen Knoten, der identisch mit Original ist. Ist alles gleich true, so werden auch alle Kindknoten von Original mit dupliziert; bei false lediglich der Knoten selbst.
createElement | document.createElement (HTML-Tag) | Erzeugt einen Knoten, der aus dem in Klammern angegebenen HTML-Element (z. B. h3) besteht.
hasChildNodes | Knoten.hasChildNodes() | Boolescher Wert, der angibt, ob Knoten Kinder hat oder nicht.
insertBefore | Vater.insertBefore(Kind, Schwester) | Kind wird als Kindknoten von Vater eingefügt, und zwar direkt vor Schwester.
removeNode | Knoten.removeNode(alles) | Knoten wird aus dem DOM-Baum entfernt. Ist alles gleich true, dann werden auch alle Kindknoten von Knoten entfernt.
replaceNode | Alt.replaceNode(Neu) | Der Knoten Alt wird durch den Knoten Neu ersetzt.
setAttribute | Knoten.setAttribute( Name, Wert) | Der Knoten enthält ein neues Attribut.
In einem kleinen Beispiel soll dies einmal ausprobiert werden. Wir gehen von dem obigen Beispiel-HTML-Dokument aus und bauen die folgenden Effekte ein:
| Wenn der Benutzer mit der Maus auf eine der Grafiken klickt, soll diese durch eine andere Grafik ausgetauscht werden.
| Wenn der Benutzer noch einmal auf die Grafik klickt, soll sie komplett verschwinden (eine Art armseliges Ballerspiel mit JavaScript also).
Der Einfachheit halber werden die Event-Handler der Grafiken schon im ursprünglichen HTML-Dokument gesetzt. Es muss also nur noch eine Funktion geschrieben werden, die überprüft, ob die Grafik schon einmal angeklickt worden ist, und dann entweder die Grafik austauscht oder den Knoten aus dem DOM-Baum entfernt. Alternative Möglichkeiten des Event-Handlings finden Sie in Kapitel 14. ### 16.3.2 Zugriff auf einzelne Elemente Jetzt benötigen Sie nur noch eines: den Startpunkt. Dafür gibt es eine weitere Methode des document-Objekts, und zwar getElementById(). Diese ermöglicht Ihnen den Zugriff auf jedes HTML-Element, solange es nur eine ID besitzt. Diese ID nämlich übergeben Sie als Parameter. So greifen Sie beispielsweise per document.getElementById("alles") auf das <body>-Element zu und können von dort ab alle Kindknoten (sprich: die Elemente der HTML-Seite) erreichen. Der folgende Code ist kurz und einleuchtend und wird daher ohne längere Vorrede abgedruckt. Er enthält allerdings noch einen kleinen (absichtlichen) Fehler, dazu später mehr.
    <html>
    <head>
    <title>DOM-Demo</title>
    <script type="text/javascript"><!--
    function mausklick(Nummer){
       var obj = document.getElementById("alles").childNodes[Nummer + 1];
       var gfx = obj.src;
       if (gfx.indexOf("ball.gif") > –1) {
          obj.src="kreuz.gif";
       } else {
          obj.removeNode(false);
       }
    }
    //--></script>
    </head>
    <body id="alles">
    <h3 id="Ueberschrift">DOM-Demo</h3>
    <img src="ball.gif" id="Ball1" onclick="mausklick(1);" />
    <img src="ball.gif" id="Ball2" onclick="mausklick(2);" />
    <img src="ball.gif" id="Ball3" onclick="mausklick(3);" />
    <img src="ball.gif" id="Ball4" onclick="mausklick(4);" />
    </body>
    </html>
Hier klicken, um das Bild zu Vergrößern Abbildung 16.4 Die DOM-Demo im Internet Explorer Wie Ihnen sicherlich nicht entgangen ist, spuckt der Browser hin und wieder Fehlermeldungen bei der Ausführung dieses Skripts aus, beispielsweise, wenn Sie auf die dritte Grafik von links klicken. Sehr merkwürdig! Zum Testen sollten Sie in die Funktion mausklick() den folgenden Debug-Code einfügen (am besten gleich am Anfang):
    function mausklick(Nummer) {
       var meldung = "";
       for (var i=0; i<document.getElementById("alles").childNodes.length; i++) {
          meldung += document.getElementById("alles").childNodes[i].nodeName +
    "|" + document.getElementById("alles").childNodes[i].nodeType + "\n";
       }
       alert(meldung);
       var obj = document.getElementById("alles").childNodes[Nummer + 1];
       var gfx = obj.src;
       if (gfx.indexOf("ball.gif")>-1) {
          obj.src="kreuz.gif";
       } else {
          obj.removeNode(false);
       }
    }
Hier klicken, um das Bild zu Vergrößern Abbildung 16.5 Die Debug-Ausgabe In Abbildung 16.5 (oder auch im DOM Inspector) sehen Sie die Ursache des Übels: Anscheinend befinden sich zwischen den einzelnen Grafiken noch Textstücke. Auch das ist nicht weiter verwunderlich: Auch wenn ein Zeilenumbruch im HTML-Code in der Anzeige quasi nie Auswirkungen hat, ist das beim DOM-Baum ein Textelement. Sie sollten also die Zeilenumbrüche entfernen, dann gibt es beim ersten Anklicken einer Grafik auch keine Fehlermeldungen mehr. Um diese Fehlermeldungen zu vermeiden, sollten Sie die HTML-Elemente, die Sie in Ihrem Skript verwenden wollen, mit den oben gezeigten Methoden (createElement(), setAttribute() und appendChild() bzw. insertBefore()) erzeugen. Das obige HTML-Dokument kann auch folgendermaßen erzeugt werden (von der Klick-Funktionalität mal abgesehen):
    <html>
    <head>
    <title>DOM-Demo</title>
    <script type="text/javascript"><!--
    function init() {
       var basis = document.getElementById("alles");
       var h3 = document.createElement("h3");
       h3.setAttribute("id", "Ueberschrift");
       h3.innerText = "Überschrift";
       basis.appendChild(h3);
       for (var i=1; i<=4; i++) {
          img = document.createElement("img");
          img.setAttribute("id", "Ball" + i);
          img.src = "ball.gif";
          basis.appendChild(img);
       }
    }
    //--></script>
    </head>
    <body id="alles" onload="init();">
    </body>
    </html>
Ein kleiner Vorgriff war dabei: innerText bezeichnet den Text innerhalb eines HTML-Elements. Eine Alternative dazu gibt es auch noch: Der Text innerhalb eines HTML-Elements ist wie bereits gesehen ein Knoten, und zwar ein Textknoten. Mit den DOM-Methoden von JavaScript können Sie auch einen solchen Knoten erzeugen (die dazugehörige Methode heißt document.createTextNode()) und diesen dann in den DOM-Baum einhängen – als Unterknoten des übergeordneten Elements natürlich:
    <html>
    <head>
    <title>DOM-Demo</title>
    <script type="text/javascript"><!--
    function init() {
       var basis = document.getElementById("alles");
       var h3 = document.createElement("h3");
       h3.setAttribute("id", "Ueberschrift");
       textknoten = document.createTextNode("Überschrift");
       h3.appendChild(textknoten);
       basis.appendChild(h3);
       for (var i=1; i<=4; i++) {
          img = document.createElement("img");
          img.setAttribute("id", "Ball" + i);
          img.src = "ball.gif";
          basis.appendChild(img);
       }
    }
    //--></script>
    </head>
    <body id="alles" onload="init();">
    </body>
    </html>
Wie Sie in einer Aufgabe am Ende des Kapitels jedoch noch sehen werden, ist das ursprüngliche Skript nicht ganz fehlerfrei. Es ist einfach gefährlich, über den Index auf ein Element zuzugreifen, wenn zwischendurch Elemente entfernt werden sollen. Aber Sie haben ja bereits an anderer Stelle schon gesehen, dass es fast immer besser ist, per Identifikator auf ein Element zuzugreifen. Hier ist das auch der Fall – verwenden Sie einfach getElementById() für die einzelnen Bälle. Im folgenden Code finden Sie das für unser kleines Beispiel einmal umgesetzt. Anhand der Nummer, die an mausklick() übergeben wird, kann der Identifikator der angeklickten Grafik ermittelt werden, und dieser Wert wird dann an getElementById() übergeben.
    function mausklick(Nummer){
       var obj = document.getElementById("Ball" + Nummer);
       var gfx = obj.src;
       if (gfx.indexOf("ball.gif") > –1) {
          obj.src="kreuz.gif";
       } else {
          obj.removeNode(false);
       }
    }
### 16.3.3 Zugriff auf Tags Es gibt noch eine Alternative zum Knotenzugriff via ID: Sie können auch spezifisch auf Tags zugreifen. Die entsprechende Methode des document-Objekts heißt getElementsByTagName(). Beachten Sie den Plural (Element s), denn Sie erhalten auf jeden Fall ein Array zurück, auch wenn es nur ein entsprechendes Element auf der Seite gibt. Damit lässt sich im ursprünglichen, absichtlich fehlerhaften Beispiel etwa die ID für das <body>-Element einsparen:
    <html>
    <head>
    <title>DOM-Demo</title>
    <script type="text/javascript"><!--
    function mausklick(Nummer){
       var basis = document.getElementsByTagName("body")[0];
       var obj = basis.childNodes[Nummer + 1];
       var gfx = obj.src;
       if (gfx.indexOf("ball.gif") > –1) {
          obj.src="kreuz.gif";
       } else {
          obj.removeNode(false);
       }
    }
    //--></script>
    </head>
    <body>
    <h3 id="Ueberschrift">DOM-Demo</h3>
    <img src="ball.gif" id="Ball1" onclick="mausklick(1);" />
    <img src="ball.gif" id="Ball2" onclick="mausklick(2);" />
    <img src="ball.gif" id="Ball3" onclick="mausklick(3);" />
    <img src="ball.gif" id="Ball4" onclick="mausklick(4);" />
    </body>
    </html>
### 16.3.4 Beispiele Zum Abschluss dieser DOM-Einführung noch zwei kleine Beispiele, die aufzeigen, wie Sie per DOM schnell Elemente der aktuellen Seite hinzufügen können – eine Technik, die in Kapitel 18 wichtig werden wird. Wir beginnen mit einer Aufzählungsliste:
    <ul id="Liste"></ul>
Wie Sie sehen, ist die Liste leer. Die Daten für die Liste stehen in folgendem Objekt:
    var daten = [
       {"text": "Mozilla", "url": "http://www.mozilla.com/"},
       {"text": "Microsoft", "url": "http://www.microsoft.com/"},
       {"text": "Opera", "url": "http://www.opera.com/"}
    ];
Unser Ziel ist es nun, diese Daten in die Liste einzufügen, und zwar als verlinkten Text. Werfen wir einen Blick auf das entsprechende Markup für ein Listenelement:
    <li><a href="http://www.mozilla.com/">Mozilla</a></li>
Wir müssen also die folgenden DOM-Elemente erzeugen:
| Das <li>-Element
| Das <a>-Element samt dem Attribut href
| Den Textknoten mit dem Linktext
Am Ende müssen Sie diese Elemente untereinander einhängen: den Textknoten unterhalb des Links, den Link unterhalb des Listenelements, und natürlich abschließend das Listenelement unterhalb der Liste selbst. Sie sehen: Das ist zu Anfang ein wenig ungewohnt und auch etwas aufwändig, geht aber nach wiederholtem Üben sehr leicht von der Hand. Hier ist das vollständige Listing:
    <html>
    <head>
    <title>DOM-Demo</title>
    <script type="text/javascript"><!--
    var daten = [ {"text": "Mozilla", "url":
    "http://www.mozilla.com/"}, {"text": "Microsoft", "url":
    "http://www.microsoft.com/"}, {"text": "Opera", "url": "http://www.opera.com/"}
    ];

    window.onload = function() {
       var liste = document.getElementById("Liste");
       for (var i = 0; i < daten.length; i++) {
          var link = daten[i];
          var li = document.createElement("li");
          var a = document.createElement("a");
          a.setAttribute("href", link.url);
          var txt = document.createTextNode(link.text);
          a.appendChild(txt);
          li.appendChild(a);
          liste.appendChild(li);
       }
    }
    //--></script>
    </head>
    <body>
    <ul id="Liste"></ul>
    </body>
    </html>
Natürlich können Sie statt document.getElementById("Liste") im vorliegenden Beispiel auch document.getElementsByTagName("ul")[0] verwenden. Hier klicken, um das Bild zu Vergrößern Abbildung 16.6 Die dynamisch per DOM erzeugte Liste Das zweite Beispiel soll etwas komplexer sein: Diesmal soll eine komplette Tabelle erzeugt und in den DOM-Baum eingehängt werden. Dabei gibt es eine wichtige Besonderheit: Unter bestimmten Umständen ist der Internet Explorer sehr wählerisch, was den (korrekten) Aufbau einer per DOM erzeugten Tabelle betrifft. Die Tabellenzellen müssen nämlich im <tbody>-Element platziert werden (und etwaige <th>-Zellen innerhalb von <thead>). Von der Technologie her ist das nichts Neues: Sie erzeugen Elemente mit createElement() und hängen sie per appendChild() untereinander. Hier der Code für <thead>:
    var table = document.createElement("table");
    var thead = document.createElement("thead");
    var tr = document.createElement("tr");
    var th1 = document.createElement("th");
    var th1text = document.createTextNode("Hersteller");
    th1.appendChild(th1text);
    var th2 = document.createElement("th");
    var th2text = document.createTextNode("URL");
    th2.appendChild(th2text);
    tr.appendChild(th1);
    tr.appendChild(th2);
    thead.appendChild(tr);
    table.appendChild(thead);
Auch der <tbody>-Abschnitt bietet wenig Neues, Sie müssen nur eine Menge Elemente erstellen. Eine kleine Besonderheit gibt es jedoch schon: Der Linktext und der Text in der linken Spalte sollen identisch sein. Sie können aber einen Knoten nicht an zwei Stellen in den DOM-Baum einhängen, denn Knoten werden wie Referenzen oder Zeiger gehandhabt, nicht wie Kopien. Das heißt, Sie müssen zunächst eine Knotenkopie erzeugen, was die Methode cloneNode() erledigt. Diese Methode erwartet als Parameter die Angabe, ob auch Unterknoten mit dupliziert werden sollen (true) oder nicht (false). Da der Textknoten selbst keine Unterknoten besitzt, genügt die Angabe false:
    var tbody = document.createElement("tbody");
    for (var i = 0; i < daten.length; i++) {
       var link = daten[i];
       var tr = document.createElement("tr");
       var td1 = document.createElement("td");
       var td1txt = document.createTextNode(link.text);
       td1.appendChild(td1txt);
       var td2 = document.createElement("td");
       var a = document.createElement("a");
       a.setAttribute("href", link.url);
       a.appendChild(td1txt.cloneNode(false));
       td2.appendChild(a);
       tr.appendChild(td1);
       tr.appendChild(td2);
       tbody.appendChild(tr);
    }
Das war es auch schon fast, die Tabelle muss nur noch fertiggestellt und in das Dokument eingefügt werden:
    table.appendChild(tbody);
    var body = document.getElementsByTagName("body")[0];
    body.appendChild(table);
Hier noch einmal der komplette Code im Überblick:
    <html>
    <head>
    <title>DOM-Demo</title>
    <script type="text/javascript"><!--
    var daten = [ {"text": "Mozilla", "url":
    "http://www.mozilla.com/"}, {"text": "Microsoft", "url":
    "http://www.microsoft.com/"}, {"text": "Opera", "url": "http://www.opera.com/"}
    ];

    window.onload = function() {
       var body = document.getElementsByTagName("body")[0];
       var table = document.createElement("table");

       var thead = document.createElement("thead");
       var tr = document.createElement("tr");
       var th1 = document.createElement("th");
       var th1text = document.createTextNode("Hersteller");
       th1.appendChild(th1text);
       var th2 = document.createElement("th");
       var th2text = document.createTextNode("URL");
       th2.appendChild(th2text);
       tr.appendChild(th1);
       tr.appendChild(th2);
       thead.appendChild(tr);
       table.appendChild(thead);

       var tbody = document.createElement("tbody");
       for (var i = 0; i < daten.length; i++) {
          var link = daten[i];
          var tr = document.createElement("tr");

          var td1 = document.createElement("td");
          var td1txt = document.createTextNode(link.text);
          td1.appendChild(td1txt);
          var td2 = document.createElement("td");
          var a = document.createElement("a");
          a.setAttribute("href", link.url);
          a.appendChild(td1txt.cloneNode(false));
          td2.appendChild(a);

          tr.appendChild(td1);
          tr.appendChild(td2);
          tbody.appendChild(tr);
       }
       table.appendChild(tbody);

       body.appendChild(table);
    }
    //--></script>
    </head>
    <body>
    </body>
    </html>
Hier klicken, um das Bild zu Vergrößern Abbildung 16.7 Die dynamisch per DOM erzeugte Tabelle Sie sehen also: Das ist viel Tipparbeit, aber doch eigentlich gar nicht so schwierig. Die JavaScript-Programmierung wird sich zweifelsohne mehr in Richtung DOM bewegen – das steht außer Frage. Da die Browser der Versionsnummer 4 ausgestorben sind (so kennen weder der Internet Explorer 4 noch der Netscape 4 die DOM-Methoden wie beispielsweise getElementById() oder document.getElementsByTagName()), kann man mittlerweile DOM mit gutem Gewissen einsetzen. Allerdings ist das Denken in Baumstrukturen nicht immer intuitiv; schöner ist es doch, mit dem bekannten JavaScript-Objekten wie etwa Image oder den Formularfeldern zu arbeiten. Der Trend geht jedoch langsam, aber sicher hin zu DOM. Warum? Weil Sie damit vor allem Text auf einer Seite verändern und neue HTML-Elemente hinzufügen können, wie weiter oben gezeigt wurde. Die folgenden Kapitel stehen ganz im Zeichen dieser Einsatzszenarios und zeigen DHTML und insbesondere AJAX: moderne Ansätze für die JavaScript-Programmierung, die der Sprache einen neuen Aufwind gegeben haben.
<< zurück | <top> | vor >>
Zum Katalog
JavaScript und AJAX bestellen
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Buchtipps
| JavaScript und AJAX - Das Video-Training
| Webseiten programmieren und gestalten
| XHTML, HTML und CSS
| CSS-Praxis
| AJAX
| PHP 5 und MySQL 5
| TYPO3 4.0
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de