![]() |
|
|||||
Es existieren zwei verschiedene Möglichkeiten, auf einen Knoten vom Typ HTML-Tag zuzugreifen:
document.getElementById (ID-String)
<p id="test">Spezieller Absatz, Marke test</p>
document.getElementsByTagName (Tag-String)
Auf Text- und Kommentarknoten können Sie nicht direkt zugreifen. Sie sind stets Kindknoten der umschließenden HTML-Tags. Auf die Kindknoten eines Elements sowie auf seinen Elternknoten und seine »Geschwister« können Sie mit Hilfe der in Tabelle 19.2 gezeigten Eigenschaften zugreifen:
Textknoten-Eigenschaften HTML-Tag-Knoten besitzen die Eigenschaft nodeName, die den Namen des eigentlichen HTML-Tags enthält. Text- und Kommentarknoten weisen dagegen die Eigenschaft nodeValue auf, die den Textinhalt enthält. nodeValue liefert möglicherweise etwas anderes zurück als Sie erwarten. Betrachten Sie beispielsweise den folgenden Auszug aus dem Body eines HTML-Dokuments:
Die alert()-Anweisung greift zunächst über die Methode getElementById() auf den Absatz mit der ID test zu. Anschließend liest sie per nodeValue den Textinhalt ihres ersten Kindknotens (firstChild). Vielleicht überrascht es Sie, zu hören, dass das Ergebnis nicht so lautet: Dies ist der alte Text Vielmehr bekommen Sie lediglich Folgendes zu sehen: Dies ist der Der Text »Dies ist der« bildet den ersten Kindknoten des Absatzes, das HTML-Tag <i>...</i> ist der zweite und der restliche »Text« der letzte. Textknoten ändern Das nächste Beispiel verwendet einige dieser Methoden und Eigenschaften zur Anzeige der aktuellen Uhrzeit im Fließtext eines Absatzes. Der Absatz selbst wird so definiert: <p id="uhr">Uhrzeit</p> Im Head steht folgende Funktion, die im <body>-Tag im Event-Handler onload aufgerufen werden sollte:
Das Thema Datums- und Uhrzeitanzeige wurde bereits weiter oben in diesem Kapitel behandelt. Neu ist hier lediglich die Zeile
Über getElementById() wird der Absatz mit der ID uhr angesprochen. Dessen erster Kindknoten firstChild ist der Absatztext, der mit Hilfe einer Wertzuweisung an seine Eigenschaft nodeValue geändert wird. Eine DOM-Baum-AnzeigeDas folgende Beispiel durchwandert rekursiv den DOM-Baum des aktuellen Dokuments und gibt in einem separaten Fenster Informationen über alle Knoten aus, die es dabei findet. Abbildung 19.3 zeigt das Skript bei der Arbeit. Listing 19.9 zeigt zuerst den Quellcode des gesamten HTML-Dokuments. Listing 19.10 Den DOM-Baum des aktuellen Dokuments ausgeben <html>
<head>
<title>DOM-Baumdiagramm</title>
<script language="JavaScript">
<!--
var infofenster;
function initDOMTree () {
infofenster =
open ("", "", "width=400,height=400");
showDOMTree (document, 0);
}
function showDOMTree (knoten, indentation) {
var typ = knoten.nodeType;
var typtext, info;
switch (typ) {
case 1:
typtext = "HTML-Tag";
info = knoten.nodeName;
break;
case 3:
typtext = "Text";
info = knoten.nodeValue;
break;
case 8:
typtext = "Kommentar";
info = knoten.nodeValue;
break;
case 9:
typtext = "Dokument";
info = "Das ganze HTML-Dokument";
break;
default:
typtext = "Anderer Typ";
info = "XML-Dokument?";
}
// Einrücken
for (var i = 0; i < indentation; i++) {
infofenster.document.write
(" ");
}
infofenster.document.write ("<b>" + typtext
+ "</b> (<i>" + info + "</i>)<br />");
// Kinder rekursiv bearbeiten
if (knoten.hasChildNodes ()) {
for (var j = 0;
j < knoten.childNodes.length; j++) {
showDOMTree (knoten.childNodes[j],
indentation + 1);
}
}
}
//-->
</script>
</head>
<body onload="initDOMTree();">
<!-- Jetzt geht's los! -->
<font size="4" color="#FF0000">Hier sehen Sie
<i>die DOM-Baumstruktur <b>des aktuellen
<u>Dokuments</u></b></i>.</font>
</body>
</html>
Im Grunde verwendet das Skript nur Funktionen, die bereits besprochen wurden, und benötigt deshalb nicht viel an Erläuterungen. Für die eigentliche Rekursion wird mit Hilfe der Methode knoten.hasChildNodes() überprüft, ob überhaupt Kindknoten vorhanden sind. Ist dies der Fall, dann werden sie in einer Schleife über alle Elemente des Arrays knoten.childNodes[] durchlaufen. Für jedes Kindelement wird wiederum die Funktion selbst aufgerufen; dabei wird der um 1 erhöhte Wert der Variablen indentation übergeben, um jeweils die korrekte Einrückung vorzunehmen. Beachten Sie bitte zuletzt, dass die explizite Deklaration der Schleifenzähler i und j mittels var hier absolut notwendig ist, weil sie ansonsten als globale Variablen betrachtet würden und so bei der Rekursion die falschen Werte hätten. DOM-Anwendung in der PraxisDas wichtigste Anwendungsgebiet von DOM ist es, nachträglich Veränderungen an Struktur und Inhalt des Dokuments vorzunehmen. Am häufigsten wird es verwendet, um die Positionierung und andere per Stylesheet definierte Eigenschaften von Layers zu ändern. Die bereits in Kapitel 16, HTML, vorgestellten Layers sind frei schwebende <div>-Elemente, die über das CSS-Attribut position an eine bestimmte Stelle gesetzt werden. Die festgelegte Position kann nachträglich geändert werden, um Animationen zu erzeugen. Abgesehen davon können Sie auch jede andere CSS-Eigenschaft ändern, beispielsweise Farben, Schriftformatierungen, die generelle Sichtbarkeit oder die Stapelreihenfolge. CSS-Formatierungen dynamisch ändern Über die DOM-Eigenschaft style können Sie auf die Stylesheet-Formatierungen von Layers (und beliebigen anderen HTML-Elementen) zugreifen und diese dynamisch ändern. Dabei besitzt style jeweils Untereigenschaften, deren Namen mit den Original-CSS-Attributen übereinstimmen. So können Sie etwa über top und left die Position eines absolut positionierten Layers ändern oder mittels color die Schriftfarbe modifizieren. Die einzige Besonderheit gilt für diejenigen Attribute, deren CSS-Name einen Bindestrich enthält: Statt dieses Sonderzeichens wird in üblicher JavaScript-Bezeichner-Konvention der darauf folgende Buchstabe großgeschrieben – aus background-color wird beispielsweise backgroundColor; text-align wird zu textAlign. Die Werte für die jeweiligen Stil-Eigenschaften sind Strings, deren Inhalt auf dieselbe Weise festgelegt wird wie bei Stylesheet-Angaben. Betrachten Sie zum Beispiel den folgenden Absatz: <p id="info">Der Hintergrund dieses Absatzes kann gelb werden!</p> Mit Hilfe der folgenden JavaScript-Anweisung können Sie seinen Hintergrund wie versprochen gelb einfärben:
Interessant ist in diesem Zusammenhang, dass neuere Browser Event-Handler wie onmouseover oder onmouseout für beinahe jedes Element unterstützen. So ist es zum Beispiel inzwischen weit verbreitet, in umfangreichen Tabellen die Zeile oder Zelle, in der sich der Cursor gerade befindet, durch Änderung der Hintergrundfarbe hervorzuheben. Die folgende Funktion kann durch einen solchen Handler aufgerufen werden, um die Farbänderung durchzuführen:
Hier sehen Sie eine Tabellenzeile, die bei Mausberührung mit Hilfe dieser Funktion ihre eigene Hintergrundfarbe ändert:
Layers manipulieren Die Manipulation der Eigenschaften von Layer-Objekten funktioniert im Prinzip genauso. Denken Sie daran, dass ein <div>-Element nur dann zum echten Layer wird, wenn es mit Hilfe des CSS-Attributs position auf eine feste Position gesetzt wird. Da sich HTML-Tag-Knoten am leichtesten über ihre ID ansprechen lassen, liegt es nahe, die CSS-Formatierung für den Layer in einer unabhängigen Stilangabe vorzunehmen, die dem Layer dann gleichzeitig mit seiner ID zugewiesen wird. Das Beispiel in Listing 19.10 lässt nach einer Wartezeit von drei Sekunden nach dem Laden einen Layer mit einem Bild von links in den sichtbaren Bereich des Fensters fahren; anschließend bleibt er fünf Sekunden stehen und wird schließlich ausgeblendet. Auf immer mehr Sites ist heute Werbung nach diesem Schema zu sehen. Listing 19.11 Ein aufdringliches Werbe-Popup in einem Layer <html>
<head>
<title>Aufdringliche Werbung</title>
<style type="text/css">
<!--
#werbung {
position: absolute;
top: 100px;
left: -200px
}
-->
</style>
<script language="JavaScript"
type="text/javascript">
<!--
// Aktuelle Position
var x = -200;
function werbungZeigen()
{
x += 5;
document.getElementById ("werbung").style.
left = x + "px";
if (x >= 100)
setTimeout ("werbungSchliessen ();",
5000);
else
setTimeout ("werbungZeigen ();", 50);
}
function werbungSchliessen()
{
document.getElementById ("werbung")
.style.visibility = "hidden";
}
setTimeout ("werbungZeigen();", 3000);
//-->
</script>
</head>
<body>
<div id="werbung"><img src="werbung.gif"
width="198" height="198"></div>
... beliebiger Inhalt ...
</body>
</html>
Eine überzeugendere Anwendung als dieses Beispiel, das Anwender verärgern könnte, finden Sie im letzten Unterabschnitt dieses Kapitels, in dem browserübergreifende Lösungen präsentiert werden. Dokumentinhalte verändern und austauschenDie Struktur des DOM-Baums, den ein HTML-Dokument bildet, kann beliebig manipuliert werden, um Inhalte vollständig gegen andere auszutauschen. Zu diesem Zweck sind Knoten-Objekte mit einer Reihe von Methoden ausgestattet, die entsprechende Manipulationen ermöglichen. Tabelle 19.3 zeigt hierzu eine Übersicht.
Das Beispiel in Listing 19.11 tauscht den Inhalt eines vollständigen Absatzes aus, der aus mehreren Text- und Elementknoten besteht. Listing 19.12 Austauschen von DOM-Knoten <html>
<head>
<title>Eine Geschichte in zwei Teilen</title>
<script language="JavaScript"
type="text/javascript">
<!--
function weiter()
{
var k1 = document.createTextNode
("Hier folgt der zweite Teil des ");
var k2 = document.createElement ("b");
var k2a = document.createTextNode
("kurzen");
k2.appendChild (k2a);
var k3 = document.createTextNode
(" Textes.");
document.getElementById ("story")
.replaceChild (k1, document.
getElementById ("story").firstChild);
document.getElementById ("story")
.appendChild (k2);
document.getElementById ("story")
.appendChild (k3);
}
//-->
</script>
</head>
<body>
<div id="story"><p>Dies ist ein <i>kurzer</i>
Text. Er besteht aus zwei Teilen. Den zweiten Teil
können Sie durch Klick auf den Link
"Weiter" lesen.</p></div>
<p><a href="javascript:weiter();">Weiter</a></p>
</body>
</html>
Da von Anfang an bekannt ist, dass der komplette Inhalt des <div>-Elements mit der ID story ausgetauscht werden soll, wurde dieser insgesamt zwischen die Tags <p> und </p> gepackt. Eine mögliche Alternative bestünde darin, sämtliche Kindknoten von story mit Hilfe einer Schleife zu entfernen:
In der vorliegenden Lösung werden zunächst die Knoten für den Ersatztext von Grund auf neu erzeugt: die beiden Textknoten k1 und k3 sowie der dazwischen liegende Elementknoten k2 vom Typ "b" (das HTML-Tag <b>) und sein Text. Anschließend wird der bisher einzige Kindknoten von story, das <p>-Element, mittels replaceChild() durch k1 ersetzt; die beiden folgenden Knoten k2 und k3 werden durch appendChild() angefügt. Praktisch gesehen wird in diesem Beispiel der Text »Dies ist ein kurzer Text. Er besteht aus zwei Teilen.« gegen den neuen Inhalt »Hier folgt der zweite Teil des kurzen Textes.« ausgetauscht. 19.7.2 Das klassische Internet-Explorer-Modell
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
In Listing 19.12 sehen Sie zunächst den vollständigen Code.
Listing 19.13 Eine browserunabhängige DHTML-Analoguhr
<html>
<head>
<title>DHTML-Analoguhr</title>
<script language="JavaScript" type="text/javascript">
<!--
// DHTML-Version ermitteln
var dom = document.getElementById ? true : false;
var ie = document.all ? true : false;
var n4 = document.layers ? true : false;
// Globale Variablen
var std_radius = 80;
var min_radius = 100;
var sek_radius = 90;
var x = 110;
var y = 110;
function zeit ()
{
var jetzt = new Date();
var std = jetzt.getHours();
var min = jetzt.getMinutes();
var sek = jetzt.getSeconds();
if (std > 11)
std -= 12; // 12-Stunden-Anzeige!
// Winkel ermitteln
var std_winkel = std * 30 - 90 + min * 0.1 - 90;
var min_winkel = min * 6 - 90 + sek * 0.1 - 90;
var sek_winkel = sek * 6 - 90;
// Zeigerpositionen berechnen
var std_y = Math.round (y + std_radius *
Math.sin (std_winkel * Math.PI / 180)) - 10;
var std_x = Math.round (x + std_radius *
Math.cos (std_winkel * Math.PI / 180)) - 10;
var min_y = Math.round (y + min_radius *
Math.sin (min_winkel * Math.PI / 180)) - 8;
var min_x = Math.round (x + min_radius *
Math.cos (min_winkel * Math.PI / 180)) - 8;
var sek_y = Math.round (y + sek_radius *
Math.sin (sek_winkel * Math.PI / 180)) - 5;
var sek_x = Math.round (x + sek_radius *
Math.cos (sek_winkel * Math.PI / 180)) - 5;
// Zeiger setzen
if (dom) {
document.getElementById ("std").style.top
= std_y + "px";
document.getElementById ("std").style.left
= std_x + "px";
document.getElementById ("min").style.top
= min_y + "px";
document.getElementById ("min").style.left
= min_x + "px";
document.getElementById ("sek").style.top
= sek_y + "px";
document.getElementById ("sek").style.left
= sek_x + "px";
} else if (ie) {
document.all.std.style.top = std_y + "px";
document.all.std.style.left = std_x + "px";
document.all.min.style.top = min_y + "px";
document.all.min.style.left = min_x + "px";
document.all.sek.style.top = sek_y + "px";
document.all.sek.style.left = sek_x + "px";
} else if (n4) {
document.layers.std.top = std_y;
document.layers.std.left = std_x;
document.layers.min.top = min_y;
document.layers.min.left = min_x;
document.layers.sek.top = sek_y;
document.layers.sek.left = sek_x;
}
setTimeout ("zeit();", 1000);
}
//-->
</script> </head>
<body onload="zeit();">
<div id="zifferblatt" style="position: absolute; top: 0px; left: 0px">
<img src="zifferblatt.gif" width="220" height="220" /></div>
<div id="std" style="position: absolute; top: 90px; left: 10px">
<img src="std_zeiger.gif" width="20" height="20" /></div>
<div id="min" style="position: absolute; top: 92px; left: 20px">
<img src="min_zeiger.gif" width="15" height="15" /></div>
<div id="sek" style="position: absolute; top: 95px; left: 30px">
<img src="sek_zeiger.gif" width="10" height="10" /></div>
</body>
</html>
DHTML-Browserweiche
Zunächst fällt auf, dass hier eine völlig andere Art der Browserweiche zum Einsatz kommt als die weiter oben besprochenen: Den Variablen dom, ie und n4 werden versuchsweise die DHTML-Objekte von DOM, dem klassischen Internet Explorer-Modell beziehungsweise dem alten Netscape-Modell als Werte zugewiesen. Das Ergebnis dieser Wertzuweisung ist jeweils eine Objektreferenz, wenn die Zugriffsart funktioniert, oder null, wenn sie fehlschlägt. Auf diese Weise können die DHTML-Modelle weiter unten einfach über Formulierungen wie if (dom) oder if (ie) abgefragt werden.
Die herkömmliche Browserweiche hat für DHTML-Zwecke einen großen Nachteil: Da auch neuere Internet Explorer-Versionen als Hauptversionsnummer 4.0 melden, würden alle Varianten dieses Browsers eben als Internet Explorer 4.0 behandelt. Neuere Versionen könnten dann nicht von den DOM-Vorteilen profitieren.
Berechnung
der Zeigerpositionen
Das Interessanteste an dem vorliegenden Skript ist wahrscheinlich das mathematische Verfahren, nach dem die Positionen der Zeiger auf dem Zifferblatt berechnet werden.
Der erste Schritt besteht darin, aus der jeweiligen Stunden-, Minuten- oder Sekundenangabe den korrekten Winkel zu berechnen. Dazu werden einfach die 12 möglichen Stunden- beziehungsweise 60 möglichen Minuten- und Sekundenangaben durch Multiplikation auf 360° verteilt: Zum Beispiel können Sie aus Gründen der Klarheit statt der bereits vereinfachten Angabe sek * 6 auch sek / 60 * 360 schreiben.
Für den Stundenzeiger wird noch der anteilige Minutenwert und für den Minutenzeiger der entsprechende Sekundenwert hinzuaddiert, damit diese beiden Zeiger kontinuierlich mitlaufen. Zu guter Letzt müssen noch 90° abgezogen werden, da der Startpunkt 12 Uhr nicht links liegt, sondern oben.
Im zweiten Schritt muss nun der Winkel in x- und y-Werte auf einem Kreis mit einem bestimmten Radius umgerechnet werden. Wenn die Sinus-Werte der Winkel als x–Koordinaten und die Cosinus-Werte als y-Koordinaten betrachtet werden, lassen sich daraus die korrekten auf 1 bezogenen Grundwerte ermittelt, die nur noch mit dem Radius multipliziert und zum jeweiligen Achsenwert des Mittelpunkts addiert werden müssen. Dies ergibt etwa für den Stundenzeiger (Radius 80 Pixel) die Werte sin(x) * 80 + 110 und cos(y) * 80+110.
Das einzige kleine Problem besteht darin, dass die trigonometrischen Funktionen in JavaScript das Bogenmaß verwenden; für die Umrechnung aus dem Winkelmaß gilt 360° = 2
.
Als Letztes wird noch der Radius des jeweiligen Zeigerbildes abgezogen, um die Zeiger wirklich korrekt zu positionieren.
Nach abgeschlossener Berechnung können die drei Zeiger-Layers auf die berechneten x- und y-Werte gesetzt werden. Zu diesem Zweck wird abgefragt, welches zu Beginn der Funktion ermittelte Objektmodell unterstützt wird, damit jeder Browser mit der für ihn passenden Syntax angesprochen wird.
Als Beispiel für den Austausch von Textinhalten wird im folgenden Listing im Layer dauer angezeigt, wie lange der Besucher bereits die Seite betrachtet.
Den Code sehen Sie in Listing 19.13.
Listing 19.14 Browserübergreifender Austausch von Layer-Texten
<html>
<head>
<title>Ihre Verweildauer</title>
<script language="JavaScript" type="text/javascript">
<!--
// DHTML-Version ermitteln
var dom = document.getElementById ? true : false;
var ie = document.all ? true : false;
var n4 = document.layers ? true : false;
// Bisherige Verweildauer
var zeit = 0;
function zeigeDauer()
{
var infostr = "Sie sind bereits " + zeit
+ " Sekunden hier.";
if (dom)
document.getElementById ("dauer").
firstChild.nodeValue = infostr;
else if (ie)
document.all.dauer.innerHTML = infostr;
else if (n4) {
with (document.layers.dauer.document) {
open();
write (infostr);
close();
}
}
zeit++;
setTimeout ("zeigeDauer();", 1000);
}
//-->
</script> </head>
<body onload="zeigeDauer();">
<div id="dauer" style="position: absolute; top: 10px; left:
10px">So lange sind Sie schon hier!</div>
</body>
</html>
Als Erstes wird wieder ermittelt, welche DHTML-Version unterstützt wird. Anschließend wird der anzuzeigende String gebastelt, der dann je nach Browser auf die passende Art und Weise dargestellt wird.
Beachten Sie bitte, dass Sie in einen solchen Ausgabestring kein HTML hineinschreiben dürfen, wenn das Skript auch in DOM-Browsern funktionieren soll: Während die traditionelle Netscape-Methode sowie die alte Internet Explorer-Eigenschaft innerHTML damit kein Problem haben, stellen HTML-Tags unter DOM separate Knoten dar, die nicht einfach als String in die nodeValue eines Textknotens eingetragen werden dürfen.
| << zurück |
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
Copyright © Galileo Press GmbH 2004
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.