(
KOMPENDIUM
) JavaScript
Das Kompendium Die Reihe für umfassendes Computerwissen Seit mehr als 20 Jahren begleiten die KOMPENDIEN aus dem Markt+Technik Verlag die Entwicklung des PCs. Mit ihren bis heute über 500 erschienenen Titeln deckt die Reihe jeden Aspekt der täglichen Arbeit am Computer ab. Die Kompetenz der Autoren sowie die Praxisnähe und die Qualität der Fachinformationen machen die Reihe zu einem verlässlichen Partner für alle, ob Einsteiger, Fortgeschrittene oder erfahrene Anwender. Das KOMPENDIUM ist praktisches Nachschlagewerk, Lehr- und Handbuch zugleich. Auf bis zu 1.000 Seiten wird jedes Thema erschöpfend behandelt. Ein detailliertes Inhaltsverzeichnis und ein umfangreicher Index erschließen das Material. Durch den gezielten Zugriff auf die gesuchte Information hilft das KOMPENDIUM auch in scheinbar aussichtslosen Fällen unkompliziert und schnell weiter. Praxisnahe Beispiele und eine klare Sprache sorgen dafür, dass bei allem technischen Anspruch und aller Präzision die Verständlichkeit nicht auf der Strecke bleibt. Mehr als 5 Millionen Leser profitierten bisher von der Kompetenz der KOMPENDIEN.
Unser Online-Tipp für noch mehr Wissen ...
... aktuelles Fachwissen rund um die Uhr — zum Probelesen, Downloaden oder auch auf Papier.
www.InformIT.de
JavaScript Interaktives und dynamisches Webpublishing TOBIAS HAUSER
(
KOMPENDIUM Einführung I Arbeitsbuch I Nachschlagewerk
)
eBook Die nicht autorisierte Weitergabe dieses eBooks an Dritte ist eine Verletzung des Urheberrechts!
Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar. Die Informationen in diesem Buch werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt.
10 9 8 7 6 5 4 3 2 1 05 04 03
ISBN 3-8272-6465-0 © 2003 by Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Coverkonzept: independent Medien-Design, Widenmayerstraße 16, 80538 München Coverlayout: Grafikdesign Heinz H. Rauner, Gmund Titelfoto: IFA-Bilderteam Lektorat: Jürgen Bergmoser,
[email protected] Korrektorat: Metke&Hardt, Köln,
[email protected] Herstellung: Elisabeth Egger,
[email protected] Satz: reemers publishing services gmbh, Krefeld (www.reemers.de) Druck und Verarbeitung: Kösel, Kempten (www.KoeselBuch.de) Printed in Germany
Im Überblick
Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
Teil 1
JavaScript
...................................................
29
Kapitel 1
Wissenswertes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
Kapitel 2
JavaScript in HTML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
Kapitel 3
Syntax und Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
Kapitel 4
Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
Kapitel 5
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
131
Kapitel 6
Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
159
Kapitel 7
Arrays und Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
207
Kapitel 8
OOP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
253
Kapitel 9
Debugging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
283
Kapitel 10
Document Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
305
Kapitel 11
Ereignisse und Event-Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
339
Teil 2
Webanwendungen
...........................................
359
Kapitel 12
Browserunterscheidung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
361
Kapitel 13
Bilder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
395
Kapitel 14
Navigationshilfen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
431
Kapitel 15
Fenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
459
Kapitel 16
Formulare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
491
Kapitel 17
Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
537
KOMPENDIUM
JavaScript
5
Im Überblick Kapitel 18
Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
553
Kapitel 19
CSS und JavaScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
581
Kapitel 20
DHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
601
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . . . .
647
Teil 3
Über den Tellerrand …
......................................
673
Kapitel 22
JavaScript und Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
675
Kapitel 23
Kommunikation mit der Außenwelt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
691
Kapitel 24
JScript .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
713
Anhänge
.....................................................
727
Anhang A
Browser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
729
Anhang B
Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
739
Anhang C
JavaScript 2.0 und die Zukunft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
741
Anhang D
Quellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
743
Anhang E
CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
745
Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
747
6
KOMPENDIUM
JavaScript
Inhaltsverzeichnis
Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
Wer sollte dieses Buch noch lesen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
Inhalt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
Browser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
Hilfe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
Team . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
Schreiben Sie uns! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
Teil 1
JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
Kapitel 1
Wissenswertes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
1.1
Historie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
Browserkrieg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
Heute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
1.2
ECMAScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
1.3
Weitere Einsatzgebiete. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
1.4
JavaScript und Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
Kapitel 2
JavaScript in HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
2.1
Einbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
Alte Browser und deaktiviertes JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
Position des Skript-Bereichs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
Externes JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
MIME-Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
45
KOMPENDIUM
JavaScript
7
Inhaltsverzeichnis 2.2
JavaScript in Links. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
2.3
JavaScript bei Ereignissen (Event-Handler) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
2.4
Versionsunterscheidung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
JavaScript-Versionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
Browserunterscheidung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
Besonderheiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
<script for>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
<script defer> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
Kapitel 3
Syntax und Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
3.1
Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
Gleitkommazahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
61
Boolean. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
Spezielle Werte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
Variablen deklarieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
67
Werte zuweisen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
Werte ändern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
Strichpunkt (;) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
Mehrere Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
Bezeichner und Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
Groß- und Kleinschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
Variablennamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
Reservierte Schlüsselwörter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
Formatierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
Zeichensatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
Typkonvertierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
77
Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
77
2.5
3.2
3.3
8
KOMPENDIUM
JavaScript
Inhaltsverzeichnis Hilfsmittel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78
Kommentare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78
Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
Kapitel 4
Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
4.1
Operatoren. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
Arithmetische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
String-Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
Vergleichsoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
Logische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
Bitweise Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
96
3.4
Operator-Präferenz. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 4.2
Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
103
if-Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 switch case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 4.3
Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
115
for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 do while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Kapitel 5
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
131
5.1
Eigene Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
131
Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Rückgabewert (return) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Funktionen abbrechen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Funktionsaufrufe verschachteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Funktionen verschachteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Lokale und globale Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Rekursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 this. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 5.2
Funktionen als Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
144
5.3
Globale Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
145
Zahlentests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
KOMPENDIUM
JavaScript
9
Inhaltsverzeichnis Datentypen ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 eval(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 URLs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Debugging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Kapitel 6
Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
159
6.1
Was sind Objekte? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
160
Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Polymorphismus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 6.2
Objekte von JavaScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
165
Math. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 Boolean. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Number. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Browser-spezifische Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 Kapitel 7
Arrays und Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
207
7.1
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
207
Alternativen und Kurzformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Elemente ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Die Länge eines Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 for-in- und andere Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Array-Elemente löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Assoziative Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 Methoden für Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Alternative Datenspeicherung mit eval(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 7.2
String. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
236
String-Länge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Formatieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Groß- und Kleinbuchstaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Methoden zum Arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
10
KOMPENDIUM
JavaScript
Inhaltsverzeichnis Suchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 toString() und valueOf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Kapitel 8
OOP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
253
8.1
Eigene Objekte. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
253
Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 Sinn und Unsinn von eigenen Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 8.2
for-in für Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
260
8.3
with . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
261
8.4
prototype-Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
262
8.5
Das Objekt Object und die Vererbungskette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
265
Objekte mit Object definieren. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Eigenschaften und Methoden von Object. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 8.6
Vorhandene Objekte erweitern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
271
Math erweitern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 8.7
Funktionen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
275
Funktionen als Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 Eigenschaften von Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Methoden von Function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Objekte an Funktionen übergeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Kapitel 9
Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
283
9.1
Debugging mit Browsern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
283
Internet Explorer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 Netscape Navigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 Mozilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 Opera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 9.2
Editoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
291
9.3
Fehler und Lösungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
292
Endlosschleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
KOMPENDIUM
JavaScript
11
Inhaltsverzeichnis 9.4
JavaScript Fehler-Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
294
Fehler abfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 Fehlerereignis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 Wann ist Fehler-Handling sinnvoll? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 Kapitel 10
Document Object Model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
305
10.1
W3C-DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
308
Knoten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Zugriff. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 Eigenschaften und Methoden des W3C-DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 W3C-DOM und DHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 10.2
DOM in verschiedenen Browsern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
328
DOM Level 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 DOM Level 0 mit Bild-Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Netscape 4.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Internet Explorer 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 Internet Explorer 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 W3C-DOM Level 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 W3C-DOM Level 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 10.3
Browserobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
332
window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 navigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 history. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 Kapitel 11
Ereignisse und Event-Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
339
11.1
Ereignis-Modelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
340
Netscape Navigator-Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 Internet Explorer-Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 W3C-Ereignis-Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
12
KOMPENDIUM
JavaScript
Inhaltsverzeichnis 11.2
Ereignisse anwenden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
351
Die Standardmethoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 Browserübergreifend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Besonderheiten des Internet Explorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 11.3
Ereignisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
354
11.4
Tastatur-Ereignisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
357
Teil 2
Webanwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
359
Kapitel 12
Browserunterscheidung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
361
12.1
language-Attribut. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
362
12.2
Deaktiviertes JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
363
12.3
navigator-Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
364
Welcher Browser? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Browser Sniffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 Sprache feststellen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384 12.4
Browserobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
385
DHTML und Browserunterscheidung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 12.5
Serverseitige Browserunterscheidung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
390
Kapitel 13
Bilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
395
13.1
Rollover . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
395
Rollover-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 Automatisiert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Ältere Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 Zufall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 Tipps und Tricks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 13.2
Vorladen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
402
Mehrere Bilder vorladen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 Alles geladen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 Fehler beim Laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
KOMPENDIUM
JavaScript
13
Inhaltsverzeichnis 13.3
Bilder als Formularelemente. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
406
13.4
Animation?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
410
Dateiformate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 Bildertausch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411 Größenänderung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Tipps und Tricks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 13.5
Formatierung und Verschönerung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
424
Alternativ-Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426 13.6
Imagemaps und JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
427
Kapitel 14
Navigationshilfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
431
14.1
history-Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
431
Netscape Navigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433 14.2
Weiterleitung und das location-Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
434
Zeitversetzt umleiten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Anker usw. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 Neu laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 14.3
Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
438
Linkziel ändern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438 Anker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440 14.4
Statusleiste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
442
Automatisieren. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443 Laufschrift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 Tipps & Tricks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 14.5
Laufschrift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
453
Laufschrift schützen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455 14.6
14
Drucken mit JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
KOMPENDIUM
456
JavaScript
Inhaltsverzeichnis Kapitel 15
Fenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
459
15.1
Dialogfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
459
Warnmeldung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459 Bestätigung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461 Eingabefenster. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462 Dialogfelder im Internet Explorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 15.2
Popups und andere neue Fenster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
467
Einstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469 Fokus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475 Popup unterdrücken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 In Popups schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 Fenster schließen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 opener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 15.3
Scrollen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
484
Scrollen verhindern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486 15.4
Fenster bewegen und skalieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
487
Kapitel 16
Formulare. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
491
16.1
Zugriff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
491
Zugriff mit name-Attribut. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492 Zugriff mit forms-Kollektion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 16.2
Formularelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
494
Textfeld. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 Mehrzeilige Textfelder. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 Checkbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 Radiobutton. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 Auswahlliste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505 Datei-Upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 Schaltflächen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 fieldset, legend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
KOMPENDIUM
JavaScript
15
Inhaltsverzeichnis 16.3
Formular versenden … . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
532
… an serverseitiges Skript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533 … per E-Mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533 … per Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535 Kapitel 17
Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
537
17.1
Geschichte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
538
Beschränkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 Cookies im Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540 17.2
Mit Cookies arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
542
Setzen und auslesen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542 Ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 Löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 Mehrere Informationen in einem Cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550 17.3
Cookietest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
550
17.4
Serverseitige Datenhaltung im Vergleich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
551
Kapitel 18
Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
553
18.1
Struktur und Zugriff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
554
Ereignisse und Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557 Frames formatieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558 Verschachtelte Framesets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564 18.2
Häufige Anwendungen und Tricks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
568
Frames und Links. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568 Unsichtbare Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570 Frames füllen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571 History und Frames. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572 18.3
Frames erzwingen und vermeiden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
573
18.4
iFrames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
573
JavaScript-Zugriff. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 iFrame-Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 iFrames verwenden?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578 16
KOMPENDIUM
JavaScript
Inhaltsverzeichnis Kapitel 19
CSS und JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
581
19.1
CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
582
Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583 Einheiten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583 Farben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583 19.2
Zugriff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
584
Das style-Objekt und seine Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 Netscape Navigator 4.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587 19.3
Klassen und Stylesheets wechseln. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
588
Klassen wechseln. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588 Stylesheets wechseln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 19.4
styleSheets-Kollektion und Regeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
593
Regeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593 Weitere Eigenschaften und Methoden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595 19.5
Stylesheets in der Praxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
598
Kapitel 20
DHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
601
20.1
Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
602
Netscape 4.x und Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 Internet Explorer 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 Internet Explorer 4 und höher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 Neuere DHTML-Ansätze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 Kleine Fallen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614 20.2
Maus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
614
Mauszeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614 Auf den Spuren der Maus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616 Drag&Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 620 Mehr Drag&Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 20.3
Navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
628
Sichtbare und unsichtbare Elemente. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628 zIndex. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632 Elemente permanent sichtbar machen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
KOMPENDIUM
JavaScript
17
Inhaltsverzeichnis 20.4
Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
638
Vorbereitungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639 Dynamische Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640 Funktionsaufruf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 Komplett . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642 Erweiterungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . .
647
21.1
Vollständigkeitsüberprüfung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
647
Formularelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648 Automatisieren. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651 Nachfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654 Ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656 Überprüfung bei der Eingabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656 Auf dem Server? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658 21.2
Formulardaten übernehmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
659
21.3
Reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
662
Mit regulären Ausdrücken arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 664 Anwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667 21.4
Usability. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
670
Teil 3
Über den Tellerrand … . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
673
Kapitel 22
JavaScript und Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
675
22.1
Diskussionen und potenzielle Sicherheitslecks. . . . . . . . . . . . . . . . . . . . . . . . . . . .
675
Lecks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676 22.2
Zertifikate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
676
Grundprinzip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677 Internet Explorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679 Netscape Navigator und Mozilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 680 Andere Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 684 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 684
18
KOMPENDIUM
JavaScript
Inhaltsverzeichnis 22.3
Skripten absichern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
684
Rechte Maustaste unterbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685 Code in Frames auslagern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686 Externe Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687 Quellcode schwer lesbar machen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 688 Quellcode verschlüsseln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 689 Sichern oder nicht? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690 22.4
Passwortschutz mit JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
690
Kapitel 23
Kommunikation mit der Außenwelt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
691
23.1
Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
691
Liveconnect. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 692 Zugriff auf Java-Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693 Java zu JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696 23.2
Sound und Multimedia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
698
In die Website einbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699 Plugin-Erkennung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 700 Steuerungsmöglichkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703 Apple QuickTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704 RealPlayer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706 23.3
Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
706
JavaScript zu Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707 Flash zu JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709 Kommunikationssorgen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 Kapitel 24
JScript .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
713
24.1
.NET-Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
713
Von ASP zu ASP.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714 Welche Betriebssysteme und Webserver? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715 ASP.NET-Seiten anlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716 Editoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717 JScript .NET im Vergleich mit VB.NET und C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717
KOMPENDIUM
JavaScript
19
Inhaltsverzeichnis 24.2
Web Forms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
718
HTML Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719 Web Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720 Validation Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 723 24.3
Sessionmanagement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
724
24.4
Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
726
Anhänge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
727
Anhang A
Browser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
729
A.1
Internet Explorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
729
Geschichte: Der Browserkrieg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 730 A.2
Netscape Navigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
731
A.3
Mozilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
733
Gecko und Konsorten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733 A.4
Opera. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
734
A.5
Konqueror . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
735
A.6
Safari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
736
A.7
HotJava . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
737
A.8
Browser ohne JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
738
Anhang B
Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
739
B.1
Editoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
739
B.2
JavaScript-Engines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
739
Anhang C
JavaScript 2.0 und die Zukunft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
741
C.1
JavaScript 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
741
Anhang D
Quellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
743
D.1
Skripten und Tutorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
743
D.2
Newsboards, Newsgroups und Maillisten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
744
20
KOMPENDIUM
JavaScript
Inhaltsverzeichnis Anhang E
CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
745
E.1
Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
745
E.2
Browser. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
745
E.3
Java SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
746
E.4
.NET. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
746
Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
747
KOMPENDIUM
JavaScript
21
Vorwort
Sie sollten dieses Buch lesen, wenn Sie eine solche Fehlermeldung öfter mal produzieren …
Wer sollte dieses Buch noch lesen? Für dieses Buch brauchen Sie von JavaScript noch nichts zu wissen. Sie lernen die Grundlagen, beginnend mit dem Einbau von Skripten in HTML. Der Einstieg erfolgt in aufeinander aufbauenden Schritten. Eine Vorraussetzung gibt es allerdings doch: Sie sollten HTML beherrschen oder sich zumindest parallel aneignen. Wenn Sie bereits fortgeschrittener JavaScript-Programmierer sind, wissen Sie, dass es im Internet Tausende von fertigen Skripten gibt. Das Problem ist nicht, fündig zu werden, sondern die Skripte zuerst qualitativ zu beurteilen, dann auf die eigenen Bedürfnisse anzupassen und abzuwandeln. Dazu ist Hintergrundwissen und Sachkenntnis erforderlich, die Sie sich mit Hilfe dieses Buches aneignen können. Zugegeben, dicke Bücher sind schwer zu tragen, aber wenn Sie sich dieses Buch ins Regal stellen, haben Sie auf jeden Fall auch noch lange nach dem Einstieg in JavaScript ein gutes Nachschlagewerk. Und der Weg vom Regal zum Schreibtisch ist ja normalerweise überschaubar .
KOMPENDIUM
JavaScript
23
Vorwort
Inhalt Das Buch ist in drei Teile unterteilt und besitzt einen Anhang. Ein Überblick zeigt Ihnen, was Sie erwartet: Teil 1 enthält die Grundlagen von JavaScript und behandelt alle nötigen Bausteine für fortgeschrittenes Programmieren. Die Kapitel von Teil 1 hängen inhaltlich zusammen und bauen aufeinander auf. Sollte der geneigte Leser allerdings einzelne Teile daraus später benötigen, findet er sich auch beim direkten Nachschlagen gut zurecht. Teil 2 zeigt häufige, wichtige und interessante Webanwendungen von Bildern über Formulare, Fenster, Cookies und DHTML. Alle relevanten Themen werden ausführlich und detailliert behandelt. Teil 3 auf den gelben Seiten wirft einen Blick über den Tellerrand, erklärt Sicherheitsaspekte und die Kommunikation von JavaScript mit Java, Multimedia-Plugins und Flash. Abgerundet wird der Teil durch einen Blick auf serverseitiges JavaScript mit JScript .NET. Im Anhang finden Sie Informationen über Browser und Tools, Sie werfen einen Blick in die Zukunft und erhalten nützliche Quellen. Den Abschluss bildet der Inhalt der Buch-CD-ROM, die nicht nur schmückendes Beiwerk, sondern praktische Hilfe für Sie sein soll.
Browser Eine der Kernfragen für JavaScript-Entwickler ist nach wie vor, welche Funktionen in welchen Browsern zur Verfügung stehen. Dieses Buch beschreitet hier einen neuen Weg: Sie finden am Ende keine dicke Referenz, sondern stattdessen bei allen wichtigen Elementen von JavaScript eine Tabelle über die Browserkompatibilität: Tabelle 0.1: alert()
NS4x
NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Darin sehen Sie auf einen Blick, für welchen Browser das jeweilige Sprachelement vorhanden ist. Gegenüber normalen Übersichten wurden zusätzlich zu den Standardbrowsern Netscape Navigator (NS, gefolgt von Versionsnummer) und Internet Explorer (IE, gefolgt von Versionsnummer) noch die »Exoten« Opera 7.x, Mozilla (M, Version 1.x) und Konqueror (K, Version 3.x) hinzugenommen. Ältere Versionen von Netscape Navigator und Internet Explorer haben in der Tabelle keinen Platz gefunden und augrund des nicht mehr vorhandenen Marktanteils auch nicht unbedingt verdient. Falls erforderlich, werden sie allerdings im Vortext zu den Tabellen erwähnt. 24
KOMPENDIUM
JavaScript
Service
Vorwort
Service Auf dem Weg zum JavaScript-Profi werden Sie beim Lesen einige Icons unterstützen: Dieses Symbol deutet an, dass Sie hier zusätzliche Informationen finden.
Einen Verweis auf eine andere Stelle, die für ein Thema ebenfalls von Interesse ist oder einen Themenbereich vertieft, finden Sie bei diesem Symbol. Achtung, hier versteckt sich eine Falle oder eine Information, die Ihre besondere Aufmerksamkeit erfordert. Egal ob schnellere Lösung oder zusätzliche Möglichkeiten: Informationen neben diesem Symbol geben nützliche Tipps. Dieses Icon deutet an, dass auf der Buch-CD-ROM eine passende Datei liegt. Meist sind dies Dateien, die vorhandene Listings abwandeln und weitere Alternativen aufzeigen oder die für Beispiele im Buch benötigt werden. Insgesamt finden Sie über 400 Listings auf der CD-ROM. Alle Beispiele in diesem Buch befinden sich auf der CD-ROM. Die Namen der Beispieldatei entnehmen Sie der Listingunterschrift. Im abgedruckten Code sind wichtige Stellen fett hervorgehoben, um Ihnen die Übersicht zu erleichtern.
Listing 0.1: Ein Beispiel (beispiel.html)
Neben allen Listings und zusätzlichen Beispieldateien finden Sie außerdem eine Menge nützlicher Software auf der CD. Eine Übersicht vermittelt Anhang E »CD-ROM«.
Hilfe Der Kerngedanke dieses Buches ist es, dem (angehenden) JavaScript-Entwickler das bestmögliche Hilfsmittel mitzugeben. Sollten Sie als JavaScriptEntwickler und Leser dieses Buches: etwas vermissen, einen Fehler finden, eine Anregung loswerden wollen oder einfach nur eine Meinung zum Buch haben, schreiben Sie mir eine E-Mail an
[email protected].
KOMPENDIUM
JavaScript
25
Vorwort Neuigkeiten und eine Errataliste zum Buch finden Sie auf der Website zum Buch http://www.hauser-wenz.de/go/javascript-kompendium. Leider kann ich nur Fragen beantworten, die sich direkt um den Inhalt dieses Buches drehen. Dafür versuche ich aber, die Antwortzeiten so kurz wie möglich zu halten.
Team Dass dieses Buch heute in Ihren Händen liegt, verdanken Sie als Leser und noch viel mehr ich als Autor vielen Menschen, die den Entstehungsprozess ganz oder teilweise begleitet haben: Meinem Lektor Jürgen Bergmoser für sein Engagement und den Glauben an das Projekt. Meiner Korrektorin Monika Hardt, die auch bei großer Zeitknappheit den Duden nicht aus den Augen verloren hat. Christian für seine Unterstützung und viele wertvolle Anregungen. Stefanie für aufopferungsvolle Kampfbereitschaft und Kuchen. Claudia und Rudi für ein wenig Entspannung in der heißen Phase. Marianne. Vielen Dank! Und zum Schluss noch ein Dank an Sie, lieber Leser! Denn für Sie ist dieses Buch geschrieben. Tobias Hauser Starnberg, Frühjahr 2003
26
KOMPENDIUM
JavaScript
Team
Vorwort
Schreiben Sie uns! Autor und Verlag sind immer bemüht Ihnen, unseren Kunden und Lesern die optimale Information zum Thema zu bieten. Scheuen Sie sich deshalb nicht, uns über Fehler und andere Ärgernisse zu informieren. Nur so können wir laufend an der Verbesserung unserer Bücher arbeiten. Aber auch Lob, Erfolgserlebnisse und Ihre Ergebnisse interessieren uns. Schreiben Sie uns unter
[email protected], Ihre Mails werden sofort an den Autor weitergeleitet! Ihr Markt+Technik-Buchlektorat Jürgen Bergmoser
[email protected] KOMPENDIUM
JavaScript
27
Teil 1 JavaScript
Kapitel 1:
Wissenswertes
31
Kapitel 2:
JavaScript in HTML
37
Kapitel 3:
Syntax und Variablen
57
Kapitel 4:
Programmieren
81
Kapitel 5:
Funktionen
131
Kapitel 6:
Objekte
159
Kapitel 7:
Arrays und Strings
207
Kapitel 8:
OOP
253
Kapitel 9:
Debugging
283
Kapitel 10: Document Object Model
305
Kapitel 11: Ereignisse und Event-Handler
339
1
Wissenswertes
Das World Wide Web wäre ohne JavaScript nicht denkbar. Wenn Sie einen Blick in den Quellcode irgendeiner größeren Website werfen, sehen Sie dort sicherlich einen <script>-Block mit JavaScript-Code. Dieser Code wird im Browser interpretiert (ausgeführt) und ist clientseitig, da das Ausführen des Codes auf dem Rechner des Nutzers (Client) geschieht.
Server Webserver
Response
Abbildung 1.1: Die (vereinfachte) Client-ServerArchitektur
Request
JavaScriptInterpreter
Client
Browser JavaScript ist im Web für die verschiedensten Aufgaben verantwortlich: für Rollover-Effekte, für das Ändern mehrerer Frames mit einem Link, für die Vollständigkeitsüberprüfung von Formularen, für Warenkörbe, Navigationselemente und Animationen. All diese Anwendungen erfüllen hauptsächlich einen Zweck: Webseiten zu verbessern, interaktiver zu gestalten und komfortabler zu machen. Zum Erfolg von JavaScript hat sicherlich auch beigetragen, dass es clientseitig nahezu konkurrenzlos ist. Im Internet Explorer können Sie zwar noch VBScript (Visual Basic Script) verwenden, allerdings bleibt es auf den Internet Explorer beschränkt und schließt damit viele Browser aus.
KOMPENDIUM
JavaScript
31
Kapitel 1
Wissenswertes
1.1
Historie
Vor dem Erfolg von JavaScript stand eine wechselhafte Geschichte: Der erste kommerzielle Webbrowser wurde im Jahr 1995 von der Firma Netscape1 entwickelt. Relativ bald darauf entstand die Idee für eine Skriptsprache. Sie sollte im Browser, aber auch in den Webserver-Produkten von Netscape eingesetzt werden und trug den Namen LiveScript. Der Leiter des damaligen Projektteams war Brendan Eich, der als Vater von JavaScript gilt. Zu diesem Zeitpunkt wurde Java, eine recht komplexe Programmiersprache von Sun, sehr erfolgreich. Netscape dachte sich, die neue Skriptsprache könnte von diesem Erfolg profitieren, schloss eine Vereinbarung mit Sun und benannte LiveScript in JavaScript um. Dieser Schritt war ein Fehler, der heute noch seine Schatten wirft. JavaScript wird in vielen Diskussionen, Beiträgen und Pamphleten mit Java gleichgesetzt, was in keinster Weise richtig ist. Die Syntax von JavaScript mag Ähnlichkeiten mit der von Java haben, da aber Java schon auf C und C++ basiert, kann man solche Ähnlichkeiten zwischen fast allen heute verwendeten Skript- und Programmiersprachen finden. Dankenswerterweise konnte sich JavaScript freischwimmen und hat seinen Erfolgsweg trotzdem eingeschlagen2. Microsoft merkte spätestens beim erfolgreichen Börsengang von Netscape, dass das Web und der Browser große Zukunftschancen haben und zog deswegen mit einem eigenen Browser, dem Internet Explorer, nach. Die ersten ernst zu nehmenden Versionen des Internet Explorer sind zwei Auslieferungen der Version 3. Sie besitzen einige JavaScript-Fähigkeiten beispielsweise für Bilder. Leider trug nun auch Microsoft zur Namenskonvention von JavaScript bei: Aus Lizenz-rechtlichen Gründen nannte Microsoft seine JavaScript-Version JScript, was heute für ebensoviel Verwirrung sorgt.
Browserkrieg In der vierten Version der Browser hat JavaScript (und JScript)3 einen deutlichen Sprung gemacht. Die Objekt-Modelle der Browser wurden erweitert 1
2
3
32
Gegründet als Mosaic Communications von Jim Clark, der bereits mit Silicon Graphics ein erfolgreiches Unternehmen aus der Taufe gehoben hatte, und Marc Andreessen, einem Studenten in Stanfort, der den ersten grafischen Webbrowser Mosaic entwickelt hat. Aus Mosaic entstand auch der erste Netscape Navigator. Java ist zur gleichen Zeit von den Clients mehr und mehr verschwunden. Java-Applets finden sich im Web immer weniger. Dafür feiert Java in verschiedenen Formen serverseitig neue Erfolge. JavaScript schließt im Folgenden und im ganzen Buch JScript mit ein. Ist speziell von der Microsoft-Implementierung die Rede, dann wird es JScript genannt.
KOMPENDIUM
JavaScript
Historie
Kapitel 1
(siehe Kapitel 10 »Document Object Model«) und eine Vielzahl an Funktionen kamen hinzu. Das Problem war damals jedoch, dass beide Browser in vielen Bereichen völlig unterschiedliche Wege gingen. Erste Standardisierungsbemühungen der ECMA für JavaScript und des W3C (World Wide Web Consortium) für das Objekt-Modell (DOM = Document Object Model) waren zwar schon auf dem Weg, aber in der Hitze des Browsergefechts ging einiges unter. Diese Zeiten waren hart für JavaScript-Programmierer. Browserunterschiede waren noch wichtiger als heute. Aktuell kann man wenigstens auf eine Unterstützung der dritten Generation, also Internet Explorer 3 und Netscape Navigator 3, verzichten. Ähnlich hart wurde es für Netscape: Microsoft zog mit fairen und weniger fairen Mitteln am Wettbewerber vorbei und Netscape ging schließlich in AOL Time Warner auf.
Heute Der Browsermarkt im Jahr 2003 wird – vor allem unter Windows – deutlich von Microsofts Internet Explorer beherrscht. Die Marktanteils-Statistiken schwanken um die 90%, je nachdem welche Websites ihre Ergebnisse beisteuern. Neben dem Hauptbrowser bilden sich allerdings viele Nebenschauplätze. Nachdem Netscape seinen Quellcode freigegeben hatte, entwickelte sich daraus die Gecko-Engine und schließlich die neuen Netscape-Versionen 6 und 7 sowie Mozilla. Opera, schon lange eine gute Alternative auf dem Browsermarkt, macht in Version 7 einen Schwenk hin zu offiziellen Standards. Besonders beachtlich schlägt sich der Konqueror, ein Webbrowser unter Linux, der in die Benutzeroberfläche KDE integriert ist. Seine Engine KHTML wurde von Apple dazu ausersehen, die Grundlage des neuen Safari für Mac OS X zu bilden. Ein guter JavaScript-Programmierer sollte die Entwicklung bei den Browsern sehr genau beobachten und auf möglichst vielen Browsern testen. Dieses Buch hilft Ihnen mit vielen Tabellen über die Browserkompatibilität, auch für die »Exoten« zu entwickeln. Im Anhang A »Browser« finden Sie die einzelnen Browser noch einmal detaillierter vorgestellt. Außer den Entwicklungen im Browserbereich gibt es in JavaScript natürlich noch weitere Strömungen: Die nächste JavaScript-Version wird wohl wesentlich stärker objektorientiert sein, zumindest wenn man den aktuellen, aber noch sehr vorläufigen Plänen glauben darf.4 Ein endgültiger Termin für neue Standards steht allerdings nicht fest. 4
Siehe hierzu Anhang C »JavaScript 2.0 und die Zukunft«
KOMPENDIUM
JavaScript
33
Kapitel 1
Wissenswertes Neben der zunehmenden Bedeutung der »exotischen« Browser und der Objektorientierung sind JavaScript-Programmierer einer weiteren Strömung ausgesetzt: dem Zeitgeist. Was ist gerade »in« im Web, welche Effekte gefallen, wie viel Usability muss sein (natürlich immer so viel wie möglich) und was verbessert den Komfort für den Nutzer? Dazu gibt es eigentlich nur zwei gute Ratschläge: Surfen Sie viel und denken Sie sich in Ihre Zielgruppe hinein.
1.2
ECMAScript
ECMAScript ist nicht gleich JavaScript. ECMAScript definiert einen großen Teil des Sprachkerns von JavaScript und damit auch von JScript. JavaScript erweitert diesen Sprachschatz allerdings um einige Funktionen und Möglichkeiten. Sie finden den ECMAScript-Standard unter http://www.ecma-international. org/publications/standards/ECMA-262.htm.
Leider kann die Skriptsprache selbst noch nicht mit der Webseite und den HTML-Inhalten darin kommunizieren. Dazu benötigt JavaScript das Object Model des Browsers. Die Standardisierung dieses Modells (DOM) obliegt dem W3C.5 Das Modell liefert die Browserobjekte, die den Zugriff auf die Elemente einer Webseite, wie beispielsweise Bilder, Links oder Formularelemente erlauben. Die folgende Tabelle gibt eine Übersicht über die Parallelen zwischen dem ECMAScript-Standard und den JavaScript- bzw. JScript-Versionen. Tabelle 1.1: JavaScript und ECMAScript
JavaScript-Version
JScript-Version
ECMAScript
1.0
1.0
1.1
1.1
1.2
3.0a
v1 (eingeschränkt)
1.3
5.0
v1
5.5 5.6
v3
1.4b 1.5
a. Den Zwischenschritt JScript 4.0 hat Microsoft ausgelassen. b. Nur in Netscape-Webservern, aber in keinem Browser implementiert.
5
34
Siehe Kapitel 10 »Document Object Model«
KOMPENDIUM
JavaScript
Weitere Einsatzgebiete
Kapitel 1
In Kapitel 2.4, Abschnitt »JavaScript-Versionen« finden Sie weitere Informationen zu den Browsern und den JavaScript-Versionen.
1.3
Weitere Einsatzgebiete
Das Haupteinsatzgebiet von JavaScript liegt eindeutig im Browser und damit in der clientseitigen Verwendung. Allerdings ist JavaScript oder der übergeordnete Standard ECMAScript entgegen der landläufigen Meinung auch in anderen Bereichen anzutreffen: Serverseitig in ASP (Active Server Pages), einer serverseitigen Technologie von Microsoft. ASP hinkt allerdings, was den Marktanteil betrifft, deutlich hinter dem Marktführer PHP her. Für den Entwickler bietet der Nachfolger ASP.NET mehr. Serverseitig in ASP.NET, dem Nachfolger von ASP. Hier heißt JavaScript JScript .NET. Eine Einführung in das .NET-Konzept und in JScript .NET finden Sie in Kapitel 24 »JScript .NET«. Die Diskussion, welche Aufgaben besser clientseitig und welche besser serverseitig erledigt werden, finden Sie in diesem Buch noch häufiger. Nicht behandelt wird die Frage, welche serverseitige Technologie die beste ist. Hier spielen viele Faktoren eine Rolle. Die Grabenkämpfe – gerade zwischen Microsoft und der Open-Source-Gemeinde rund um PHP – sind eine teilweise sehr emotionale Diskussion. Dieses Buch greift auf JScript .NET zurück, weil sich damit zwei Fliegen mit einer Klappe schlagen lassen: Eine (neue) serverseitige Technologie wird vorgestellt und sie lässt sich mit einer JavaScript-Variante programmieren. Als Skript-Sprache für neue Technologien wie beispielsweise SVG (Scalable Vector Graphics), einem Vektorgrafik-Standard des Internet-Standardisierungsgremiums W3C.6 Flash von Macromedia, der Quasi-Standard und Platzhirsch bei Vektorgrafiken und -animationen, verwendet eine Skriptsprache namens ActionScript. Sie ist – wie JavaScript – seit Flash 5 ein Abkömmling von ECMAScript. Wer das eine beherrscht, kann auch das andere lernen.
6
Siehe http://www.w3.org/Graphics/SVG
KOMPENDIUM
JavaScript
35
Kapitel 1
Wissenswertes
1.4
JavaScript und Sicherheit
Einige Dinge kann clientseitiges JavaScript nicht: beliebig Browserfenster schließen Netzwerk-Verbindungen herstellen oder verarbeiten Dateien öffnen und speichern Grafiken zeichnen.7 Der Grund für diese »Mängel« ist die Sicherheit. Niemand will einem Skript in einer fremden HTML-Seite das Recht geben, Dateien zu löschen. Diese strengen Sicherheitsregeln führen dazu, dass JavaScript verhältnismäßig wenig negative Schlagzeilen produziert. Die meisten Sicherheitslücken für den Internet Explorer wurden von ActiveX und damit VBScript gemeldet. Auch in Netscape gab es in den älteren Versionen 2 und 3 einige Probleme. Mehr über die Sicherheitsvorkehrungen von JavaScript erfahren Sie in Kapitel 22 »JavaScript und Sicherheit«.
7
36
Eine Ausnahme ist das dynamische Generieren von HTML-Elementen.
KOMPENDIUM
JavaScript
2
JavaScript in HTML
Clientseitiges JavaScript – das den größten Raum in diesem Buch einnimmt – erweitert HTML. Dementsprechend sind die JavaScript-Skripten auch Teil der HTML-Seite. Sie sind im normalen HTML-Code eingebunden und werden vom Server auf den Client übertragen und dort ausgeführt.
2.1
Einbau
Damit der Browser erkennt, dass es sich um JavaScript und nicht um HTML handelt, müssen die JavaScript-Bereiche innerhalb einer HTMLSeite hervorgehoben sein. So sieht ein normales HTML-Grundgerüst ohne JavaScript aus: HTML-Grundgerüst
Listing 2.1: Das HTML-Grundgerüst (grundgeruest.html)
In diesem Buch kommt recht viel HTML vor. Sie sollten also mit HTML in Grundzügen vertraut sein. Die Beispiele sind – soweit möglich und sinnvoll – XHTML-konform1: Alle Tags sind Kleinbuchstaben. Jedes Tag wird beendet, auch Tags ohne Ende-Tag:
statt:
1
zu finden unter: http://www.w3.org/TR/xhtml1/
KOMPENDIUM
JavaScript
37
Kapitel 2
JavaScript in HTML Attribute sind in Kleinbuchstaben geschrieben. Attribut-Werte stehen immer in Anführungszeichen. JavaScript-Skripten werden in HTML mit <script> und eingebunden. Zwischen diesen Tags steht der JavaScript-Code. Da die <script>-Tags auch von anderen Skriptsprachen verwendet werden, muss mit dem Attribut language die Sprache identifiziert werden. <script language="JavaScript">
Wenn Sie das language-Attribut weglassen, verwenden die aktuellen Browser dennoch JavaScript als Standard. Da dies allerdings nicht selbstverständlich ist, sollten Sie sich nicht darauf verlassen. Das <script>-Element findet seinen Platz im Kopf der HTML-Seite: Listing 2.2: Skript-Container im Kopf der HTMLSeite (script.html)
Der Skript-Container <script language="JavaScript"> document.write("Herzlich willkommen!");
Abbildung 2.1: Das Skript gibt einen Text aus.
Der Befehl document.write() gibt einen Text aus, der in Anführungszeichen innerhalb der runden Klammern steht. Eng verwandt ist document.writeln(), das eine einzelne Zeile ausgibt.
Alte Browser und deaktiviertes JavaScript Browser ohne JavaScript-Unterstützung sind ein ständig wiederkehrendes Problem für JavaScript-Programmierer. Prinzipiell lassen sich zwei Fälle unterscheiden:
38
KOMPENDIUM
JavaScript
Einbau
Kapitel 2
Browser, in denen JavaScript deaktiviert wurde. Sie ignorieren den Code in den <script>-Tags (siehe Abbildung 2.2). Die verschiedenen Browser und ihre Möglichkeiten, JavaScript zu deaktivieren, finden Sie im Anhang A »Browser«.
Abbildung 2.2: Mit deaktivierter JavaScript-Unterstützung zeigt ein JavaScript-fähiger Browser nichts an.
Alte Browser, die kein JavaScript unterstützen, kennen <script>-Tags nicht. Daher ignorieren sie die Tags und geben den Inhalt aus. Hier kann es also passieren, dass das ganze Skript in Klarsicht ausgegeben wird. Der erste Fall – deaktivierte JavaScript-Unterstützung – lässt sich nur dadurch umgehen, dass Ihre Website auch ohne JavaScript navigierbar ist. Im zweiten Fall müssen Sie auf jeden Fall verhindern, dass das Skript ausgegeben wird. Dazu gibt es einen Trick: Der ganze Skriptteil wird in HTMLKommentare Abbildung 3.7: Der Navigator 7 zeigt die korrekte Umrechnung an.
Abbildung 3.8: Der Internet Explorer 6 meldet einen Syntaxfehler, da er const nicht unterstützt.
80
KOMPENDIUM
JavaScript
4
Programmieren
Spricht ein Experte lapidar vom Programmieren, bleibt immer die Frage, worum es dabei eigentlich geht. Eine Webanwendung stellt andere Anforderungen, als eine Windows-Applikation oder ein VBA-Makro. Trotz der unterschiedlichsten Einsatzgebiete sind in vielen Programmiersprachen die Grundstrukturen gleich. In C++, Visual Basic, PHP und auch in JavaScript wird mit Variablen gearbeitet. Diese Variablen müssen mittels Operatoren miteinander verknüpft, Bedingungen müssen überprüft und Anweisungen ausgeführt werden.1 Sollten Sie bereits mit anderen Programmiersprachen vertraut sein, kommt Ihnen also vieles vertraut vor. Es ist ausreichend, wenn Sie einen Blick auf die Syntax werfen. Haben Sie dagegen noch keine Programmiererfahrung, lohnt sich eine ausführlichere Beschäftigung mit den Grundlagen in diesem Kapitel. Sie können später immer wieder darauf zurückgreifen.
4.1
Operatoren
Operatoren verbinden in Variablen gespeicherte Daten. Die verschiedenen mathematischen Rechenarten wie Addition, Subtraktion usw. haben jeweils eigene Operatoren. Für die Addition steht beispielsweise das Pluszeichen (+). Darüber hinaus gibt es noch weitere Operatoren, beispielsweise um zwei Werte miteinander zu vergleichen. Einen Operator haben Sie bereits kennen gelernt: den Zuweisungsoperator (das Ist-Gleich). Er weist einer Variablen einen Wert zu: var x = 5;
Arithmetische Operatoren Die arithmetischen Operatoren sind für die mathematischen Grundrechenarten, beispielsweise Addition und Multiplikation, zuständig. Die Syntax ist sehr einfach. Folgende Zeile addiert 5 und 3 und weist das Ergebnis 8 der Variable x zu. 1
Zugegeben, das ist nur ein kleiner Teil des Programmierens im weiteren Sinne. Für dieses Kapitel wird der Begriff sehr eng gefasst.
KOMPENDIUM
JavaScript
81
Kapitel 4
Programmieren var x = 5 + 3;
Der Operator ist in diesem Fall das Plus-Symbol für die Addition. Die zwei Werte 5 und 3 werden als Operanden2 bezeichnet. In den Beispielskripten dieses Buches sind Operanden und Operatoren jeweils durch ein Leerzeichen getrennt. JavaScript erfordert dies nicht, allerdings werden die Skripten dadurch übersichtlicher. Das folgende Beispiel ist ein komplett lauffähiges Skript. Es rechnet einen in der Variable dm gespeicherten Geldwert von DM in Euro um und gibt ihn aus. Dazu wird die Variable dm durch den Umrechnungskurs (Variable kurs) geteilt. Listing 4.1: Einfache Umrechnung von DM in Euro (euro.html)
Euro in DM <script language="JavaScript">
document.write(euro); //-->
Beachten Sie, dass der arithmetische Operator für die Division kein Doppelpunkt, sondern ein Schrägstrich (/) ist. Natürlich können auch mehrere arithmetische Operatoren hintereinander eingesetzt werden. Dabei gilt – wie in der »echten« Mathematik – die Regel »Punkt vor Strich«. Das heißt, Division und Multiplikation rangieren in der Präferenz vor Addition und Subtraktion. Ein einfaches Beispiel illustriert dies: Listing 4.2: Bei den arithmetischen Operatoren gilt Punkt vor Strich (punkt_vor_strich. html).
Punkt vor Strich <script language="JavaScript">
82
Frei übersetzt hieße das wohl: »diejenigen, mit denen der Operator arbeitet«.
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
var y = (100 + 200) / 2; document.write("y: " + y);
//-->
Das Beispiel besteht aus zwei Teilen: 1.
Im oberen Teil des Skripts wird die Variable x definiert. Sie erhält als Wert das Ergebnis einer Berechnung. Zuerst wird 200 durch 2 geteilt. Das Ergebnis (100) wird mit 100 addiert. Die Variable x erhält also den Wert 200, der anschließend ausgegeben wird.
2.
Der untere Teil des Skripts umgeht das Punkt-vor-Strich-Prinzip mit Klammern. Klammern sind im Prinzip auch Operatoren, die außerdem eine höhere Präferenz als arithmetische Operatoren besitzen. Im Beispiel rechnet der JavaScript-Interpreter zuerst 100 plus 200 und teilt das Ergebnis (300) anschließend durch 2. Ausgegeben wird dann 150 als Wert von y.
Bisher kamen in den Beispielen nur Addition und Division vor. In der folgenden Tabelle finden Sie alle arithmetischen Operatoren im Überblick. Operator
Beispiel
Beschreibung
+
x = 5 + 3; // Ergebnis: 8
Addition; addieren zweier Zahlen
-
x = 5 - 3; // Ergebnis: 2
Subtraktion; eine Zahl wird von der anderen subtrahiert.
-
x = 5; y = -x; //Ergebnis y: -5
Negation mit vorangestelltem Minus-Symbol. Vorzeichenwechsel
*
x = 5 * 3; // Ergebnis: 15
Multiplikation; zwei Zahlen werden miteinander multipliziert.
/
x = 5 / 3; // Ergebnis: 1.6666
Division; eine Zahl wird mit der zweiten Zahl dividiert.
%
x = 5 % 3; // Ergebnis: 2
Modulo Divisionsrest errechnen; im Beispiel: 3 passt in 5 einmal, als Rest bleibt 2.
Tabelle 4.1: Die arithmetischen Operatoren
Inkrement und Dekrement JavaScript hat einen eigenen Operator, das so genannte Inkrement, um einen Wert genau um 1 zu erhöhen. Er wird durch ein doppeltes Pluszeichen (++) symbolisiert und insbesondere bei Schleifen recht häufig zum Erhöhen des Zählers eingesetzt (siehe Kapitel 4.3 »Schleifen«).
KOMPENDIUM
JavaScript
83
Kapitel 4
Programmieren var x = 2; x++;
Diese zwei Zeilen definieren x zuerst mit dem Wert 2 und erhöhen x dann um 1 auf 3. Das Gegenstück zum Inkrement ist das Dekrement zum Verringern eines Wertes um 1. Die Funktionsweise ist analog: var x = 2; x--;
ergibt also den Wert 1 für x. Reihenfolge Bei Inkrement und Dekrement ist entscheidend, ob sie vor oder hinter der Variablen oder dem zu ändernden Wert stehen. ++x;
Stehen Sie wie in dieser Zeile vor der Variablen, wird zuerst der Variablenwert erhöht, bevor die Variable verwendet wird. var x = 5; var a = 3 + ++x;
Bei diesen Zeilen hat also a den Wert 9 ( 3 + 5 + 1). x hat nach den zwei Zeilen den Wert 6. Steht das Inkrement oder Dekrement hingegen hinter der Variablen, wird deren Wert erst um eins erhöht oder gesenkt, wenn die Variable verwendet wurde: var x = 5; var a = 3 + x++; a hat hier also den Wert 8, x wie im vorhergehenden Beispiel den Wert 6.
Kurzformen Inkrement und Dekrement sind zwar sehr praktisch, häufig soll der Wert einer Variablen allerdings nicht nur um 1 verändert werden. In der umständlicheren Variante sieht dies wie folgt aus: var x = 5; x = x - 3; //Ergebnis: 2
84
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Für die zweite Zeile gibt es allerdings auch eine elegantere Kurzform: x -= 3; //Ergebnis: 2
Was geschieht hier? Der Operator wird vor das Pluszeichen geschrieben. Das signalisiert dem Interpreter, dass er den Variablenwert verändern soll. Um welchen Wert er verändert werden soll, steht nach dem Ist-Gleich. Diese Kurzform gibt es für alle arithmetischen Operatoren (siehe Tabelle 4.2). Operator
Beispiel (var x = 5)
Längere Alternative
+=
x += 3; // Erg: 8
x = x + 3;
-=
x -= 3; // Erg: 2
x = x - 3;
*=
x *= 3; // Erg: 15
x = x * 3;
/=
x /= 3; // Erg: 1.6666
x = x / 3;
%=
x %= 3; // Erg: 2
x = x % 3;
Tabelle 4.2: Kurzformen für arithmetische Operatoren
String-Operator Natürlich lassen sich mit Zeichenketten keine Berechnungen anstellen. Dennoch gibt es einen Operator: das Plus-Symbol (+). Es verbindet mehrere Strings miteinander. Listing 4.2 macht davon bereits Gebrauch. Die Verknüpfung von Strings wird auch Konkatenation genannt. var titel = "Yesterday"; var text = "all my trouble ..."; document.write(titel + text);
Die oberen Zeilen fügen den Anfang des Beatles-Klassikers »Yesterday« aneinander und geben ihn aus. Allerdings gibt es dabei ein Problem. Da keine Leerzeichen als Zwischenräume vorgesehen sind, wird der Text direkt aneinander gehängt (siehe Abbildung 4.1). Dieses Problem ist in der Praxis ein sehr häufiger Flüchtigkeitsfehler. Im Prinzip ist es unerheblich, ob Sie das Leerzeichen in den ersten oder zweiten String einfügen. Im Allgemeinen wirkt es allerdings im ersten übersichtlicher.
KOMPENDIUM
JavaScript
85
Kapitel 4
Programmieren
Abbildung 4.1: Der Browser hängt den Text direkt aneinander.
Listing 4.3: Der String-Operator verknüpft zwei Zeichenketten (string_operator. html).
String-Operator <script language="JavaScript">
//--> Abbildung 4.2: Jetzt ist der Abstand korrekt.
Kurzform Für den String-Operator gibt es wie bei der normalen Addition die Kurzform +=. Das Beispiel sieht in der Kurzform mit nur noch einer Variablen wie folgt aus: var text = "Yesterday, "; text += "all my trouble…" document.write(text);
86
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Vergleichsoperatoren Vergleichen ist in der Programmierung gang und gäbe. Es werden keine »Äpfel mit Birnen«, sondern meistens Zahlen miteinander verglichen, um Bedingungen zu überprüfen. Bedingungen kommen insbesondere in Kontrollstrukturen und Schleifen zum Einsatz (siehe Kapitel 4.2 »Kontrollstrukturen« und Kapitel 4.3 »Schleifen«). Die Vergleichsoperatoren sind größtenteils ebenfalls bereits im Mathematikunterricht zum Einsatz gekommen. Folgende Zeile stellt beispielsweise fest, ob 4 größer als 3 ist. var v = (4 > 3);
Das Ergebnis eines Vergleichs ist immer ein Wahrheitswert (Boolean), also true (wahr) oder false (falsch). In unserem Beispiel lautet das Ergebnis natürlich … true. Sie können das feststellen, indem Sie die Variable einfach ausgeben (siehe Abbildung 4.3). Abbildung 4.3: Die Ausgabe von 4 > 3 (vergleich.html)
Eine vollständige Auflistung der Vergleichsoperatoren in JavaScript finden Sie in Tabelle 4.3. Operator
Beispiel
Beschreibung
==
var a = (4 == 3); //Erg: false
Gleichheit
!=
var a = (4 != 3); //Erg: true
Ungleichheit
=
var a = (4 >= 3); //Erg: true
Kleiner als oder gleich
KOMPENDIUM
JavaScript
Tabelle 4.3: Die Vergleichsoperatoren
87
Kapitel 4
Programmieren Sind zwei Zahlen gleich groß, ergibt ein Vergleich mit < oder > immer false. Soll bei Gleichheit true zurückgegeben werden, müssen Sie = verwenden. Beachten Sie außerdem, dass der Vergleich auch Nachkommastellen berücksichtigt. Der Gleichheitsoperator == wird in der Praxis häufig mit dem Zuweisungsoperator = vertauscht. Das Problem ist, dass JavaScript-Interpreter in diesem Fall manchmal keine Fehlermeldung liefern. Die Schwierigkeit liegt also darin, das Problem zu lokalisieren (zur Fehlerkorrektur siehe Kapitel 9 »Debugging«). Datentypen Ist einer der Operanden keine Zahl, sondern ein anderer Datentyp, führt der JavaScript-Interpreter eine automatische Typkonvertierung durch: Ist einer der Operanden ein String und der andere eine Zahl, wird der String in eine Zahl umgewandelt. Ist einer der Operanden ein Wahrheitswert, wird true in 1 und false in 0 umgewandelt. Ist einer der Operanden ein Objekt, testet der Interpreter, ob das Objekt die Methode toString() (zur Umwandlung in eine Zeichenkette) oder valueOf() (zur Umwandlung in eine Zahl) besitzt. Wenn dies der Fall ist, wird umgewandelt, ansonsten gibt der Browser eine Fehlermeldung aus. Genau gleich (===) und ungleich (!==) Seit JavaScript 1.3 gibt es die Operatoren genau gleich (===)3 und ungleich (!==). Sie überprüfen nicht nur, ob die Werte der zwei Operanden gleich bzw. ungleich sind, sondern auch, ob die Datentypen identisch sind. In den ECMAScript-Standard wurden die beiden Operatoren mit der Version 3 übernommen. Die Browserkompatibilität entnehmen Sie Tabelle 4.4. Ältere Browser unterstützen diese Operatoren nicht.
Tabelle 4.4: Genau gleich und genau ungleich
NS4.x NS6 === !==
3
88
()
NS7
IE4 IE5
IE5.5 IE6
O6
M1
K3
Der Operator genau gleich (===) wird auch Identitätsoperator genannt.
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Wenn Sie im Netscape Navigator 4.x als Sprachversion JavaScript 1.2 angeben (language="JavaScript1.2"), werden die Operatoren genau gleich und genau ungleich wie der normale Gleichheits- bzw. Ungleichheitsoperator behandelt. Das vermeiden Sie, indem Sie die bei der Sprachangabe die Versionsnummer weglassen. Ein einfaches Beispiel zeigt dies. Das folgende Skript vergleicht eine Zahl mit einer Zeichenkette: Bei der Verwendung des normalen Gleichheitsoperators == wird die Zeichenkette automatisch in eine Zahl konvertiert. Der Vergleich bei der Variablen x ergibt also true. var a = 4; var b = "4"; var x = (a == b);
Mit dem Operator genau gleich === wird zusätzlich zum Wert auch der Typ verglichen. Da es sich hier um einen String und eine Zahl handelt, ist das Ergebnis false. var y = (a === b);
Hier der vollständige Code: Vergleichsoperatoren <script language="JavaScript">
Wenn Sie das Skript testen, wird der richtige Wochentag angezeigt (siehe Abbildung 4.12). Abbildung 4.12: Der richtige Wochentag wird ausgegeben.
Wenn Sie break aus Versehen weglassen, werden alle Anweisungen ab dem zutreffenden Fall ausgeführt. In Abbildung 4.13 ist tag gleich 3, also »Donnerstag«. Da break fehlt, werden allerdings auch »Freitag« bis »Sonntag« ausgegeben. Abbildung 4.13: Ohne break werden alle Anweisungen ab der erfüllten Bedingung ausgeführt.
Typkonvertierung Im Gegensatz zum Einsatz von Vergleichsoperatoren wird in der switchcase-Anweisung keine automatische Typkonvertierung durchgeführt. Folgender Code ergibt also keine Ausgabe, da der Wert der Variablen ein String ist, der zugehörige Fall aber eine Zahl:
112
KOMPENDIUM
JavaScript
Kontrollstrukturen
Kapitel 4
var tag = "3"; switch (tag) { case 0: document.write("Montag"); break; case 1: document.write("Dienstag"); break; case 2: document.write("Mittwoch"); break; case 3:
document.write("Donnerstag"); break; case 4: document.write("Freitag"); break; case 5: document.write("Samstag"); break; case 6: document.write("Sonntag"); break; }
default Wenn wie bei der Verwendung eines falschen Datentyps aus dem vorigen Abschnitt keiner der Fälle eintrifft, ist es oft ärgerlich, dass der Nutzer keine Rückmeldung erhält. Um dieses Problem zu beheben, fügen Sie einfach am Ende eine default-Anweisung an. Sie tritt ein, wenn vorher keiner der Fälle denselben Wert wie der Ausdruck hat. Die Syntax der switch-Anweisung wird um die default-Anweisung erweitert und damit ein wenig länger: switch (Ausdruck) { case Wert1: Anweisung1; break; case Wert2: Anweisung2; break; . default: Anweisung; }
KOMPENDIUM
JavaScript
113
Kapitel 4
Programmieren Wird das Beispiel mit den Wochentagen um eine default-Anweisung erweitert, kann damit auch eine Falscheingabe, beispielsweise der Wert 7 für den Wochentag, abgefangen werden: var tag = 7; switch (tag) { case 0: document.write("Montag"); break; case 1: document.write("Dienstag"); break; case 2: document.write("Mittwoch"); break;
Listing 4.13: Der Einsatz von default
(switch_default. html nicht vollständig abgedruckt)
. . . default: document.write("Keiner der Fälle ist eingetreten");
} Abbildung 4.14: Keiner der sieben Wochentage konnte identifiziert werden.
switch und if im Vergleich Wenn nur mögliche Werte eines Ausdrucks nacheinander ausgewertet werden sollen, wird eine if-Anweisung unnötig kompliziert. Dies zeigt der direkte Vergleich zwischen switch und if: Listing 4.14: Das switchBeispiel, mit if-realisiert (if_switch.html).
if oder switch <script language="JavaScript">
114
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
} else if (tag == 2) { document.write("Mittwoch"); } else if (tag == 3) { document.write("Donnerstag"); } else if (tag == 4) { document.write("Freitag"); } else if (tag == 5) { document.write("Samstag"); } else if (tag == 6) { document.write("Sonntag"); } else { document.write("Kein gültiger Wochentag!"); }
//-->
Zwar ist die if-else if-Variante um einige Zeilen8 kürzer, dafür besteht sie aus einigen Zeichen weniger und fordert damit auch mehr fehlerträchtige Tipparbeit. Außerdem wirkt die switch-Variante optisch aufgeräumter. Schließlich muss jeder selbst abwägen, was ihm besser gefällt. Viele Programmierer greifen automatisch zu if-else if, da sie dieses Konstrukt besser kennen. Behalten Sie aber die Alternative switch im Hinterkopf, wenn es an neue Aufgaben geht.
4.3
Schleifen
Schleifen enthalten stetig sich wiederholende Anweisungen. Sie werden so lange ausgeführt, bis eine vorher festgelegte Bedingung nicht mehr erfüllt ist. Fehlt diese Bedingung oder ist sie immer erfüllt, läuft die Schleife ewig. Man spricht dann von einer Endlosschleife. Endlosschleifen gehören zu den Fehlern, die es unbedingt zu vermeiden gilt, denn häufig stürzt dem Nutzer sonst der Browser ab. Haben Sie beim Programmieren eine Endlosschleife erzeugt, klicken Sie im Browser auf das Stop-Symbol oder betätigen Sie (Esc), um den JavaScriptInterpreter anzuhalten. Manche Browser fragen im Falle einer Endlosschleife auch nach, ob sie das Skript abbrechen sollen (siehe Abbildung 4.15).
8
Um genau zu sein: sieben Zeilen. Natürlich könnten Sie weitere Zeilen einsparen, indem Sie else if-Anweisungen auf eine Zeile komprimieren. Ähnlich lassen sich auch switch-Fälle auf eine Zeile schreiben. Der Nachteil bei beiden Methoden ist, dass die Übersichtlichkeit sehr stark leidet.
KOMPENDIUM
JavaScript
115
Kapitel 4
Programmieren
Abbildung 4.15: Der Internet Explorer 6 erkundigt sich, ob das Skript weiter ausgeführt werden soll.
for Die for-Schleife ist die komfortabelste und daher auch meist verbreitete Schleifenart. Wie oft die Schleife durchlaufen wird, steuern drei Parameter: for (Initialisierung; Bedingung; Änderung) { Anweisungen; }
Die drei Parameter dienen alle zur Steuerung des Schleifenzählers: Bei der Initialisierung wird der Zählervariablen ein erster Wert vergeben. Diese Anweisung wird nur einmal, zu Beginn, ausgeführt. Der Variablenname für die Zählervariable ist natürlich beliebig wählbar. Als Standard eingebürgert hat sich allerdings i. Die Bedingung wird vor jedem Schleifendurchlauf überprüft. Ist sie erfüllt (true), werden die Anweisungen in der Schleife ausgeführt. Nach jedem Schleifendurchlauf wird in der Änderung die Zählervariable angepasst. Dies geschieht so lange, bis die Zählervariable die Bedingung nicht mehr erfüllt und die Schleife abgebrochen wird. Natürlich kann die Zählervariable auch in der Schleife geändert werden und in der Änderung folgen andere Anpassungen. Jeder der drei Schleifenparameter kann weggelassen werden, nicht aber die abtrennenden Strichpunkte. Fehlt die Bedingung, ist sie automatisch immer true. In diesem Fall wird aus der for-Schleife eine Endlosschleife, wenn sie nicht in den Anweisungen mit break abgebrochen wird. Ein einfaches Beispiel gibt die Quadrate der Zahlen von 1 bis 10 aus: Dazu wird der Zähler auf 1 initialisiert. for (var i=1;
116
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
Die Zählervariable muss nicht unbedingt erst in der for-Schleife deklariert werden. Meist wird allerdings diese Technik verwendet, da die Zählervariable nur in der Schleife eingesetzt wird. Hier ist allerdings Vorsicht geboten: selbst wenn die Zählervariable erst in der for-Schleife deklariert wird, steht sie auch nach der Schleife noch zur Verfügung. Sie ist also keine lokale Variable, wie es sie bei Funktionen gibt (siehe Kapitel 5 »Funktionen«). In der Bedingung überprüft die for-Schleife, ob der Zähler kleiner oder gleich 10 ist. for (var i=1; i
Listing 4.23: Ist while manchmal besser als for? (while_besser.html)
while (weiter == true) { if (zahl % 21 == 0) { document.write(zahl + " ist durch 21 teilbar"); weiter = false; } zahl--; }
//-->
Auch dieses Beispiel lässt sich natürlich mit einer for-Schleife realisieren. Hier ist die while-Schleife ohne die zwei zusätzlichen Parameter jedoch praktischer, da in einer for-Schleife die Bedingung nicht mit den Zählervariablen übereinstimmen würde: for (var zahl = 100; weiter == true; zahl--) {
ist für das Verständnis nicht sehr sinnvoll. Die while-Schleife im letzten Beispiel ließe sich auch noch einfacher gestalten, indem die Bedingung auf true gesetzt und in der if-Anweisung break verwendet würde: while (true) { if (zahl % 21 == 0) { document.write(zahl + " ist durch 21 teilbar"); break; } zahl--; }
Dies funktioniert zwar identisch, balanciert allerdings noch näher an der Endlosschleife, da die Bedingung nie false werden kann.
KOMPENDIUM
JavaScript
127
Kapitel 4
Programmieren
Abbildung 4.24: Die erste durch 21 teilbare Zahl wurde gefunden und ausgegeben.
do while Die do while-Schleife überprüft die Bedingung erst am Ende: do { Anweisungen; } while (Bedingung)
Das heißt auch, dass die Anweisungen im Schleifenkörper mindestens einmal ausgeführt werden, unabhängig davon, ob die Bedingung am Anfang erfüllt oder nicht erfüllt ist. do while gehört noch nicht seit den Anfängen zu JavaScript wie die anderen Schleifen. Netscape 2 und 3 und Internet Explorer 3 in beiden Varianten unterstützen sie nicht. Aus heutiger Sicht werden allerdings alle aktuellen und wichtigen Browser unterstützt. Tabelle 4.10: do while-Schleife
128
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
Ein Beispiel verdeutlicht die Besonderheit der do while-Schleife: do while-Schleife <script language="JavaScript"> Abbildung 5.12: Der Text aus dem Formularfeld wird in einem Warnfenster ausgegeben.
5.2
Funktionen als Operator
Funktionen können auch als Wert für eine Variable definiert werden. Man spricht dann von einem so genannten Funktionsliteral. Das Schlüsselwort function bildet einen Operator. Diese Möglichkeit ist noch recht neu (siehe Tabelle 5.2). Tabelle 5.2: Funktionen als Operator
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Nachfolgend die Syntax: var Name = function(Parameter1, Parameter2) { Anweisungen; }
Bei dieser Art der Funktionsdefinition wird der Funktionsname weggelassen. Der Aufruf erfolgt wie bei normalen Funktionen auch. Als Funktionsname wird der Name der Variablen verwendet: Name(Parameter1, Parameter2);
144
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5
So lässt sich das bisher verwendete einfache Beispiel mit einer Funktion, die einen Parameter quadriert zurückgibt, sehr einfach auch mit einem Funktionsliteral umsetzen: Funktion als Operator <script language="JavaScript">
Listing 5.12: Eine Funktion als Operator (funktion_operator. html)
//--> Abbildung 5.13: Die Funktion als Operator liefert das richtige Ergebnis.
Funktionen als Operator dürfen wie normale Funktionen verschachtelt werden. Sie können sogar in Fallunterscheidungen und Schleifen eingebunden werden. Funktionen lassen sich auch als JavaScript-Objekt definieren und verwenden. Mehr dazu erfahren Sie in Kapitel 6 »Objekte«.
5.3
Globale Funktionen
JavaScript besitzt einige Funktionen, die Sie in Ihren Skripten jederzeit und überall nutzen können. Daher heißen diese Funktionen auch globale Funktionen. Diese Funktionen haben verschiedenste Anwendungsgebiete. Im Folgenden finden Sie einen gesammelten Überblick, einzelne Funktionen begegnen Ihnen in anderen Kapiteln wieder. Die meisten Möglichkeiten liefert JavaScript allerdings in Objekten. Zur Arbeit mit Objekten lesen Sie das nächste Kapitel. Später wird in fast allen Kapiteln mit Objekten programmiert.
KOMPENDIUM
JavaScript
145
Kapitel 5
Funktionen
Zahlentests Die zwei Funktionen isFinite(Zahl) und isNaN(Wert) kennen Sie bereits: isFinite(Zahl) liefert true, wenn die als Parameter übergebene Zahl nicht größer oder kleiner als die maximal in JavaScript darstellbare Zahl ist. Listing 5.13: Test auf Unendlichkeit (infinite.html)
isFinite <script language="JavaScript">
Abbildung 5.14: Irgendwann ist für JavaScript bei Zahlen Schluss.
isNaN(Wert) gibt true zurück, wenn es sich bei einem Wert nicht um eine
Zahl, sondern einen anderen Datentyp handelt. Listing 5.14: Test, ob eine Variable eine Zahl ist (Ausschnitt aus: isNaN.html)
var x = "text"; if (isNaN(x)) {
document.write("x ist keine Zahl"); }
Unendlichkeit testen Wer hat sich nicht schon einmal dafür interessiert, wann die Unendlichkeit eintritt? Vermutlich jeder, der sich nicht mit Philosophie oder Mathematik beschäftigt. Es kann jedoch ganz interessant sein, festzustellen, wo JavaScript seine Unendlichkeitsgrenze hat. Folgendes Skript erledigt das mit einer einfachen Schleife:
146
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5 Abbildung 5.15: Die Variable x ist keine Zahl.
Unendlichkeitstest <script language="JavaScript">
Listing 5.15: Testen, wo die Unendlichkeit in JavaScript liegt (unendlich.html)
} //--> Abbildung 5.16: Die Zahl in der zweiten Zeile lässt sich in JavaScript noch anzeigen.
Datentypen ändern JavaScript konvertiert Datentypen zwar automatisch (siehe Kapitel 3.3 unter »Typkonvertierung«), manchmal ist es allerdings dennoch nötig, Hand anzulegen.
KOMPENDIUM
JavaScript
147
Kapitel 5
Funktionen In String konvertieren Die Funktion toString()dient dazu, einen beliebigen Datentyp in einen String zu konvertieren. Sie steht als Methode für sämtliche JavaScript- und DOM-Objekte zur Verfügung (mehr zu Objekten erfahren Sie in Kapitel 6 »Objekte«).
Listing 5.16: Mit toString() in eine Zeichenkette konvertieren (Ausschnitt aus: tostring.html)
var x = 3; document.write(x.toString() + 3);
Abbildung 5.17: Die Zahlen werden nicht addiert, sondern hintereinander ausgegeben, da das Skript die erste Zahl in einen String umgewandelt hat.
Tabelle 5.3: toString()
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
toString() ist auch in Uralt-Browsern ab Netscape 2 und Internet Explorer 3
verfügbar. toString() hat bei verschiedenen Datentypen unterschiedliche Auswirkun-
gen: Strings bleiben Strings. Booleans (Wahrheitswerte) werden als »true« oder »false« ausgegeben. Zahlen werden direkt in Strings umgewandelt. Bei Arrays werden die einzelnen Array-Elemente durch Kommata getrennt ausgegeben. Bei Objekten können nur manche einen sinnvollen String liefern, beispielsweise, wenn sie eine Eigenschaft haben.
148
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5
Als optionaler Parameter für toString(Basis) können Sie die Basis angeben, wenn Sie eine Zahl umwandeln1: 10 ist das Dezimalsystem. 2 steht für die binäre Schreibweise. Folgender Code gibt also 11 aus, das Binärmuster für 3. var x = 3; document.write(x.toString(2));
16 ist die Basis für die hexadezimale Schreibweise. Dieser Code gibt also ff aus. var x = 255; document.write(x.toString(16));
8 bildet die Basis für die oktale Schreibweise. Folgender Code gibt für 24 den oktalen Wert 30 aus. var x = 24; document.write(x.toString(8));
Informationen zu den unterschiedlichen Schreibweisen erhalten Sie in Kapitel 3.1 unter »Integer« und für die binäre Schreibweise in Kapitel 4.1 unter »Bitweise Operatoren«. In Zahlen konvertieren Um Strings in Zahlen zu konvertieren, gibt es drei mögliche Funktionen: Number(String) wandelt einen String entweder in ein Integer oder eine
Gleitkommazahl um, je nachdem, ob sich im String ein Dezimalpunkt befindet. Handelt es sich bei dem String nicht um eine umwandelbare Zahl, liefert die Funktion NaN zurück. Folgende Zeilen geben also 8.4 aus. var x = "5.4"; document.write(Number(x) + 3);
Bei älteren Browsern, Netscape 2 und 3 und Internet Explorer 3 in beiden Varianten, funktioniert Number() noch nicht. Neuere Browser werden allerdings alle unterstützt. Die anderen zwei Konvertierungsfunktionen stehen auch für die genannten älteren Browser zur Verfügung.
1
Netscape 2 und Internet Explorer 3 in der ersten Version können dies nicht.
KOMPENDIUM
JavaScript
149
Kapitel 5 Tabelle 5.4: Number()
Funktionen
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
parseFloat(String) wandelt die Zeichenkette automatisch in eine Fließ-
kommazahl um. Beachten Sie, dass im Deutschen Fließkommazahlen mit Komma geschrieben werden. Die korrekte Umwandlung funktioniert aber nur, wenn statt des Kommas ein Punkt angegeben wird. parseInt(String) wandelt den String in ein Integer um. Eventuell vorhandene Nachkommastellen werden weggelassen. Wie bei toString (String, Basis) lässt sich auch hier die Basis angeben (parseInt(String, Basis) (Werte siehe toString())).
Sie können die hier beschriebenen Funktionen auch dazu verwenden, um eine Zahl aus Text herauszuschneiden. Die Funktionen wandeln die Zahl um, die am Anfang der Zeichenkette stehen muss. Der komplette nachfolgende Text wird abgeschnitten. Folgender Code schneidet beispielsweise die Währungsangabe Euro hinter den Beträgen ab, rechnet sie zusammen und gibt das Ergebnis wieder mit der Währungsangabe aus: Listing 5.17: Währung abschneiden und anfügen (parseFloat_ abschneiden.html)
Mit parseFloat() Text abschneiden <script language="JavaScript">
//--> Abbildung 5.18: Das Ergebnis ist wieder mit der Währungsangabe versehen.
150
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5
Vorsicht ist allerdings angebracht, wenn Nachkommastellen mit Komma angegeben sind. Diese ignoriert parseFloat(), da die Funktion nur Dezimalpunkte kennt.
eval() Die Funktion eval(String) ist recht mächtig. Sie wertet den als Parameter übergebenen String als JavaScript-Code aus. Das klingt noch nicht so spannend? JavaScript-Code wird prinzipiell in drei Bereichen ausgeführt. Im allgemeinen Code zwischen den <script>-Tags, in Funktionen und als eval()Anweisung. Wenn der JavaScript-Interpreter ein Skript bearbeitet, führt er die Anweisungen zwischen den <script>-Tags sofort aus. Funktionen werden »vorkompiliert«, das heißt, ihre Anweisungen werden im Hauptspeicher abgelegt und mit dem Funktionsnamen verknüpft, falls er aufgerufen wird. Die eval()-Anweisung dagegen wird beim Aufruf ausgeführt. Da es sich hier um die Lösung mit der geringsten Performanz handelt, wird insbesondere bei größeren Anwendungen häufig auf sie verzichtet. Folgendes Beispiel erlaubt dem Nutzer die Eingabe von JavaScript-Code in einem Textfeld. Klickt er anschließend auf die Schaltfläche, wird die Funktion ausgabe() aufgerufen. Sie führt den im Textfeld eingegebenen Code mit eval() als JavaScript-Code aus. eval() <script language="JavaScript">
Listing 5.18: Mit eval() ein Eingabeformular für Code programmieren (eval.html)
//-->
Code-Eingabe
Wird in eval() ein Objekt ausgewertet, gibt eval() eine Verknüpfung auf das Objekt zurück.
KOMPENDIUM
JavaScript
151
Kapitel 5
Funktionen
Abbildung 5.19: Der Nutzer gibt JavaScript-Code im Textfeld ein. Beim Anklicken der Schaltfläche wird der Code ausgewertet und das Ergebnis ausgegeben.
eval("window");
ist also eine Verknüpfung auf das window-Objekt. Folgender Code gibt alle Eigenschaften des window-Objekts zurück: Listing 5.19: Objektverknüpfung mit eval() (eval_rueckgabe. html)
eval() mit Rückgabe <script language="JavaScript">
Eine Alternative zu eval() ist die Methode execScript(String, Sprache). Sie ist eine Methode des window-Objekts (siehe Kapitel 6 »Objekte«) und kann Code in verschiedenen Sprachen ausführen. Mögliche Parameter für die Sprache sind JavaScript, JScript und VBScript. Insbesondere, wenn Sie Code in einer anderen Sprache, beispielsweise VBScript, ausführen möchten, ist diese Methode hilfreich. Im Gegensatz zu eval() liefert sie nichts zurück. Allerdings bleibt sie auf den Internet Explorer beschränkt.
152
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5 Abbildung 5.20: Eigenschaften des window-Objekts
URLs Eine URL (Uniform Resource Locator) in der Adressleiste des Browsers wird nicht in normaler Schreibweise dargestellt. Leerzeichen entsprechen beispielsweise dem Hexadezimalcode %20. Daher müssen Sie, wenn Sie in JavaScript mit URLs arbeiten, diese erst umwandeln. Die Schreibweise für URLs heißt URI-Codierung (Encoding). URI steht für Uniform Resource Identifier. Die Funktion escape(String) wandelt eine normale Zeichenkette in URICodierung um. escape() <script language="JavaScript"> Zu rundende Zahl
Ergebnis
Abbildung 6.12: JavaScript rundet die Zahl.
Bei negativen Zahlen wird -4,50 auf -4 aufgerundet und erst -4,51 auf -5 abgerundet. Vorsicht, das wird häufig falsch gemacht. Nachkommastellen runden Wollen Sie eine Zahl in den Nachkommastellen runden, müssen Sie den Dezimalpunkt erst um so viele Stellen nach links verschieben, wie Sie runden möchten. In wenigen Schritten lässt sich Listing 6.4 so anpassen, dass es auf zwei Stellen hinter dem Komma rundet: In der Funktion kommt eine neue Variable als Zwischenspeicher zum Einsatz. Dies erhöht die Übersichtlichkeit.
KOMPENDIUM
JavaScript
173
Kapitel 6
Objekte Der Variablen wird als Wert das gerundete Ergebnis der um zwei Stellen nach links verschobenen Zahl übergeben. Für die Verschiebung multipliziert das Skript einfach mit 100. var r = Math.round(feld.value * 100);
Nun muss die Verschiebung um zwei Stellen nach links rückgängig gemacht werden. Dazu dient die Division durch 100. r = r / 100;
Abschließend erhält das zweite Textfeld mit Namen erg den gerundeten Wert zugewiesen. document.formular.erg.value = r;
Der vollständige Code sieht wie folgt aus: Listing 6.5: Nachkommastellen runden (runden_nachkom ma.html)
Nachkommastellen runden <script language="JavaScript">
} //--> Zu rundende Zahl
Ergebnis Abbildung 6.13: Das Rundungsskript rundet nun auf zwei Stellen hinter dem Komma.
174
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Ändern Sie einfach den Multiplikator, je nachdem auf wie viele Stellen Sie runden möchten. Wollen Sie auf drei Stellen hinter dem Komma runden, multiplizieren Sie beispielsweise mit 1.000. Soll bereits vor dem Dezimalpunkt gerundet werden, teilen Sie durch ein Vielfaches von 10. max() und min() Math.max() und Math.min() wurden in neueren Browsern verbessert. Sie können nun auch beliebig viele Zahlen miteinander vergleichen und die größte beziehungsweise kleinste herausfinden. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
max
min
Tabelle 6.4: Math.max() und Math.min()
Das folgende Beispiel gibt bei einem Vergleich aus drei Zahlen die größte aus. Zwei der Zahlen werden noch in der max()-Methode mit arithmetischen Operatoren (siehe Kapitel 4.1 »Operatoren«) aus Variablenwerten errechnet: max() mit mehreren Zahlen <script language="JavaScript">
Listing 6.6: max() mit mehreren Zahlen (max_neu.html)
var x = Math.max(5.2, b / a, a * 2);
document.write(x); //--> Abbildung 6.14: Das richtige Ergebnis ist die dritte Zahl (a * 2 = 6).
KOMPENDIUM
JavaScript
175
Kapitel 6
Objekte Zufallszahlen Eine Zufallszahl ist schnell erzeugt.
Listing 6.7: Eine Zufallsdatei ausgeben (zufall.html)
Zufall <script language="JavaScript">
document.write(x); //--> Abbildung 6.15: Eine Zufallszahl
Beliebige Zufallszahlen Die Zahlen von 0 bis 1 – dazu noch in einer Genauigkeit von 17 Stellen – sind zwar schön, für die meisten Fälle aber nicht ausreichend. Nehmen wir an, Sie brauchen die Zufallszahlen in einer beliebigen Spanne von x bis y, dann hilft folgende Formel: x + Math.random() * (y – x)
Sollen die Zufallszahlen nur ganze Zahlen sein, müssen Sie das Ergebnis nur noch runden. Im folgenden Beispiel verwenden wir eine Zufallszahl, um damit Bilder mit den Namen 1 bis 6 zufällig aufzurufen. Diese Bilder zeigen verschiedene Augenzahlen eines Würfels. Für das Beispiel finden Sie die benötigten Bilddateien mit den Augenzahlen des Würfels. Sie befinden sich im Ordner code\kap6 und heißen 1.jpg bis 6.jpg. Listing 6.8: JavaScript simuliert einen Würfel (wuerfel.html).
176
Würfeln
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
<script language="JavaScript">
//--> Abbildung 6.16: Der Würfel zeigt eine 5.
Date Das Date-Objekt muss – im Gegensatz zu Math – immer mit new instanziiert werden. var datum = new Date();
Diese Zeile weist der Variablen datum das Date-Objekt und damit das aktuelle Datum und die aktuelle Zeit zu. Folgendes Skript gibt das Datum sofort aus: Datum <script language="JavaScript">
Aber es geht auch etwas einfacher. Die folgende Schleife gibt alle Uhrzeiten in allen Zeitverschiebungen aus. Dies funktioniert wie folgt: Zuerst wird ein neues Date-Objekt mit dem aktuellen Datum instanziiert. var datum = new Date();
KOMPENDIUM
JavaScript
183
Kapitel 6
Objekte
Abbildung 6.22: Die Zeitverschiebung ausrechnen
In einer zweiten Variablen aktuell speichert das Skript die aktuelle Zeit in Millisekunden seit dem 1.1.1970, 00:00 GMT. Die Zeit in Millisekunden ist der Schlüssel zur Lösung des Umrechnungsproblems. Denn mit den Millisekunden zu einer festen Basis können Sie mit Daten rechnen (siehe Abschnitt »Mit Daten rechnen«)! var aktuell = datum.getTime();
Die dritte Variable nimmt die Zeitzonenverschiebung der aktuellen Zeit in Minuten auf. var zone = datum.getTimezoneOffset();
Das Herzstück des kleinen Programms ist die for-Schleife. Die Zählervariable läuft über die ganzen Zeitzonen von -12 bis +12. for (var i = -12; i < 13; i++) {
In der Schleife wird zuerst die Zeitzone (in Millisekunden5) von der aktuellen Zeit abgezogen. Anschließend wird die Zeitverschiebung (gespeichert in der Zählervariablen i) ebenfalls in Millisekunden6 dazugezählt. var erg = aktuell + zone * 60 * 1000 + i * 60 * 60 * 1000;
Ein neues Date-Objekt erhält den Zeitwert in Millisekunden. Daraus wird automatisch ein neues Datum gebildet. var time = new Date(erg);
5 6
184
Die Umrechnung von Minuten in Millisekunden lautet: Minuten * 60 * 1.000 = Millisekunden. Die Umrechnung von Stunden in Millisekunden lautet: Stunden * 60 * 60 * 1.000 = Millisekunden.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Als Nächstes geben wir Teile des Datums, hier Stunden und Minuten, aus. document.write(time.getHours() + ":" + time.getMinutes()); document.write(" " + i + " GMT
"); }
Nachfolgend der vollständige Code: Zeitverschiebung <script language="JavaScript">
Listing 6.13: Die Zeitverschiebung in allen Zeitzonen (zeitverschiebung_ einfach.html)
Der Internet Explorer 3 liefert die Zeitverschiebung mit getTimezoneOffset() mit umgekehrtem Vorzeichen: für den deutschsprachigen Raum also +60 statt -60 (siehe Abbildung 6.23). Wollen Sie hier einen Fehler in der Rechnung vermeiden, müssen Sie eigens auf den Internet Explorer 3 prüfen. Eine entsprechende Prüfbedingung könnte wie folgt aussehen: navigator.appVersion.indexOf('MSIE 3') != -1
Mehr zur Browserunterscheidung erfahren Sie in Kapitel 12 »Browserunterscheidung«. Eigene Daten Im letzten Beispiel (siehe Listing 6.13) gibt bereits ein Betrag in Millisekunden das Datum für ein neues Date-Objekt vor. Die Syntax dazu sieht folgendermaßen aus: var datum = new Date(Millisekunden);
KOMPENDIUM
JavaScript
185
Kapitel 6
Objekte
Abbildung 6.23: Die aktuelle Uhrzeit in allen Zeitzonen
Das Datum wird aus den Millisekunden seit dem 1.1.1970, 00:007 GMT errechnet. var datum = new Date(264290400000);
entspricht beispielsweise dem 18. April 1978. Sie haben aber noch eine andere Möglichkeit, ein eigenes Datum anzugeben. Zuerst wieder die Syntax: var datum = new Date(Jahr, Monat, Tag, Stunden, Minuten, Sekunden, Millisekunden);
7
186
Dieser Zeitpunkt wird als Beginn der Unix-Epoche festgelegt. Das Datum in Millisekunden heißt seitdem auch Unix-Zeitstempel.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Die Angaben von Jahr, Monat und Tag sind hier obligatorisch. Das Jahr muss vierstellig angegeben werden. Der Monat von 0 (Januar) bis 11 (Dezember) und der Tag von 1 bis 31. Optional sind die Angaben der Zeit. Wenn sie erfolgen, dann allerdings in der festgesetzten Reihenfolge. Sie können also nicht nur Sekunden angeben, aber keine Minuten und Stunden. Die Stunden werden von 0 (Mitternacht) bis 23 angegeben, die Minuten von 0 bis 59, die Sekunden ebenfalls von 0 bis 59 und die Millisekunden von 0 bis 999. var datum = new Date(1978, 3, 18); var datum2 = new Date(2001, 12, 6, 9, 30, 0);
In der oberen Zeile wird nur das Datum übergeben, die Zeit wird automatisch auf 00:00:00 Uhr gestellt. In der unteren Zeile ist auch eine Zeitangabe bis hin zu Sekunden, aber ohne Millisekunden vorhanden. Abbildung 6.24: Ohne Uhrzeitangabe (erste Zeile des Codes) stellt der Interpreter die Uhrzeit auf 00:00:00.
Das Jahr-2000-Problem Das Jahr-2000-Problem8 haben viele bereits abgehakt. War ja alles nicht so schlimm … Das stimmt zwar teilweise, allerdings gilt es nach wie vor, vorsichtig zu sein. In JavaScript gibt es die Methoden getYear() und setYear(). Sie arbeiten mit einer zweistelligen Jahreszahl. Das folgende Beispiel zeigt die Probleme: Jahr 2000 <script language="JavaScript">
Listing 6.14: getYear() hat ein Jahr-2000-Problem (jahr2000.html).
auch Y2K genannt
KOMPENDIUM
JavaScript
187
Kapitel 6
Objekte document.write(datum2.getYear()); //-->
Der Internet Explorer behilft sich damit, alle Jahre über 2000 vierstellig auszugeben (siehe Abbildung 6.25). Abbildung 6.25: Der Internet Explorer 6 gibt das Jahr 2002 vierstellig aus.
Im Netscape Navigator 7 funktioniert diese Krücke nicht mehr (siehe Abbildung 6.26). Abbildung 6.26: Das Jahr 2002 verkommt zu 102.
Den besten Ausweg bei diesen Problemen bietet die Methode getFullYear(), die das Jahr vierstellig zurückgibt. In sehr alten Browsern, Netscape 2 und 3 und Internet Explorer 3 in der ersten Version, ist diese Methode allerdings noch nicht enthalten. In diesem Fall hilft nur eine Fallunterscheidung, die Sie am einfachsten in eine Funktion packen: Listing 6.15: Jahr-2000-Fallunterscheidung (jahr2000_faelle. html)
188
Jahr 2000 Fallunterscheidung
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
<script language="JavaScript"> 100 && jahr < 200) { return jahr + 1900; } else { return jahr; } }
var datum = new Date(1978, 4, 18); document.write(getJahr2000(datum) + "
"); var datum2 = new Date(2002, 3, 4); document.write(getJahr2000(datum2)); //-->
Die Fallunterscheidung hat nur einen Haken. Liegt das Jahr zwischen 100 und 200, weil Sie beispielsweise über die römische Kaiserzeit schreiben, funktioniert die Fallunterscheidung nicht mehr. Abbildung 6.27: Auch Netscape 2 kommt jetzt mit den Daten zurecht.
Wenn Sie die if-Bedingung verändern, können Sie natürlich auch die Jahre vor 2000 vierstellig schreiben. Entfernen Sie dazu einfach die Bedingung jahr > 100. Wollen Sie die Jahre ab 2000 mit zweistelliger Endung9 angezeigt bekommen, ziehen Sie einfach 100 ab, statt 1900 dazuzuzählen. Allerdings müssen Sie noch einen zusätzlichen Fall für die neueren Internet Explorer (im Listing hervorgehoben) einfügen, da sie das Jahr vierstellig ausgeben:
9
Hier besteht natürlich Verwechslungsgefahr mit den Jahren 1900, 1901 usw. Andererseits wird eine zweistellige Jahreszahl häufig bei der Bezeichnung von Jahrgängen oder aktuellen Dokumenten wie Auftragsbestätigungen und Bestellungen benötigt. Sie automatisch in JavaScript zu generieren, ist also durchaus öfter notwendig.
KOMPENDIUM
JavaScript
189
Kapitel 6
Objekte function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr > 100 && jahr < 200) { return jahr - 100; } else if (jahr > 1999){ return jahr - 2000; } else { return jahr; } }
Soll das Jahr auch bei einstelligen Ziffern zweistellig sein, müssen Sie noch einen String hinzufügen. Dafür muss wieder eine if-Bedingung herhalten: Listing 6.16: Jahreszahlen zweistellig und IE-kompatibel (zweistellig_ie.html)
function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr > 100 && jahr < 200) { jahr -= 100; if (jahr < 10) { return "0" + jahr; } else { return jahr; }
} else if (jahr > 1999){ jahr -= 2000; if (jahr < 10) { return "0" + jahr; } else { return jahr; }
} else { return jahr; } } Abbildung 6.28: Auch im IE klappt es jetzt mit den zweistelligen Jahreszahlen.
Daten aus der Vergangenheit Sehr alte Browser unterstützen keine Daten vor dem 1.1.1970, 00:00:00 GMT. Dazu gehören der Netscape Navigator 2 und 3 sowie der Internet Explorer 3 in der ersten Version. Bei diesen Browsern können Sie ältere Daten also nicht als Date-Objekt speichern. 190
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Mit Daten rechnen Um mit Daten zu rechnen, müssen Sie sie immer in Millisekunden seit der Unix-Epoche, also seit dem ominösen 1.1.1970, 00:00:00 GMT, umrechnen. Dann funktioniert die Rechnung aber sehr einfach: Zuerst instanziieren Sie zwei Date-Objekte. var datum1 = new Date(1978, 3, 18); var datum2 = new Date(2001, 11, 6);
Anschließend ziehen Sie die mit getTime() in Millisekunden seit dem 1.1.1970 umgewandelten Datenwerte voneinander ab. var erg = datum2.getTime() - datum1.getTime();
Da das Ergebnis noch in Millisekunden vorliegt, wird es in Tage umgerechnet und abgerundet, damit ganze Tage herauskommen: erg = Math.floor(erg / (1000 * 60 * 60 * 24));
Abschließend gibt das Skript das Ergebnis aus: document.write(erg + " Tage"); Mit Datumswerten rechnen <script language="JavaScript">
Die Umformatierung von Daten ist auf manchen Websites eine sehr häufige Aufgabe. Hier lohnt es sich, die Umwandlung in eine Funktion oder eine Objektmethode zu packen und sie in einer externen JavaScript-Datei zur Verfügung zu stellen. Wir zeigen in Kapitel 8 »OOP«, wie Sie das DateObjekt um eine solche Methode erweitern können. Abbildung 6.34: Das Datum im manuell erstellten Format
Verbinden Sie die Datumsformatierung nun noch mit der Fallunterscheidung aus dem Abschnitt »Das Jahr-2000-Problem«, und Sie erhalten die Jahreszahl in korrekter Form auch für Netscape 2 und 3 und die erste Version des Internet Explorers 3. Listing 6.23: (Ausschnitt aus: datum_formatieren _y2k.html)
function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr < 200) { return jahr + 1900; } else { return jahr; } } . . . var datum = new Date(); . document.write(getJahr2000(datum));
Neue und spezielle Methoden Einige Methoden für das Date-Objekt sind erst in neueren Browsern hinzugekommen oder beschränken sich speziell auf den Internet Explorer. Tabelle 6.7 gibt einen Überblick und Tabelle 6.8 zeigt, in welchen Browsern die Methoden funktionieren. 198
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6 Abbildung 6.35: Mit der Jahr-2000Fallunterscheidung funktioniert das Skript sogar im Netscape Navigator 2.
Methode
Beschreibung
toDateString()
wandelt ein Date-Objekt in einen String um. Enthält nur das Datum, nicht die Zeit. Ist auf den Internet Explorer beschränkt.
toLocaleString()
gibt das Datum und die Uhrzeit als String zurück, wie auf dem lokalen System vorgesehen. Das Ergebnis ist vom Browser abhängig.
toLocaleDateString()
gibt nur das Datum im lokalen Format, abhängig vom Browser, zurück.
toLocaleTimeString()
gibt nur die Zeit in einem lokalen Format zurück. Das Aussehen ist vom Browser abhängig.
getVarDate()
liefert das Datum in dem Format VT_DATE, das bei der Interaktion mit ActiveX- und DOM-Objekten benötigt wird. Es ist auf den Internet Explorer beschränkt.
toTimeString()
liefert nur die Zeit als String.
Tabelle 6.7: Die neueren und speziellen Methoden des DateObjekts
Auf der CD-ROM finden Sie im Ordner code\kap06 für jede Methode ein Beispiel. Der Dateiname entspricht jeweils dem Namen der Methode.
NS4.x NS6
NS7
toDateString() toLocaleString()
KOMPENDIUM
JavaScript
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 6.8: Neue Methoden von Date
199
Kapitel 6 Tabelle 6.8: Neue Methoden von Date (Forts.)
Objekte
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
toLocaleDateString()
toLocaleTimeString()
getVarDate() toTimeString
Prinzipiell ist insbesondere der Einsatz der lokalen Datums- und Zeitstrings durchaus sinnvoll. Der Internet Explorer liefert sogar deutsche Tages- und Monatsnamen (siehe Abbildung 6.36). Das ist allerdings in der Praxis kaum verwertbar, da der Navigator auch in der deutschen Version 7 englische Namen und ein etwas anderes Format einsetzt (siehe Abbildung 6.37). Solange hier keine Einigkeit herrscht, bleibt dem Entwickler nichts anderes übrig, als das Datum selbst zu formatieren. Abbildung 6.36: Der Internet Explorer 6 verwendet deutsche Tagesund Monatsnamen.
Abbildung 6.37: Der Navigator kann nur Englisch – und das auf dem selben Rechner.
200
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Vorgefertigte Datumsobjekte Das Browserobjekt document besitzt drei Methoden, die Datumsformate zurückliefern: lastModified() – Zeitpunkt, an dem das Dokument zuletzt gespeichert
wurde fileCreatedDate() – Zeitpunkt, an dem das Dokument erstellt wurde. Beschränkt auf den Internet Explorer fileModifiedDate() – ebenfalls der Zeitpunkt, an dem das Dokument
zuletzt bearbeitet wurde, allerdings auf den Internet Explorer beschränkt. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
fileCreatedDate()
fileModifiedDate()
lastModified()
Tabelle 6.9: Methoden mit vorgefertigten Datumsobjekten
Da die drei Methoden auf Informationen vom Server angewiesen sind, können die Ergebnisse sehr unpräzise sein. Diesen Funktionen sollten Sie daher nicht unbedingt trauen. Ein einfaches Beispiel gibt das Datum aus, an dem das aktuelle Dokument zuletzt geändert wurde. Dateiinfo <script language="JavaScript"> Abbildung 8.11: Die Methode für das mit Object definierte Objekt liefert die richtige Ausgabe.
Eigenschaften und Methoden von Object Das Object-Objekt besitzt einige Eigenschaften und Methoden, die Sie in den nächsten Abschnitten beschrieben finden. Wie bereits erwähnt, stehen sie für alle Objekte in JavaScript zur Verfügung. Die Eigenschaften und Methoden des Object-Objekts sind neueren Datums (siehe Tabelle 8.7), fehlen also in älteren Browsern. NS4.x NS6
KOMPENDIUM
NS7
JavaScript
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 8.7: Eigenschaften und Methoden von Object
267
Kapitel 8
OOP hasOwnProperty() Die Methode hasOwnProperty("Eigenschaft") überprüft, ob eine Objektinstanz eine Eigenschaft besitzt. Wenn dies der Fall ist, liefert sie true, sonst false. Der Name der Eigenschaft wird als Parameter übergeben. Beachten Sie, dass er ein String sein muss, also in Anführungszeichen steht. Das folgende Beispiel testet, ob die Eigenschaft Vorkommen in der Objektinstanz Wuschl vorhanden ist.
Listing 8.10: hasOwnProperty() im Einsatz
(hasOwnProperty.html)
hasOwnProperty() <script language="JavaScript">
Die Methode hasOwnProperty() liefert im Beispiel true, da eine Eigenschaft mit dem Namen vorhanden ist (siehe Abbildung 8.12). Abbildung 8.12: Die Eigenschaft ist vorhanden.
Eine per prototype zugewiesene Eigenschaft wird in die Überprüfung nicht mit einbezogen: document.write(Wuschl.hasOwnProperty("Laut"));
liefert also false.
268
KOMPENDIUM
JavaScript
Das Objekt Object und die Vererbungskette
Kapitel 8
propertyIsEnumerable() propertyIsEnumerable("Eigenschaft") ist eigentlich eine Eigenschaft, die aber ähnlich wie die Methode hasOwnProperty("Eigenschaft") arbeitet.6 Sie geben eine Eigenschaft als Parameter an und propertyIsEnumerable() liefert zurück, ob das Objekt die Eigenschaft besitzt (true) oder nicht (false).
In Listing 8.10 ändert sich nur die Ausgabezeile mit dem Zugriff auf die Eigenschaft propertyIsEnumerable() statt hasOwnProperty(): document.write(Wuschl.propertyIsEnumerable("Vorkommen"));
Die Ausgabe ist dieselbe, wie in Abbildung 8.12 zu sehen.
Listing 8.11: propertyIsEnumerable() (property
IsEnumerable.html)
In den aktuellen Browserversionen gibt es keinen Unterschied zwischen propertyIsEnumerable() und hasOwnProperty(). propertyIsEnumerable() ist allerdings eigentlich dafür vorgesehen, in einer for-in-Schleife durchlaufen werden zu können. isPrototypeOf() Die Methode isPrototypeOf(Objekt) liefert als Ergebnis, ob ein Objekt in einer prototype-Verknüpfung mit dem aktuellen Objekt steht: Objekt.isPrototypeOf(Objekt);
Diese Methode wird in der Praxis recht selten benötigt. Nachfolgend finden Sie dennoch ein einfaches Beispiel: isPrototypeOf() <script language="JavaScript">
Listing 8.12: isPrototypeOf()
(isPrototypeOf.html)
var Wuschl = new Vogel("Europa"); Vogel.prototype.Laut = "Tschiep"; document.write(Vogel.prototype.isPrototypeOf(Wuschl)); //--> 6
Microsoft nennt propertyIsEnumerable() eine Eigenschaft (beispielsweise http://msdn. microsoft.com/library/default.asp?url=/library/en-us/jscript7/html/jsproPropertyIs Enumerable.asp). Der Autor des Buches würde sie eher als Methode bezeichnen. Dies ist
allerdings eine in der Praxis nicht relevante Diskussion.
KOMPENDIUM
JavaScript
269
Kapitel 8
OOP
Das Skript prüft, ob das Objekt Vogel.prototype eine prototype-Verknüpfung mit der Objektinstanz Wuschl besitzt. Das Ergebnis ist true (siehe Abbildung 8.13). Dies entspricht natürlich auch den Erwartungen, da Wuschl eine Objektinstanz von Vogel ist und Vogel.prototype daher auch als prototypeObjekt für Wuschl verfügbar ist. Abbildung 8.13: true besagt, dass Wuschl eine prototype-Verbin-
dung mit dem Objekt Vogel.prototype besitzt.
toString(), toLocaleString() und valueOf() Die Funktionen toString(), toLocaleString() und valueOf() stehen über das Object-Objekt jedem Objekt zur Verfügung: toString()– wandelt das Objekt in eine Zeichenkette um. toLocaleString()– wandelt ebenfalls in eine Zeichenkette um, berück-
sichtigt aber lokale Einstellungen, die beispielsweise in der Sprachversion liegen können. Dies hat nur bei manchen Objekten wie Date (siehe Kapitel 6 »Objekte«) Auswirkungen. valueOf()– liefert den Wert eines Objekts. Bei einem Number-Objekt ist das eine Zahl, bei einem String-Objekt beispielsweise ein String.
Im folgenden Beispiel werden die drei Methoden auf ein eigenes Objekt angewendet: Listing 8.13: Objekt in String umwandeln (toString_toLocale String_valueOf.html)
270
function Vogel(vork) { this.Vorkommen = vork; } var Wuschl = new Vogel("Europa"); document.write(Wuschl.toString() + "
"); document.write(Wuschl.toLocaleString() + "
"); document.write(Wuschl.valueOf());
KOMPENDIUM
JavaScript
Vorhandene Objekte erweitern
Kapitel 8 Abbildung 8.14: Dreimal dieselbe Ausgabe
Die drei hier vorgestellten Methoden machen meist nur bei speziellen Objekten wie beispielsweise Date Sinn. Bei eigenen Objekten wird nur der Datentyp ausgegeben (siehe Abbildung 8.14).
8.6
Vorhandene Objekte erweitern
prototype bietet noch mehr Möglichkeiten, als nur die Vererbung in eigenen Objekten. Auch bestehende JavaScript-Objekte können so erweitert werden. Ein mögliches Anwendungsgebiet ist, Methoden für ältere Browserversionen selbst zu schreiben, die nur in neueren Browsern vorhanden sind. Dieser Abschnitt zeigt Ihnen, wie Sie ein bestehendes Objekt um eine eigene Funktionalität erweitern.
Als Beispiel dient das Date-Objekt. Es soll eine Methode erhalten, die das Datum in ein in Deutschland übliches Format umwandelt. Das Beispiel besteht aus zwei Teilen: Einer externen JavaScript-Datei mit der Endung .js. Sie enthält den Quellcode der Methode und definiert die Methode für das Date-Objekt. Einer HTML-Datei, die die externe JavaScript-Datei lädt und in einem weiteren Skript-Block die neue Methode von Date verwendet. Die externe Datei enthält zuerst eine Definition der neuen Methode: Date.prototype.deformat = de_format;
Die neue Methode heißt also deformat und wird als Methode des prototypeObjekts definiert. Sie könnten die Methode natürlich sofort bei der Zuweisung mit function beginnen lassen. Hier ist es allerdings günstiger, den Code über den Funktionsnamen (de_format) aufzurufen, da das Listing sonst unübersichtlich wird.
KOMPENDIUM
JavaScript
271
Kapitel 8
OOP Die Methode selbst ist eine Abwandlung der Datei datum_formatieren_ y2k.html aus Kapitel 6 »Objekte«. Sie finden Sie auf der CD-ROM im Ordner code\kap06. In der Funktion wurde hauptsächlich das aktuelle Datum durch das Schlüsselwort this ersetzt, denn die Methode soll ja immer auf das gerade aktuelle Datumsobjekt angewendet werden können. Darüber hinaus musste die Ausgabe mit document.write() der Rückgabe einer Ergebnisvariablen (return erg;) weichen. Hier der vollständige Code:
Listing 8.14: Die externe JavaScript-Datei (erweitern.js)
Date.prototype.deformat = de_format; function de_format() { function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr < 200) { return jahr + 1900; } else { return jahr; } } var monat = new Array(12); monat[0] = "Januar"; monat[1] = "Februar"; monat[2] = "März"; monat[3] = "April"; monat[4] = "Mai"; monat[5] = "Juni"; monat[6] = "Juli"; monat[7] = "August"; monat[8] = "September"; monat[9] = "Oktober"; monat[10] = "November"; monat[11] = "Dezember"; var erg = this.getDate() + ". "; erg += monat[this.getMonth()] + " "; erg += getJahr2000(this); return erg; }
Nun zur HTML-Seite. Um die Methode dort anzuwenden, müssen Sie nur eines tun: Binden Sie die externe JavaScript-Datei in ein <script>-Tag ein. Auf die Methode wird ganz gewöhnlich mit dem Methodennamen zugegriffen. Das Objekt im Beispiel wurde vorher instanziiert.
272
KOMPENDIUM
JavaScript
Vorhandene Objekte erweitern
Kapitel 8
Nachfolgend sehen Sie den Code: Objekte erweitern <script src="erweitern.js" language="JavaScript">
<script language="JavaScript">
Listing 8.15: In der HTML-Seite wird die neue Methode des DateObjekts verwendet (erweitern.html).
In unserem Beispiel verwenden wir das Tagesdatum (siehe Abbildung 8.15). Sie können aber natürlich auch ein beliebiges Datum von der neuen Methode sauber formatieren lassen. Abbildung 8.15: Das Datum, sauber formatiert
Dieses Beispiel gibt einen kleinen Ausblick auf die Möglichkeiten, Objekte zu erweitern. Die Vorteile liegen auf der Hand: –
Sie müssen nur eine externe JavaScript-Datei einbinden. Dann können Sie alle darin definierten Eigenschaften und Methoden nutzen.
–
Die externe Datei lässt sich natürlich in beliebig vielen Seiten wieder verwenden. So schaffen Sie sich eine eigene kleine Eigenschaften- und Methoden-Bibliothek.
–
Methoden, die nur auf neueren Browsern laufen, können – selbst programmiert – auch auf älteren Browsern zur Mitarbeit bewegt werden.
Math erweitern Das Math-Objekt verhält sich beim Erweitern ein wenig anders. Hier verwenden Sie nicht das prototype-Objekt, sondern weisen die neue Methode direkt zu. Der Grund dafür: Math ist ein global verfügbares Objekt, das keine Objektinstanzen besitzt.
KOMPENDIUM
JavaScript
273
Kapitel 8
OOP Ein Beispiel erklärt dies. Ziel ist es, eine Methode zu definieren, die die Fakultät7 einer als Parameter übergebenen Zahl zurückliefert. Die Methode selbst befindet sich wieder in einer externen Datei. Dieses Mal wird sie dem Math-Objekt allerdings ohne prototype zugewiesen: Math.fak = fakultaet;
Hier sehen Sie den kompletten Code einschließlich der Funktion zur Berechnung der Fakultät: Listing 8.16:
Math.fak = fakultaet;
Math um eine
Methode zur Fakultätsberechnung erweitern (erweitern_math.js)
function fakultaet(x) { x = Math.round(x); var wert = 1; if(x > 0) { for (var i = x; i > 0; i--) { wert *= i; } } else { wert = "Zahl größer 0 angeben"; } return wert; }
Der Aufruf erfolgt, wie bereits im letzten Beispiel besprochen. Die externe JavaScript-Datei wird eingebunden, die Methode einfach verwendet. Das folgende Skript gibt also die Fakultät von 3 aus: Listing 8.17: Eine neue Methode des Math-Objekts verwenden (erweitern_mathe. html)
Objekte erweitern <script src="erweitern_math.js" language="JavaScript"> Abbildung 9.14: Die catch-Anweisung meldet, dass ein Fehler aufgetreten ist.
Da ältere Browser mit der try-catch-Anweisung nichts anfangen können, sollten Sie sie nur in Verbindung mit einer Browser-Fallunterscheidung einsetzen (siehe Kapitel 12 »Browserunterscheidung«) oder den Nutzern älterer Browser Alternativen bieten. Natürlich können Sie sich auch dafür entscheiden, nicht mehr Netscape 4.x- und Internet Explorer 4-kompatibel zu programmieren. Dies ist allerdings nur bei wenigen Nutzerzielgruppen – beispielsweise in einem Intranet – sinnvoll. finally In einer try-catch-Anweisung müssen sowohl try- als auch catch-Block enthalten sein. Optional lässt sich allerdings am Ende noch ein finally-Block anfügen. Er wird ausgeführt, nachdem try- und catch-Block oder nur der try-Block abgearbeitet sind. Die Anweisungen im finally-Block kommen also auf jeden Fall zum Einsatz.
KOMPENDIUM
JavaScript
295
Kapitel 9
Debugging try { Anweisungen; } catch(Ereignis) { Anweisungen; } finally { Anweisungen; } finally ist bereits in allen Browsern enthalten, die die try-catch-Anweisung
unterstützen (siehe Tabelle 9.1). Das folgende Beispiel zeigt alle Anweisungen und die Reihenfolge, in der sie ausgeführt werden (siehe Abbildung 9.15). Listing 9.5: finally und die
Reihenfolge der Ausführung (finally.html)
finally <script language="JavaScript">
} catch(e) { document.write("catch");
} finally { document.write("
finally"); } document.write("
Nach dem Block");
function ausgabe() { document.write("try
"); } //-->
Error-Objekt Mit dem Ereignis, das in der catch-Anweisung als Parameter übergeben wird, können Sie noch einiges anfangen. Das Ereignis ist ein Error-Objekt. Wie andere Objekte auch hat es Eigenschaften (aber keine Methoden). Die wichtigste Eigenschaft ist name. Sie liefert den Namen des Fehlers. Die name-Eigenschaft ist im Internet Explorer noch nicht seit dem Bestehen von try-catch enthalten, da Version 5 sie nicht unterstützt.
296
KOMPENDIUM
JavaScript
JavaScript Fehler-Handling
Kapitel 9 Abbildung 9.15: An der Reihenfolge der Ausgaben wird klar, in welcher Reihenfolge die Blöcke abgearbeitet werden.
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 9.2: name-Eigenschaft des Error-Objekts
Im folgenden Skript erweitern wir das Beispiel aus Listing 9.4 um eine Bestimmung der Fehlerart: Fehlerart bestimmen <script language="JavaScript">
Listing 9.6: Die genaue Fehlerart lässt sich auslesen (fehlerart.html).
//--> Abbildung 9.16: Ein TypeError (ein Fehler im Typ) war der Übeltäter.
KOMPENDIUM
JavaScript
297
Kapitel 9
Debugging Neben dem TypeError gibt es natürlich noch eine Reihe weiterer Fehler in JavaScript. Die folgende Tabelle gibt Ihnen einen Überblick.
Tabelle 9.3: Fehlerarten des Error-Objekts
Fehler
Beschreibung
Error
Ein allgemeiner Fehler. Er kann vom Programmierer selbst mit dem Schlüsselwort throw ausgeworfen (Synonym für ausgegeben) werden.
EvalError
Ein Fehler beim Aufruf der eval()-Funktion. Allerdings werden Syntax- und Tippfehler in eval()-Funktionen auch bei fehlenden Klammern oder falschen Anführungszeichen als SyntaxError erkannt (siehe weiter unten).
RangeError
Überschreiten des zulässigen (Zahlen-) Bereichs. Beispielsweise wird für ein Array eine negative Länge angegeben.
ReferenceError
Eine Referenz ist nicht vorhanden. Dieser Fehler tritt beispielsweise auf, wenn eine Variable nicht definiert ist (Netscape 6 und 7, Mozilla). Dies wird in anderen Browsern (z.B. IE 6) allerdings als TypeError eingestuft.
RegExpError
Ein Fehler in einem regulären Ausdruck
SyntaxError
Ein Syntaxfehler; viele Syntaxfehler wie fehlende Klammern oder falsche Anführungszeichen erzeugen allerdings eine direkte Fehlermeldung, da auch der try-catch-Block so nicht mehr richtig angezeigt wird und durcheinander gerät. Gegen einige Syntax- und Tippfehler ist also kein Kraut gewachsen.
TypeError
Meldet einen Fehler des Datentyps. Ein Objekt ist also beispielsweise nicht als Typ definiert.
URIError
Fehler in einem Link oder einem Verweis
Sie können natürlich auch auf Fehler unterschiedlicher Art verschieden reagieren. Eine einfache if- oder switch-Fallunterscheidung differenziert hier zwischen verschiedenen Fehlerarten. Das Problem bleibt allerdings, dass die unterschiedlichen Browser die Fehlerarten auch unterschiedlich festlegen. Eine nicht deklarierte Variable ist bei Netscape beispielsweise ein ReferenceError, im IE dagegen ein TypeError. In den folgenden Zeilen ist nur Variable x deklariert, y nicht: var x = 2; x += y;
Der Internet Explorer gibt einen TypeError aus (siehe Abbildung 9.17). Netscape dagegen einen ReferenceError (siehe Abbildung 9.18).
298
KOMPENDIUM
JavaScript
JavaScript Fehler-Handling
Kapitel 9 Abbildung 9.17: Ein TypeError im IE 6
Abbildung 9.18: Im Netscape Navigator (hier 6.2) dagegen ein ReferenceError
Die verschiedenen Fehlerarten sind selbst eigene Objekte (ab Netscape 6). Dies wird in der Praxis allerdings erst mit JavaScript 2.0 von Bedeutung sein, denn dort soll das Fehler-Handling weiter verbessert werden (siehe Anhang C »JavaScript 2.0 und die Zukunft«. Eigenschaften Neben name hat das Error-Objekt noch weitere Eigenschaften, die Sie in der folgenden Tabelle zusammengefasst finden. Eigenschaft
Beschreibung
description
Beschreibung des Fehlers. Da sie nur im Internet Explorer verwendbar ist, wird die Eigenschaft meist von message ersetzt.
fileName
Name der Datei, in der der Fehler auftrat
lineNumber
Zeile, in der der Fehler auftrat
message
Beschreibungstext zur Fehlermeldung. Im Gegensatz zu description auch im Netscape Navigator ab Version 6, aber nicht im Internet Explorer 5 enthalten.
name
Der bereits bekannte Name des Fehlers
number
Die Nummer des Fehlers. Sie ist spezifisch für den Internet Explorer.
KOMPENDIUM
JavaScript
Tabelle 9.4: Eigenschaften des Error-Objekts
299
Kapitel 9
Debugging Die folgende Tabelle zeigt, für welche Browser die Eigenschaften des ErrorObjekts geeignet sind. Folgende Besonderheiten sind zu beachten: Beim Opera ist zusätzlich die Eigenschaft opera#sourceloc definiert. Sie gibt die Position des Fehlers im Skript-Code an. Der Mozilla kennt zusätzlich die Eigenschaft stack, die eine Kombination aus Dateiname und Zeile ausgibt. Im Konqueror heißt die Eigenschaft lineNumber lediglich line.
Tabelle 9.5: Eigenschaften des Error-Objekts
NS4.x NS6
NS7
IE4 IE5
description
IE5.5 IE6
O7
M1
K3
fileName
lineNumber
()
message
name
number
Das folgende Beispiel liest alle Eigenschaften des Error-Objekts und gibt sie aus: Listing 9.7: Die Eigenschaften des Error-Objekts auslesen (eigenschaften.html)
Eigenschaften des Error-Objekts <script language="JavaScript">
} //-->
300
KOMPENDIUM
JavaScript
JavaScript Fehler-Handling
Kapitel 9
Der Opera 6 und 7 zeigt hier ein besonderes Verhalten. Er gibt mit dieser Schleife nur die message und seine eigene Eigenschaft opera#sourceloc aus, nicht aber die name-Eigenschaft, obwohl er sie kennt (Listing 9.6 funktioniert also im Opera). Abbildung 9.19: Eigenschaften des Error-Objekts im Internet Explorer 6 …
Abbildung 9.20: … im Mozilla …
throw Mit dem Schlüsselwort throw können Sie einen eigenen Fehler ausgeben. Programmierer machen ohnehin bereits genug Fehler, warum dann noch selbst welche erzeugen? Diese Frage ist berechtigt. Sehr häufig kommt throw nicht zum Einsatz, allerdings kann es sinnvoll sein, wenn beispielsweise bestimmte Eingaben verboten sind.
KOMPENDIUM
JavaScript
301
Kapitel 9
Debugging
Abbildung 9.21: … und im Konqueror
Tabelle 9.6: throw
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel überprüft, ob der Nutzer eine Zahl größer gleich 5 eingibt. Wenn dies nicht der Fall ist, wird mit throw ein Fehler erzeugt. Nach dem Schlüsselwort throw folgt das Error-Objekt und in Klammern als String die Beschreibung (entspricht der Eigenschaft message). Listing 9.8: Einen Fehler mit throw auswerfen (throw.html)
throw <script language="JavaScript">
} catch(e) { document.write(e.message); } //-->
302
KOMPENDIUM
JavaScript
JavaScript Fehler-Handling
Kapitel 9 Abbildung 9.22: Die Ausgabe wird von der catchAnweisung vorgenommen.
Sie können throw auch in Kurzform ohne Error-Objekt schreiben: throw "Beschreibung"
Fehlerereignis Neben der try-catch-Anweisung gibt es auch einen eigenen Event-Handler für die Fehlerbehandlung: onerror. Dieses Ereignis ist Teil des window-Objekts (siehe Kapitel 10 »Document Object Model«). NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 9.7: onerror
onerror ruft eine Funktion auf, die im Fehlerfall zum Einsatz kommt. Als Rückgabewert müssen Sie true zurückgeben, damit der Browser erkennt,
dass die Funktion sich um den Fehler gekümmert hat. Vergessen Sie diese Angabe, gibt der Browser eine JavaScript-Fehlermeldung aus. onerror <script language="JavaScript">)
9
Dokument
#document
Das Dokument selbst
10
DocType
DOCTYPE
Die Document Type Declaration (DTD)
11
Fragment
#document
Ein Teil des Dokuments, der aus einem oder mehreren Knoten bestehen kann
Tabelle 10.1: Knoten-Arten für HTML-Dokumente
Zugriff Das Knoten-Konzept verrät bereits viel über den Zugriff per DOM. Jeder Knoten ist über das DOM adressierbar. Dafür gibt es zwei unterschiedliche Methoden: Direktzugriff auf ein Element – die häufiger in der Praxis eingesetzte Variante Zugriff über die Navigation durch die Knoten-Hierarchie Direktzugriff Der Direktzugriff erfolgt über zwei Methoden des document-Objekts:
KOMPENDIUM
JavaScript
309
Kapitel 10
Document Object Model getElementById("ID") – liefert ein Element mit der ID, die als Parameter
übergeben wird. getElementsByTagName("Name") – gibt ein Array mit allen Elementen mit
dem als Parameter übergebenen Tag-Namen zurück. Bei beiden Methoden gibt es häufig Verwirrungen bei der Schreibweise. Die heikelsten Stellen sind: Die Id in getElementById wird mit einem kleinen »d« geschrieben. getElementsByTagName verwendet den Plural (»Elements«). Der Direktzugriff ist daher nicht ganz unproblematisch, weil er erst in neueren Browsern möglich ist. getElementsByTagName() hat auch im Opera 6 und niedrigeren Versionen nicht funktioniert. Dort stand nur getElementById() zur Verfügung. Tabelle 10.2: Die zwei Funktionen für den Direktzugriff
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
getElementById
getElementsByTagName
getElementById() getElementById("ID") wird in der Praxis sehr häufig eingesetzt, da es den
Zugriff auf genau ein Element erlaubt. Die ID des HTML-Elements, das angesprochen werden soll, muss in Klammern als String – also in Anführungszeichen – stehen. Im HTML-Tag wird die ID als HTML-Attribut zugewiesen. Eine ID darf nur einmal im gesamten Dokument vergeben sein. Häufig kommen daher IDs mit Nummern, beispielsweise a01, a02 usw., zum Einsatz. Das folgende Beispiel zeigt den Einsatz von getElementById(). Das Skript überträgt die Eingabe von einem Formularfeld in ein anderes, sobald der Nutzer die Schaltfläche anklickt. Zuerst wird einer Variablen das Element mit der ID ein zugewiesen. var ele = document.getElementById("ein");
Anschließend greift document.getElementById() auf das Ausgabefeld zu und ändert den Wert in den Wert des Eingabefelds. document.getElementById("aus").value = ele.value;
310
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Die zugehörige Funktion auslesen() ruft der Nutzer auf, wenn er auf die Schaltfläche klickt.
Listing 10.2: Der Einsatz von getElementById() (getele-
mentbyid.html)
var ele = document.getElementById("ein"); document.getElementById("aus").value = ele.value;
} //--> Eingabe
Ausgabe Abbildung 10.4: Ein Klick auf die Schaltfläche übergibt den Text im oberen Textfeld in das untere Feld.
KOMPENDIUM
JavaScript
311
Kapitel 10
Document Object Model Für den Zugriff auf Objekte der Seite sollten Sie das Skript immer erst beim Laden (Attribut onload mit Funktionsaufruf) oder in einem auf der Seite auftretenden Ereignis (z.B. onclick) ausführen, da ansonsten das Skript bereits ausgeführt wird, bevor alle Objekte der Seite geladen sind. getElementsByTagName() Der große Unterschied von getElementsByTagName("Name") zu getElementById() besteht darin, dass nicht bekannt ist, wie viele Elemente mit dem TagNamen im Dokument vorhanden sind. Als Rückgabe liefert die Methode also nicht nur einen Variablenwert, sondern ein ganzes Array mit allen Knoten, die ein Tag mit dem Namen haben. Der direkte Zugriff auf ein einzelnes Element ist also mit getElementById() wesentlich einfacher zu bewältigen. getElementsByTagName("Name") ist insbesondere dann sinnvoll, wenn Sie eine bestimmte Art von Tags, beispielsweise alle - oder alle
-Tags, gleichzeitig ändern möchten. Das folgende Beispiel macht sich dies zunutze und ändert die Schriftgröße für alle
-Tags, wenn der Nutzer auf die Schaltfläche klickt: Dazu dient eine Schleife, die mit length die Länge des Arrays überprüft und die ArrayElemente der Reihe nach ändert: Zuerst wird die Hilfsvariable elemente definiert. Sie erhält das Array mit allen
-Tags: var elemente = document.getElementsByTagName("p");
Hilfsvariablen dienen in den meisten Fällen dazu, den Code abzukürzen. In diesem Fall müssen Sie document.getElementsByTagName() nur einmal aufrufen. Ansonsten würde der Code in der Schleife wesentlich länger und unübersichtlicher. Die for-Schleife durchläuft nun alle Elemente des soeben erzeugten Arrays: for (var i = 0; i < elemente.length; i++) {
Eine Fallunterscheidung prüft die aktuelle Schriftgröße. Beträgt sie bereits 20 pt (Punkt), wird die Schrift auf 12 pt verkleinert. Ansonsten wird (else) auf 20 pt vergrößert. if(elemente[i].style.fontSize == "20pt") elemente[i].style.fontSize = "12pt"; else elemente[i].style.fontSize = "20pt";
312
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Das style-Objekt erlaubt einen direkten Zugriff auf die Stileigenschaften des jeweiligen Tags. Es ist Teil des W3C-DOM-Standards und für jedes HTML-Objekt vorhanden. Mehr dazu erfahren Sie im Kapitel 19 »CSS und JavaScript«. Bei der Schaltfläche wird die Funktion zum Wechsel der Schriftgröße (groesse()) aufgerufen. Für einen Überblick hier das vollständige Beispiel: getElementsByTagName() <script language="JavaScript">
Listing 10.3: getElementsByTagName()
im Einsatz (getElementsByTag Name.html)
} //-->
Erster Absatz
Zweiter Absatz
Größe ändern Abbildung 10.5: Die Schaltfläche wechselt zwischen kleiner …
KOMPENDIUM
JavaScript
313
Kapitel 10
Document Object Model
Abbildung 10.6: … und großer Schrift.
Das -Element hat den großen Vorteil, dass es gegenüber nicht in -Tags stehen muss. Dafür ist es in älteren Browsern, beispielsweise Netscape 4.x, nicht verfügbar. Zugriff über Knoten-Hierarchie Der Zugriff über die Knoten-Hierarchie benötigt vor allem einen Startpunkt. Normalerweise ist dies das document-Objekt als oberstes Objekt der DOM-Hierarchie. Von diesem Objekt aus hangeln Sie sich dann in die Tiefe. Die hierarchische Struktur entspricht Verwandtschaftsgraden unseres Stammbaumsystems8. Ein übergeordneter Knoten ist also ein Parent (ein Eltern-Knoten) und ein untergeordneter ein Child (Kind-Knoten). Knoten auf einer Hierarchieebene werden als Siblings (Geschwister-Knoten) bezeichnet. Jedes Knoten-Element besitzt Eigenschaften, die den Zugriff auf benachbarte Elemente erlauben. Die Eigenschaft firstChild greift beispielsweise auf den ersten Kind-Knoten zu, parentNode auf den Eltern-Knoten und nextSibling auf den nächsten Geschwister-Knoten. Abbildung 10.7 veranschaulicht verschiedene Eigenschaften. Die Eigenschaft childNodes enthält alle KindKnoten eines Knotens in einem Array.
8
314
Es wird auch hawaiianisches System genannt.
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
k.firstChild
k
Abbildung 10.7: Die Verwandtschaftsverhältnisse zwischen Knoten
k.lastChild k[1].parentNode
childNodes:
k[0]
k[0].nextSibling
k[1]
k[2]
k[2].previousSibling
Eine Übersicht der Eigenschaften und Methoden finden Sie im Abschnitt »Eigenschaften und Methoden des W3C-DOM«. Alle Elemente auslesen Der Zugriff auf die Knoten des Dokuments kann beispielsweise dazu genutzt werden, die Hierarchie des Dokuments darzustellen. Das folgende Beispiel verwendet dazu eine Schleife und einen rekursiven Funktionsaufruf: Die Funktion zur Ausgabe (ausgabe()) wird beim Laden der Seite aufgerufen.
Der Zugriff auf den DOM-Baum kann immer erst nach dem Laden erfolgen, da erst zu diesem Zeitpunkt die DOM-Hierarchie vom Browser im Arbeitsspeicher hinterlegt ist. Sie speichert den Rückgabewert aus der Funktion schleife() in einer Variablen und gibt sie aus. Als erster Parameter wird das documentObjekt übergeben. Dies ist der Start in den Hierarchiezugriff. Der zweite Parameter ist ein leerer String. Er wird später verwendet, um tiefer in der Hierarchie liegende Elemente einzurücken. function ausgabe() { var erg = schleife(document, ""); document.write(erg); }
Die Funktion schleife() besteht aus einer Schleife. Sie führt Folgendes aus: – Als Anfangswert übernimmt sie den ersten Kind-Knoten des Parameters elemente der Funktion. – Anschließend durchläuft sie alle Geschwister-Knoten dieses Parameters (siehe Schleifenänderung ele = ele.nextSibling), bis keiner mehr vorhanden ist (Bedingung: ele != null).
KOMPENDIUM
JavaScript
315
Kapitel 10
Document Object Model for (var ele = elemente.firstChild; ele != null; ele = ele.nextSibling)
In der Schleife folgen die Anweisungen: Der Sammelvariablen string werden nur die Knoten-Namen (ele.nodeName) der Knoten hinzugefügt, die HTML-Tags sind (ele.nodeType==1). if (ele.nodeType == 1) { string += z + ele.nodeName + "
"; }
Nach der Ausgabe folgt der rekursive Aufruf der Funktion. Als neues Knoten-Objekt wird ele übergeben. Dies ist der Kind-Knoten des Knotens beim letzten Funktionsaufruf – er wurde in der Schleifenanfangsbedingung definiert. Der zweite Parameter erhält als Einrückung zwei HTML-Leerzeichen ( ). schleife(ele, z + " "); }
Der rekursive Aufruf sorgt dafür, dass die Schleife in die tieferen Ebenen der Hierarchie gelangt. Die Hierarchie der Aufrufe sieht für das Beispiel wie folgt aus: Schleife // liefert HTML Funktionsaufruf Schleife // liefert HEAD Funktionsaufruf Schleife // liefert TITLE Funktionsaufruf Schleife // Abbruch, da ele == null Schleife // liefert SCRIPT Funktionsaufruf Schleife // Abbruch, da ele == null Schleife // Abbruch, da ele == null Schleife // liefert BODY . . .
Vergleichen Sie dies mit dem Ergebnis des Codes oder mit Abbildung 10.8. Nach dem letzten Schleifenabbruch wird die Sammelvariable string zurückgegeben. return string;
316
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Hier sehen Sie den kompletten Code: 9 Zugriff auf alle Knoten <script language="JavaScript">
Listing 10.4: Mit einer rekursiven Funktion lassen sich alle HTMLTags auslesen (knoten_zugriff. html).9
function schleife(elemente, z) { for (var ele = elemente.firstChild; ele != null; ele = ele.nextSibling) { if (ele.nodeType == 1) { string += z + ele.nodeName + "
"; } schleife(ele, z + " ");
} return string; } //--> Überschrift
Text mit Hervorhebung
Soll die DOM-Hierarchie beim Zugriff nicht verändert werden, müssen Sie von außerhalb zugreifen. Am einfachsten funktioniert dies über Frames. Zugriffsarten mischen In der Praxis treten oft beide Zugriffsarten gemischt auf. Der erste Zugriff auf ein Element erfolgt dabei meist mit getElementById, die weitere Arbeit übernehmen Methoden und Eigenschaften, um innerhalb der Knoten-Hierarchie zu arbeiten.
9
Dieses Beispiel funktioniert nur in Browsern, die mit dem W3C-DOM etwas anfangen können. Also nicht im Internet Explorer 4 und im Netscape Navigator 4.x. Der Konqueror hat Probleme mit der document.write()-Ausgabe. Geben Sie dort die Informationen beispielsweise in eine Textarea aus.
KOMPENDIUM
JavaScript
317
Kapitel 10
Document Object Model
Abbildung 10.8: Ein einfaches JavaScript zeigt die Hierarchie des Dokuments.
In Kapitel 10.1.3 »Eigenschaften und Methoden des W3C-DOM« finden Sie die Eigenschaften und Methoden näher erläutert. Das folgende Beispiel zeigt auf einfache Art die Mischung von direktem Zugriff und Zugriff über die Knoten-Hierarchie. Ziel ist, einen Knoten mit seinen Kind-Knoten zu duplizieren. Grundlage dieses Beispiels ist Listing 10.1. Zusätzlich wurde dem Textabsatz ein id-Attribut mit dem Wert absatz1 zugewiesen. Dieser Absatz soll nun im Skript im Kopf der Seite mit getElementById angesprochen und anschließend geklont werden: Der Zugriff auf den Absatz erfolgt, wie bereits erwähnt, über getElementById(). var ele = document.getElementById("absatz1");
Anschließend wird der Absatz mit cloneNode(Tiefe) geklont. Für die Tiefe können Sie true angeben, wenn alle darunter liegenden Knoten (Child Nodes oder Kind-Knoten) auch geklont werden sollen. var klon = ele.cloneNode(true);
Bisher sind die geklonten Knoten allerdings nur als Referenz, als eine Art Abbild, in der Variablen klon gespeichert. Um sie wieder einzufügen, benötigen Sie eine weitere Methode, beispielsweise appendChild(Knoten). Vorher muss in der Hierarchie allerdings einen Knoten nach oben gewandert werden, da die geklonten Knoten an das Ende des Dokuments angefügt werden sollen. ele = ele.parentNode; 318
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Dann erst kommt appendChild(Knoten) zum Einsatz. Der Parameter Knoten enthält in diesem Beispiel die Referenz auf die geklonten Knoten: ele.appendChild(klon);
Hier im Überblick der vollständige Code: DOM <script language="JavaScript">
Listing 10.5: Mischen von direktem Zugriff und Arbeit mit der Hierarchie (dom_zugriff.html)
} //--> Überschrift
Text mit Hervorhebung
Abbildung 10.9: Der Absatz der Beispieldatei wurde zusammen mit den darunter liegenden Knoten geklont.
Die Mischung der Zugriffsarten ist in der Praxis eine der häufigsten Erscheinungsformen. Als Faustregel gilt: entweder wird getElementById() alleine genutzt oder in Verbindung mit dem hierarchischen Zugriff. Dabei müssen Sie allerdings immer beachten, dass der Zugriff über das W3CDOM nur in neueren Browsern funktioniert. Eine umfangreiche Diskussion dazu finden Sie in Kapitel 10.2 »DOM in verschiedenen Browsern«.
KOMPENDIUM
JavaScript
319
Kapitel 10
Document Object Model
Eigenschaften und Methoden des W3C-DOM In diesem Abschnitt finden Sie die Eigenschaften und Methoden gesammelt, die das W3C-DOM für alle Knoten-Arten definiert. Damit die Wirkungsweise der Eigenschaften aus Tabelle 10.3 nachvollziehbar wird, sehen Sie in der Tabelle jeweils ein Beispiel. Das Seitengerüst, auf das sich dieses Beispiel bezieht, sehen Sie hier: Listing 10.6: Die Arbeitsgrundlage für die Beispiele in Tabelle 10.3 (dom_id.html)
childNodes <script language="JavaScript"> Überschrift
Text mit Hervorhebung
Das Grundgerüst besteht aus einer einfachen HTML-Seite und einer Funktion, die nach dem Laden des Dokuments aufgerufen wird. In der Funktion greift getElementById("absatz") direkt auf den Knoten des
-Tags zu. Tabelle 10.3: Die Eigenschaften für Knoten
320
Eigenschaft
Beispiel
Beschreibung
attributes
Eine Beispielausgabe finden Sie auf der CD-ROM unter code\kap10\attributes.html.
Array mit allen Attribut-Knoten eines Dokuments
childNodes
ele = ele.childNodes; for (var i=0 ; i<ele.length ; i++) { string += ele[i].nodeName + "
"; } document.write(string);
Array mit allen Kind-Knoten eines Knotens. In unserem Beispiel sind das zwei TextKnoten und der ElementKnoten für das -Tag.
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Eigenschaft
Beispiel
Beschreibung
firstChild
ele = ele.firstChild; document.write(ele.nodeValue);
Gibt den Verweis auf den ersten Kind-Knoten des aktuellen Knotens zurück.
lastChild
ele = ele.lastChild; document.write(ele.nodeName);
Liefert den Verweis auf den letzten Kind-Knoten des aktuellen Knotens.
nextSibling
ele = ele.nextSibling; document.write(ele);
Ergibt den nächsten Geschwister-Knoten. Ist kein Knoten vorhanden, wird null zurückgegeben.
KOMPENDIUM
JavaScript
Tabelle 10.3: Die Eigenschaften für Knoten (Forts.)
321
Kapitel 10 Tabelle 10.3: Die Eigenschaften für Knoten (Forts.)
322
Document Object Model
Eigenschaft
Beispiel
Beschreibung
nodeName
siehe Beispiel lastChild
Liefert den Namen eines Knotens. Bei HTML-Tags ist das der Tag-Bezeichner, bei TextKnoten #text (siehe Tabelle 10.1).
nodeType
document.write(ele.nodeType);
Liefert die Art des Knotens. Eine Übersicht finden Sie in Tabelle 10.1.
nodeValue
siehe Beispiel firstChild
Liefert den Wert eines Knotens. Bei einem Text-Knoten ist das beispielsweise der Text.
ownerDocument
ele = ele.ownerDocument;
Ergibt einen Verweis auf das document-Objekt der aktuellen DOM-Hierarchie.
parentNode
ele = ele.parentNode; document.write(ele.nodeName);
Liefert einen Verweis auf den übergeordneten Knoten des aktuellen Knotens; im Beispiel also das -Tag.
previousSibling
ele = ele.previousSibling; document.write(ele.nodeName);
Verweis auf den vorangehenden Geschwister-Knoten; im Beispiel also das -Tag.
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Die kompletten Beispiele zu den einzelnen Eigenschaften finden Sie unter dem Namen der Eigenschaft im Verzeichnis code\kap10. Die Eigenschaften für Knoten sind ebenso lange in Browsern integriert wie das W3C-DOM. Allerdings gibt es eine Schwierigkeit bei ownerDocument. Diese Eigenschaft besitzt der Internet Explorer 5 nur am Macintosh, nicht aber unter Windows!10 Unter Windows verwendet der Internet Explorer nur document. Und bei nodeType unterstützt der Internet Explorer 5 unter Windows nicht alle Typen. NS4.x NS6 a.
NS7
IE4 IE5
IE5.5 IE6
O7a
M1
K3
Tabelle 10.4: Die Eigenschaften für Knoten
Opera 6 kommt mit den Eigenschaften von Knoten noch nicht zurecht.
Die Methoden für das W3C-DOM finden Sie in Tabelle 10.5. Methode
Beschreibung
appendChild(Knoten)
Fügt hinter einen Knoten den als Referenz im Parameter übergebenen Knoten an (siehe Listing 10.5).
cloneNode(Tiefe)
Klont den aktuellen Knoten. Die Tiefe gibt an, ob die Kind-Knoten mit geklont werden (true) oder nicht (false) (siehe Listing 10.5).
createElement("Tag")
Erstellt ein neues HTML-Tag-Element.
createTextNode("Text")
Erstellt einen neuen Text-Knoten.
getAttributeNode(Attribut)
Liefert einen Attribut-Knoten.
hasChildNodes()
Stellt fest, ob ein Knoten Kind-Knoten besitzt (true) oder nicht (false).
hasAttributes()
Liefert true, wenn ein Knoten Attribut-Knoten besitzt, ansonsten false.
insertBefore(neuer Knoten, Knoten)
Setzt vor einen Knoten einen neuen Knoten.
removeAttributeNode(Attribut)
Entfernt einen Attribut-Knoten.
Tabelle 10.5: Methoden für Knoten
10 Die Ursache dafür ist, dass der IE für Macintosh von einem anderen Entwicklerteam bei Microsoft weiterentwickelt wird als die Windows-Version. Das W3C-DOM wurde am Macintosh früher übernommen.
KOMPENDIUM
JavaScript
323
Kapitel 10 Tabelle 10.5: Methoden für Knoten (Forts.)
Document Object Model
Methode
Beschreibung
removeChild(Knoten)
Löscht einen Knoten. Der Knoten muss ein KindKnoten
replaceChild(neuer Knoten, alter Knoten)
Ersetzt den neuen Knoten durch einen alten Knoten.
setAttribute(Attribut, Knoten)
Setzt ein Attribut für einen Knoten.
setAttributeNode (Attribut)
Setzt einen Attribut-Knoten.
swapNode(Knoten)
Vertauscht den aktuellen Knoten mit dem als Parameter angegebenen Knoten. Diese Methode ist auf den Internet Explorer ab Version 5 beschränkt, aber nicht im Internet Explorer 5 am Mac integriert.
supports(Funktion, Version)
Stellt fest, ob ein Knoten eine bestimmte Funktion unterstützt. Diese Methode wird nur im Netscape Navigator ab Version 6 und im Mozilla unterstützt.
Spezielle Knoten-Arten können eigene Eigenschaften und Methoden besitzen. Wie Sie ein neues Element zur HTML-Seite hinzufügen, erklärt der Abschnitt »Neue Elemente hinzufügen«. Erklärungsbedürftig ist bei den Methoden insbesondere removeChild(Knoten). Mit dieser Methode entfernen Sie einen Knoten. Allerdings muss der aufrufende Knoten vor der Methode der Eltern-Knoten des zu löschenden Knotens sein. Das folgende Beispiel löscht den Absatz. Das Knoten-Objekt vor der Methode removeChild() muss also das -Tag sein. Listing 10.7: Einen Knoten mit removeChild()
entfernen (removeChild.html)
removeChild <script language="JavaScript">
} //--> Überschrift
Text mit 324
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Hervorhebung
Abbildung 10.10: Der Knoten und alle untergeordneten Knoten werden entfernt.
Andere, sehr spezielle Eigenschaften und Methoden, werden hier nicht beschrieben. So bleiben beispielsweise drei Eigenschaften für XML-Namespaces, namespaceURI, localName und prefix außen vor, da sie sich zum einen auf Netscape ab Version 6 beschränken und zum anderen dort auch nicht konsequent umgesetzt sind.11 Auf der CD-ROM finden Sie jedoch ein Beispiel unter code\kap10\namespace.html. Neue Elemente hinzufügen Wollen Sie komplett neue Elemente zur DOM-Hierarchie hinzufügen, gilt es, einiges zu beachten. Erstellen Sie zuerst ein Element mit createElement("Tag"). Als Parameter wird der Tag-Name in Großschreibung als String übergeben. Bis zu diesem Zeitpunkt ist das Element allerdings noch nicht in der DOM-Hierarchie verankert. Dazu müssen Sie es beispielsweise erst mit appendChild(Knoten) anfügen. Ähnlich ist das Vorgehen, wenn Sie einen Text-Knoten einfügen möchten. Hier benötigen Sie zuerst createTextNode("Text")und dann ebenfalls appendChild(). Im folgenden Beispiel wird beides kombiniert eingesetzt, um einen Text aus einem Textfeld beim Anklicken einer Schaltfläche in einen Absatz zu verwandeln: Zuerst erstellt createElement() einen neuen Absatz: var absatz = document.createElement("P"); 11 Unter anderem liefern namespaceURI und prefix als Ergebnis immer noch null, auch wenn ein anderes Ergebnis erwartet würde.
KOMPENDIUM
JavaScript
325
Kapitel 10
Document Object Model Für den Absatz können Sie in Punktnotation ein Attribut definieren. Für das Beispiel bietet sich die zentrierte Ausrichtung mit align an: absatz.align = "center";
Eine Variable nimmt den Wert des Textfeldes auf: var formular = document.formular.ein.value;
Der Text-Knoten wird mit dem Text aus dem Textfeld erstellt: var text = document.createTextNode(formular); appendChild() fügt den Text-Knoten als Kind an den Absatz an: absatz.appendChild(text);
Beachten Sie, dass der Absatz bisher immer noch nicht sichtbar ist, da er nicht in der DOM-Hierarchie verankert ist. Abschließend wird der Absatz-Knoten als letzter Kind-Knoten in das -Tag eingefügt: document.body.appendChild(absatz);
Einige Knoten-Arten, beispielsweise das -Tag, haben eigene Objekte. Sie können daher direkt angesprochen werden. Der vollständige Code sieht folgendermaßen aus: Listing 10.8: Neue Elemente hinzufügen (elemente_hinzu. html)
Neue Elemente hinzufügen <script language="JavaScript">
} //-->
326
KOMPENDIUM
JavaScript
W3C-DOM
Kapitel 10
Abbildung 10.11: Durch Anklicken wird …
Abbildung 10.12: … ein neuer Absatz hinzugefügt.
W3C-DOM und DHTML Wann sollten Sie mit dem W3C-DOM arbeiten? Hier gibt es in JavaScript große Verwirrungen bei den Begrifflichkeiten. Zum einen ähneln die »alten« DOMs der Browser dem W3C-DOM in Teilbereichen (siehe folgendes Kapitel) und zum anderen ist das W3C-DOM in verschiedenen Browsern unterschiedlich umgesetzt. Bei DHTML – der Mischung von Stylesheets, HTML und JavaScript12 – ist der Zugriff auf Browserobjekte und damit ein DOM das absolut Entscheidende. Schließlich soll sich etwas bewegen und Interaktivität möglich sein. 12 Zu dieser Definition erfahren Sie mehr in Kapitel 20 »DHTML«.
KOMPENDIUM
JavaScript
327
Kapitel 10
Document Object Model Das W3C-DOM können Sie dazu durchaus auch verwenden, allerdings gilt es, die Unterschiede in den Browsern zu beachten und vor allem auf ältere Browser Rücksicht zu nehmen. Dies resultiert schließlich in einer notwendigen Browserunterscheidung. Die kann zu Beginn der kompletten Website getroffen werden, indem verschiedene Browsergruppen unterschiedliche Seiten sehen dürfen. Da dies aufwändig und häufig unpräzise sein kann, können Sie auch zuerst in der DHTML-Anwendung für verschiedene Browser eigenen Code programmieren. Eine Übersicht zu diesem Thema erhalten Sie in Kapitel 12 »Browserunterscheidung«. In der Praxis wird aus dem W3C-DOM meist getElementById() verwendet. Die übrigen Methoden und Eigenschaften kommen nur selten zum Einsatz. Dieses Verhältnis wird sich allerdings vermutlich verschieben, wenn auf die vierte Browsergeneration – Netscape Navigator 4.x und Internet Explorer 4 – keine Rücksicht mehr genommen werden muss.
10.2
DOM in verschiedenen Browsern
Objektmodelle funktionieren alle ähnlich und haben dasselbe Ziel: einfachen Zugriff auf Elemente in der Webseite. Was gut klingt, ist in der Praxis nicht ganz so schön. Tabelle 10.6 zeigt die Verwendung von verschiedenen DOMs in den aktuellen Browsern.13 Tabelle 10.6: Die DOMs in den aktuellen Browsern
Object Model
Browser
DOM Level 0
ab NS 2, IE 3 v1; alle aktuellen Browser
DOM Level 0 + Bilder
ab NS 3, IE 4; alle aktuellen Browser IE 3.01 am Mac
NS4 Erweiterungen (Layer)
NS 4.x
IE 4 Erweiterungen
ab IE 4 teilweise: ab Op 6
IE 5 Erweiterungen
ab IE 5 (Unterschiede Mac und Win) teilweise: ab Op 6
13 Diese Übersicht erhebt nicht den Anspruch, vollständig oder exakt zu sein. Da sich teilweise einzelne Funktionen in ihrer Wirkung unterscheiden, wäre das vermessen. Vielmehr dient die Tabelle dem schnellen Überblick, ersetzt aber nicht das Testen in allen Browsern.
328
KOMPENDIUM
JavaScript
DOM in verschiedenen Browsern
Object Model
Browser
W3C-DOM Level 1
IE 6, NS 6, Moz, Op 7a; K3
Kapitel 10 Tabelle 10.6: Die DOMs in den aktuellen Browsern (Forts.)
teilweise: IE 5, 5.5 (Unterschiede Mac und Win) W3C-DOM Level 2 a.
Teilweise: IE 6, NS 6, 7, Moz, Op 7, K3
nicht unterstützt: http://www.opera.com/docs/specs/opera07/#dom
DOM Level 0 Das DOM Level 0 war der Ausgangspunkt auch für das W3C-DOM. Dort geistert häufig noch ein – nie als Standard verabschiedetes – W3C-DOM Level 0 durch die Hallen, das dem DOM Level 0 aus Netscape 2 und 3 relativ genau entspricht. Das DOM Level 0 hat sich insbesondere um die Browserobjekte verdient gemacht. Die wichtigsten heute verwendeten wie window, document und location waren damals Teil des DOM Level 0. Allerdings gab es viele Eigenschaften und Methoden für Netscape 2 und 3 bzw. Internet Explorer 3 noch nicht. Sie sollten heute nicht mehr auf die Kompatibilität mit Netscape 2 und 3 bzw. Internet Explorer 3 achten. Wenn Sie sehr einfache Seiten haben, könnte dies eine Ausnahme sein. DHTML ist beispielsweise mit den alten Browsern nicht möglich, da die einzigen interaktiven Elemente in der Seite Formularfelder, Schaltflächen und Links waren und eine Änderung von CSS-Stilen noch nicht vorgesehen war.
DOM Level 0 mit Bild-Objekt In Netscape 3 wurde das DOM Level 0 ein wenig erweitert, und zwar um das Bild-Objekt für -Tags. Vielleicht ahnen Sie es? Damit lassen sich Rollover-Effekte realisieren, wenn der Nutzer mit der Maus über das Bild fährt und dieses ausgewechselt wird. Diese neue Funktion wurde von Webentwicklern sehr geliebt. Leider gab es sie nicht im Internet Explorer 3, da dieser kurz vor Netscape am Markt war. Microsoft konnte dieses Objekt erst im Internet Explorer 4 bzw. am Macintosh in Release 3.01 einbauen.
Netscape 4.x Netscape 4.x brachte dem DOM-Modell einige Neuerungen. Zum einen wurde ein verbessertes Event-Handling-Modell verwendet. Die Mausereignisse wurden zahlreicher und Tastatureingaben konnten erstmals als Ereig-
KOMPENDIUM
JavaScript
329
Kapitel 10
Document Object Model nisse abgefangen werden. Zum anderen gab es die Möglichkeit, Ereignisse nicht nur bei HTML-Elementen anzugeben, sondern auf Ereignisse auch bei Objekten wie document zu warten. Der Schlüssel dazu war die captureEvents()-Methode, die gewissermaßen ein Ohr auf die Schiene legt, ob der Nutzer etwas ausführt. Neben dem Ereignismodell führte Netscape die an sich gute Idee der Layer in die Browserwelt ein. Das -Tag erlaubte, verschiedene Bildebenen übereinander zu legen und mit JavaScript flexibel zu positionieren und einund auszublenden. Das große Problem mit den Layern bestand darin, dass sie es nicht zu einem W3C-Standard brachten. Microsoft setzte nicht auf das Layer-Konzept und in allen neueren Browsern werden die Positionierung und alle Aufgaben der Layer von CSS-Befehlen übernommen, die mit JavaScript gesteuert werden können. Layer gibt es nur in Netscape 4.x. In Netscape 6 und 7 sind sie wieder rausgeflogen. Stattdessen setzt auch Netscape nun auf die Positionierung und DHTML mit CSS. Wollen Sie Netscape 4.x-kompatible DHTML-Anwendungen programmieren, kommen Sie um Layer nicht herum. Mehr Informationen dazu finden Sie in Kapitel 20 »DHTML«.
Internet Explorer 4 Der Internet Explorer 4 machte einen großen Sprung nach vorne. Es war nun möglich, alle Elemente einer Webseite per Skript anzusprechen. Dazu diente allerdings leider kein Standard, sondern das »Sammelbecken«14 document.all. Es enthält alle Elemente einer Webseite. Soll Ihr DHTML also Internet Explorer 4-kompatibel sein, müssen Sie mit document.all arbeiten. Da dies allerdings auch dem Opera in den früheren Versionen vor 7 hilft, ist dies auch bei kleineren DHTML-Anwendungen durchaus sinnvoll. Mehr dazu in Kapitel 20 »DHTML«. Das Event-Handling-Modell des Internet Explorers 4 und auch der späteren Versionen unterscheidet sich allerdings von dem des Netscapes (siehe Netscape 4.x). Die Ereignisse sind alle Teil des window-Objekts. Sobald ein Nutzer beispielsweise auf eine Schaltfläche klickt, pflanzt sich das Ereignis bis hoch in das window-Objekt fort. Dies bezeichnet man als Event Bubbling. Netscape setzt dagegen auf das Hören auf Ereignisse ausgehend vom obersten Objekt.15 14 Der programmiertechnisch korrekte Begriff ist Kollektion oder Collection. 15 Dies wird auch als Top-down-Ansatz bezeichnet.
330
KOMPENDIUM
JavaScript
DOM in verschiedenen Browsern
Kapitel 10
Als dritte große Änderung (für Programmierer ) im Internet Explorer 4 wurde der CSS-Standard Version 1 zumindest größtenteils umgesetzt. Hier können Sie sich grob merken: Der Internet Explorer 4 setzt einen Großteil des Standards um, der Netscape Navigator 4.x etwas weniger. Einzelne Anwendungen zum Thema finden Sie ebenfalls in Kapitel 20 »DHTML«.
Internet Explorer 5 Der Internet Explorer 5 ist insbesondere in einer Hinsicht ein schwieriger Geselle. Auf dem Macintosh ist für ihn ein eigenes Entwicklerteam zuständig. Daher wurden dort beispielsweise die Fähigkeiten des W3C-DOM Level 1 etwas früher integriert. Aus Sicht des JavaScript- bzw. JScript-Interessierten brachte der Internet Explorer 5 und noch einmal in stärkerem Maße die Zwischenversion 5.5 viele neue Eigenschaften und Methoden für die bestehenden Objekte. Darunter sind zwar auch viele proprietäre – also dem Internet Explorer vorbehaltene – Eigenschaften, aber auch einige, die ihn näher an die Standards rücken. Darüber hinaus wurden ebenfalls zwei grundlegende Konzepte neu eingeführt: Verhalten oder auch DHTML Behavior. Dies sind kleine Code-Schnipsel, die extern gespeichert werden und einem beliebigen HTML-Element auf der Webseite Funktionen hinzufügen. HTML-Anwendungen (HTML Applications oder HTA). Sie dienen dazu, XML-Dateien mit der Dateiendung .hta in den Browser einzubinden.16 Diese speziell auf den Internet Explorer beschränkten Themen behandelt dieses Buch aus zwei Gründen nicht: –
Es ist nicht genug Platz vorhanden. Andere – standardkonforme oder Browser-übergreifende – Themen sind wichtiger.
–
Da die Erweiterungen Internet Explorer-spezifisch sind, könnten sie höchstens in einem Intranet zum Einsatz kommen. Allerdings können die Nutzer auch dort über eigene und andere Browser verfügen.
16 Weiterführende Informationen finden Sie unter http://msdn.microsoft.com/library/default. asp?url=/workshop/author/hta/overview/htaoverview.asp.
KOMPENDIUM
JavaScript
331
Kapitel 10
Document Object Model
W3C-DOM Level 1 Das DOM Level 1 ist in der sechsten Generation der großen Browser und auch bei den wichtigsten kleineren Konkurrenten – Mozilla, Konqueror 3 und Opera 7 – bereits weitgehend integriert. In Kapitel 20 »DHTML« arbeiten die Beispiele sehr fleißig damit.
W3C-DOM Level 2 Die Level 2-Unterstützung in den Browsern ist noch sehr unterschiedlich. Wo W3C-DOM Level 1 noch ohne Event-Handling auskam, ist es nun Teil des Standards geworden. Allerdings vertreten die Browser immer noch teilweise eigene Ansätze.
10.3
Browserobjekte
Die Browserobjekte sind der wichtigste Teil des DOM. Der Zugriff über Knoten und die Hierarchie ist zwar manchmal sinnvoll, in den meisten Fällen benötigen Sie aber die Eigenschaften und Methoden der Browserobjekte. Eines der wichtigsten Browserobjekte document haben wir bereits ausführlich verwendet. Dieses Objekt ist der DOM-Hierarchie übergeordnet. Eine einfache Ausgabe in JavaScript funktioniert beispielsweise mit diesem Objekt: document.write("Ausgabe");
Die folgenden Abschnitte geben Ihnen einen Überblick über die verschiedenen Browserobjekte. Im zweiten Teil dieses Buches, der mit »Webanwendungen« überschrieben ist, werden Sie diese Browserobjekte in allen erdenklichen Formen einsetzen. Die hier vorgestellten Browserobjekte gibt es auch in älteren Browsern. Die hier verwendeten Beispiele sind mit allen in diesem Buch getesteten Browser kompatibel.
window Das window-Objekt steht für das Browserfenster. Es ist für alle Elemente im Fenster das hierarchisch übergeordnete Objekt, also auch für das Dokument und damit das document-Objekt.
332
KOMPENDIUM
JavaScript
Browserobjekte
Kapitel 10
Um das document-Objekt anzusprechen, müssten Sie also theoretisch window.document
schreiben. Dies ist allerdings in der Praxis nicht notwendig. Sie müssen window nur dann davor schreiben, wenn Sie direkt eine Eigenschaft oder Methode aus dem window-Objekt verwenden. Die folgenden Anwendungsmöglichkeiten können nur einen kurzen Ausblick auf die folgenden Kapitel geben. Sie können mit dem window-Objekt Text in der Statusleiste ausgeben, eine Ausgabe in einem Warnfenster ausgeben; dies haben Sie bereits gesehen: window.alert("Ausgabe"); Abbildung 10.13: Eine Ausgabe mit window.alert
Statt window.alert können Sie window auch weglassen, also nur alert schreiben. ein neues Browserfenster öffnen oder schließen. Neues Fenster öffnen <script language="JavaScript">
KOMPENDIUM
JavaScript
365
Kapitel 12
Browserunterscheidung
Abbildung 12.2: Der Internet Explorer 6 gibt an, wie er heißt und liefert gleich mit, dass das .NET Framework installiert ist.
Der Internet Explorer gibt auch eine Rückmeldung darüber, ob das .NET Framework installiert ist (.NET). Zusätzlich gibt er die Versionsnummer der Common Language Runtime (CLR) aus. Tabelle 12.2 enthält eine Sammlung der Ausgaben von den wichtigsten Browsern. Diese Sammlung ließe sich mit älteren Browserversionen und verschiedensten Betriebssystemen beliebig erweitern. Das Ziel ist allerdings zuerst einmal nicht, dass Sie die Tabelle auswendig können, sondern aus den Ergebnissen die Erkenntnisse für die Browserunterscheidung ziehen. Tabelle 12.2: Die Ausgaben der wichtigsten Browser
Browser
Wert
IE 4
appName
Microsoft Internet Explorer
appVersion 4.0 (compatible; MSIE 4.01; Windows NT)
IE 5
userAgent
Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)
appName
Microsoft Internet Explorer
appVersion 4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET
CLR 1.0.3705)
IE 5.5
userAgent
Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 1.0.3705)
appName
Microsoft Internet Explorer
appVersion 4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR
1.0.3705)
IE 6
userAgent
Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705)
appName
Microsoft Internet Explorer
appVersion 4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR
1.0.3705) userAgent
366
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
Browser
Wert
NN 4.x
appName
Netscape
appVersion 4.78 [de] (Windows NT 5.0; U)
NN 6.2
userAgent
Mozilla/4.78 [de] (Windows NT 5.0; U)
appName
Netscape
Tabelle 12.2: Die Ausgaben der wichtigsten Browser (Forts.)
appVersion 5.0 (Windows; de-DE)
NN 7
userAgent
Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3
appName
Netscape
appVersion 5.0 (Windows; de-DE)
Mo
userAgent
Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.0.2) Gecko/20021120 Netscape/7.01
appName
Netscape
appVersion 5.0 (Windows; en-US)
Ko 3
userAgent
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2.1) Gecko/20021130
appName
Konqueror
appVersion 5.0 (compatible; Konqueror/3; Linux) userAgent
Browser
Wert
Op 7
appName
Mozilla/5.0 (compatible; Konqueror/3; Linux)
Microsoft Internet Explorer
Tabelle 12.3: als Internet Explorer 6
appVersion 4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 2000) userAgent
Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.01 [en] Tabelle 12.4: als Opera
Browser
Wert
Op 7
appName
Opera
appVersion 7.0 (Windows 2000; U) userAgent
Opera/7.0 (Windows 2000; U) [en]
Opera Der Opera hat vor längerer Zeit eine Funktion eingeführt, die für den Nutzer praktisch, für den Entwickler dagegen problematisch ist. Opera kann sich als beliebiger anderer Browser identifizieren. Opera 7 identifiziert sich beispielsweise standardmäßig als Internet Explorer 6 (siehe Tabelle 12.2). Das Ziel dahinter ist offensichtlich: Viele Browserunterscheidungen trennen nur Netscape Navigator und Internet Explorer, Opera wurde – und wird –
KOMPENDIUM
JavaScript
367
Kapitel 12
Browserunterscheidung ignoriert. Damit Opera-Surfer aber nicht auf eine Seite ohne JavaScript geschickt werden, gibt sich Opera lieber als anderer Browser aus. Dies wirft zwei Probleme auf: Zum einen sind Browserstatistiken im Web für Opera meist nicht glaubwürdig, da nur wenige Opera sich auch als Opera identifizieren. Noch gravierender ist allerdings, dass es in einer Browserunterscheidung kaum möglich ist, den Opera von anderen Browsern zu unterscheiden. Die Identifizierung ändern Sie in Opera in den VOREINSTELLUNGEN unter NETZWERK.
Abbildung 12.3: Das Identifikationsverhalten von Opera ändern
Die einzige Unterscheidungsmöglichkeit liegt in der Zeichenkette Opera, die unter userAgent vorhanden ist. Konqueror Der Konqueror identifiziert sich zwar normal als Konqueror, Sie können allerdings unter EINSTELLUNGEN/KONQUEROR EINRICHTEN zusätzliche Angaben machen, wie er sich genau ausgeben soll.
368
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12 Abbildung 12.4: Die Einstellungen für den Konqueror
USER-AGENT-KENNUNG SENDEN zu deaktivieren, hat für JavaScript keine Auswirkung, sondern bezeichnet die Versendung der User-Agent-Identifizierung an den Webserver per HTTP. Unterscheiden Browser exakt voneinander zu unterscheiden ist sehr schwierig bis unmöglich. Zu viele Plattformen, Browserversionen und Besonderheiten sind zu beachten. Die einfachste Unterscheidung wäre nur mit dem Namen der Browser: Browser <script language="JavaScript">
Listing 12.2: Unterscheidung mit appName
(name.html)
if (name == "Netscape") { ausgabe = "Netscape"; } else if (name == "Microsoft Internet Explorer") { ausgabe= "Internet Explorer"; } else { ausgabe= "Der Rest"; }
KOMPENDIUM
JavaScript
369
Kapitel 12
Browserunterscheidung document.write(ausgabe) //-->
Dieses Listing erkennt Netscape Navigator und Mozilla beide als Netscape. Der Internet Explorer wird sehr sicher erkannt. Opera landet je nach Identifikation beim Internet Explorer oder Netscape. Übrig bleibt der Opera, der sich als Opera identifiziert und beispielsweise der Konqueror. Ein weiteres Problem dieser ersten Unterscheidung: Die Versionsnummer des Browsers wird nicht festgelegt. Mit der Versionsnummer wird es gleich ein gutes Stück schwieriger. Sie lässt sich beispielsweise aus der Eigenschaft userAgent ziehen. Da dort allerdings auch Informationen zum Betriebssystem stehen und das Ganze bei den meisten Browsern mit Mozilla beginnt6, fällt das Filtern schwer. Einfacher erscheint da der Zugriff über appVersion, allerdings gibt beispielsweise Netscape ab Version 6 hier immer 5 als Versionsnummer an. Und auch die Versionsnummern von Konqueror und Opera sind versteckter. Das folgende Skript ist ein Versuch, dies alles zu berücksichtigen7: Listing 12.3: Eine umfangreiche Browserunterscheidung mit Versionsnummer (unterscheidung.html)
Browser <script language="JavaScript">
name = navigator.appName; vers = navigator.appVersion; ua = navigator.userAgent; ausgabe = "";
function browser() { if (ua.indexOf("Opera") != -1) { ausgabe = "OP"; } else if (name == "Konqueror") { ausgabe = "KO"; } else if ((name == "Netscape") && (ua.indexOf("Netscape") == 1) && (parseFloat(vers) >= 5)) { ausgabe = "MO"; } else if (name == "Netscape") { ausgabe = "NN"; } else if (name == "Microsoft Internet Explorer") { ausgabe = "IE"; 6 7
370
Der historische Ursprung liegt im Ur-Browser Mosaic, auf dem die heutigen Browser basieren. Erklärung folgt am Ende des Skripts
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
} else { ausgabe= "NB"; } var erg = eval("ver" + ausgabe + "()"); return ausgabe + " " + erg; } function verOP() { if (name == "Opera") { return parseFloat(vers); } else if (name == "Netscape") { if (parseFloat(vers) < 5) { return "Opera als NN " + parseFloat(vers); } else { return "Opera als NN 6+"; } } else { return "Opera als IE " + verIE(); } } function verKO() { var pos = ua.indexOf("Konqueror/"); var string = ua.substring(pos + 10, pos + 14); return parseFloat(string); } function verMO() { var pos = ua.indexOf("rv:"); var string = ua.substring(pos + 3, pos + 7); return parseFloat(string); } function verNN() { if (parseFloat(vers) < 5) { return parseFloat(vers) } else if (ua.indexOf("Netscape/") != -1) { var pos = ua.indexOf("Netscape/"); var string = ua.substring(pos + 9, pos + 13); return parseFloat(string); } else { var pos = ua.indexOf("Netscape"); var string = ua.substring(pos + 8, pos + 12); return parseFloat(string); } } function verIE() { var pos = ua.indexOf("MSIE"); var string = ua.substring(pos + 5, pos + 9); return parseFloat(string); } function verNB() { return parseFloat(vers); }
KOMPENDIUM
JavaScript
371
Kapitel 12
Browserunterscheidung document.write(browser()) //-->
Das Skript besteht aus zwei Teilen: Der Funktion browser(), die den Browsernamen identifiziert Vielen Funktionen, die für die einzelnen Browser die Versionsnummer extrahieren und ihr Ergebnis an browser() zurückliefern Am einfachsten lässt sich der Ablauf der Browserunterscheidung so darstellen: 1.
Zuerst wird in einer Fallunterscheidung in der Funktion browser() geprüft, um welchen Browser es sich handelt. Als Beispiel folgt eine Zeile für den Internet Explorer: else if (name == "Microsoft Internet Explorer") {
2.
Die Variable ausgabe nimmt das Ergebnis, in diesem Fall das Kürzel des Browsers, auf. ausgabe = "IE"; }
3.
Aus der Variablen, also dem Browserkürzel, und dem String ver wird per eval()-Anweisung ein Funktionsaufruf gemacht, der genau die Funktion für den erkannten Browser aufruft. Den Rückgabewert der Funktion zum Versionscheck speichert die Variable erg. var erg = eval("ver" + ausgabe + "()");
4.
Die Funktionen zum Versionscheck unterscheiden sich von Browser zu Browser deutlich. Beim Internet Explorer muss die Versionsnummer aus der Eigenschaft userAgent gezogen werden, da appVersion ab der fünften Generation immer noch 4 ist. In userAgent folgt die Versionsnummer dagegen immer nach der Zeichenkette "MSIE", auf deren Position Sie mit der String-Methode indexOf("String") zugreifen können. Die Methode substring(Start, Ende) schneidet dann die Versionsnummer heraus und parseFloat("String") wandelt sie in eine Zahl um: function verIE() { var pos = ua.indexOf("MSIE"); var string = ua.substring(pos + 5, pos + 9); return parseFloat(string); }
372
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
Sie sollten statt substring() nicht slice() verwenden, da diese Methode in älteren Browsern wie Netscape 2 und 3 und Internet Explorer 3 nicht vorhanden ist. Eine Übersicht über die String-Methoden finden Sie in Kapitel 7 »Arrays und Strings«. 5.
Die Funktion zum Versionscheck liefert dann an die Variable erg in der Funktion browser() die Versionsnummer zurück. Dort werden dann Browserkürzel und Funktionsnummer gemeinsam zurückgeliefert. return ausgabe + " " + erg;
Bei einigen Fallunterscheidungen und Versionsüberprüfungen lohnt sich eine genauere Betrachtung. Hierzu finden Sie in den nächsten Abschnitten Details. Opera Der Opera ist bekanntlich flexibel und kann sich als beliebiger Browser identifizieren. Daher hilft appName auch nicht weiter. Allerdings gibt es, unabhängig davon, als welcher Browser sich Opera identifiziert, immer die Zeichenkette »Opera« in userAgent. Daher erfolgt die Identifikation auch über diese Zeichenkette. Die Methode indexOf("String")gibt an, ob die Zeichenkette in userAgent vorhanden8 ist. if (ua.indexOf("Opera") != -1) { ausgabe = "OP"; }
Beachten Sie, dass Opera vor den anderen Browsern geprüft werden muss. Wenn sich Opera als Netscape oder Internet Explorer identifiziert, wird die Fallunterscheidung bereits beendet, bevor sie zu Opera gelangt. Mozilla Mozilla ist ein schwer zu fassender Geselle. Er heißt Netscape (appName); dies ist aber nicht ausreichend. Er darf auch im userAgent nicht die Zeichenkette »Netscape« haben. Dies können Sie mit indexOf() prüfen. Solche Zeichenkette besitzen allerdings Netscapes vor Version 6, also 2, 3, 4.x, auch nicht. Um diese Browser auszuschließen, muss die Versionsnummer (appVersion) größer als 5 sein. else if ((name == "Netscape") && (ua.indexOf("Netscape") == -1) && (parseFloat(vers) >= 5)) { ausgabe = "MO"; }
8
Noch exakter prüft sie, ob sie nicht vorhanden ist. Das heißt, ob indexOf() nicht -1 ergibt. -1 würde bedeuten, dass die Zeichenkette nicht vorhanden ist.
KOMPENDIUM
JavaScript
373
Kapitel 12
Browserunterscheidung Sie können sich in der Praxis durchaus auch dafür entscheiden, nicht auf Mozilla zu prüfen, sondern ihn in eine Schublade mit Netscape zu stecken. Sie müssen dann lediglich die Versionsnummernüberprüfung anpassen. Version von Opera Die Version von Opera benötigt eine Fallunterscheidung, ob Opera sich als Opera, Netscape oder Internet Explorer ausgibt. Identifiziert er sich als Opera, ist es ausreichend, die Versionsnummer aus appVersion auszulesen. Als Netscape gibt er dagegen bei einer höheren Version in appVersion an, er sei Netscape 5. Dagegen hilft eine Fallunterscheidung für Netscape mit einer Version niedriger oder größer gleich 5. Für den Internet Explorer wird die Versionsnummer aus der Funktion zur Versionserkennung des Internet Explorers (verIE()) gewonnen. function verOP() { if (name == "Opera") { return parseFloat(vers); } else if (name == "Netscape") { if (parseFloat(vers) < 5) { return "Opera als NN " + parseFloat(vers); } else { return "Opera als NN 6+"; } } else { return "Opera als IE " + verIE(); } }
Version von Mozilla Die Version des Mozilla steht hinter der Zeichenkette »rv:«. Der Zugriff darauf erfolgt wie auf die Versionsnummer des Internet Explorer (siehe Seite 282). function verMO() { var pos = ua.indexOf("rv:"); var string = ua.substring(pos + 3, pos + 7); return parseFloat(string); }
Version von Netscape Der Netscape Navigator erfordert eine dreiteilige Fallunterscheidung: Zuerst werden die Versionen kleiner als 5, also 2, 3, 4.x, herausgefiltert und deren Versionsnummer aus appVersion direkt mit parseFloat() ausgelesen. 374
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
function verNN() { if (parseFloat(vers) < 5) { return parseFloat(vers) }
Anschließend muss zwischen verschiedenen Schreibweisen unterschieden werden. Netscape 7 schreibt die Versionsnummer in userAgent immer nach dem String »Netscape/«, Netscape 6 dagegen nach »Netscape« ohne Schrägstrich. else if (ua.indexOf("Netscape/") != -1) { var pos = ua.indexOf("Netscape/"); var string = ua.substring(pos + 9, pos + 13); return parseFloat(string); } else { var pos = ua.indexOf("Netscape"); var string = ua.substring(pos + 8, pos + 12); return parseFloat(string); } }
Verbesserungen Nichts ist perfekt, leider auch nicht diese Fallunterscheidung. Entsprechend könnten Sie noch beliebige Verbesserungen vornehmen. Eine wäre, die Angaben der drei Eigenschaften des navigator-Objekts in Kleinbuchstaben oder Großbuchstaben zu verwandeln, und nur diese zu vergleichen. Dadurch umgehen Sie Verwechslungen bei der Groß- und Kleinschreibung, die eventuell in manchen Versionen auftauchen könnten. Diese Variante finden Sie unter dem Namen unterscheidung_gk.html im Ordner code\kap12 auf der CD-ROM. Eine weitere Verbesserungsmöglichkeit wäre, noch mehr Fehlerüberprüfungen einzubauen. Beispielsweise ließe sich jede parseFloat()-Anweisung für die Versionsnummer mit einer Fallunterscheidung versehen, die mit isNaN() überprüft, ob auch tatsächlich eine Zahl zurückgeliefert wird. Weiterleitung Eine Browserunterscheidung ist insbesondere dann sinnvoll, wenn Sie für verschiedene Browser auch unterschiedliche Seiten vorbereitet haben. Interessant ist dies in der Praxis vor allem, um ältere Browser auf eine eigene »Low-Level«-Seite umzuleiten. Als Basis für diese Beispielanwendung dient das Browserunterscheidungsskript aus dem letzten Abschnitt (siehe Listing 12.3). Verändert wird Folgendes:
KOMPENDIUM
JavaScript
375
Kapitel 12
Browserunterscheidung Bei der Überprüfung des Browsers kommt eine Fallunterscheidung hinzu. Sie bezieht die Versionsnummer aus den Funktionen zum Versionsnummerncheck, die Ihnen ja aus dem bereits gesehenen Beispiel bekannt sind. Sie können hier für jeden Browser flexibel die Versionsnummer wählen, ab der er auf die Seite für neue Browser umgeleitet wird. Ist die Versionsnummer groß genug, bei Netscape beispielsweise größer gleich 4, erhält die Variable ausgabe den Wert true. Die Wahl der Versionsnummern müssen Sie nicht aus dem Beispiel übernehmen, sondern Sie können beliebige eigene Einschränkungen machen. Im Allgemeinen gilt: je weniger Einschränkungen, desto besser. Die Browser, die Sie auf die anspruchsvollere Seite weiterleiten, müssen das JavaScript dort allerdings wirklich packen (testen!). Nach den Überprüfungen des Browsers prüft eine eigene Fallunterscheidung den Wert von ausgabe. Ist er true, handelt es sich um einen neuen Browser und das Skript leitet auf die Seite für neue Browser weiter. Ist er false, handelt es sich um einen alten Browser, und es wird auf alte_browser.html weitergeleitet. Nachfolgend sehen Sie diesen Teil des Skripts: var var var var
name = navigator.appName; vers = navigator.appVersion; ua = navigator.userAgent; ausgabe = false;
function browser() { if (ua.indexOf("Opera") != -1) { if (verOP() >= 6) { ausgabe = true; }
} else if (name == "Konqueror") { if (verKO() >= 3) { ausgabe = true; }
} else if ((name == "Netscape") && (ua.indexOf("Netscape") == -1) && (parseFloat(vers) >= 5)) { ausgabe = true;
} else if (name == "Netscape") { if (verNN() >= 4) { ausgabe = true; }
} else if (name == "Microsoft Internet Explorer") { if (verIE() >= 4) { ausgabe = true;
}
376
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
} else { ausgabe= false;
} if (ausgabe) { window.location.href = "neue_browser.html"; } else { window.location.href = "alte_browser.html"; }
}
In den Funktionen zur Versionsüberprüfung ändert sich nur bei Opera etwas. Opera könnte sich ja theoretisch als Netscape 3 (Mozilla 3.0) ausgeben. Dann würde er vom Skript zu den alten Browsern gesteckt, was bei Opera 6 oder 7 keinen Sinn macht. Daher liest die Funktion zur Versionsüberprüfung (verOP()) die Versionsnummer aus userAgent, wo sie nach der Zeichenkette "Opera" und einem Leerzeichen folgt. function verOP() { var pos = ua.indexOf("Opera"); var string = ua.substring(pos + 6, pos + 9); return parseFloat(string); }
Natürlich ist die Frage, was Opera-Nutzer erreichen möchten, die sich als Mozilla 3 oder 4.78 ausgeben. Es werden die wenigsten sein – so viel sei verraten. Ihre wahren JavaScript-Fähigkeiten zu erkennen, macht Sinn, denn wenn sie JavaScript nicht wollten, könnten sie es auch deaktivieren. Abbildung 12.5: Opera 7 wird als neuer Browser erkannt, obwohl er sich als Mozilla 3.0 ausgibt.
Den vollständigen Code finden Sie auf der CD-ROM im Ordner code\kap12 mit dem Namen umleitung.html. Verbesserungen Verbesserungen sind natürlich immer möglich. Hier gilt wieder, dass zusätzliche Fehlerüberprüfungen eingebaut werden könnten. Des Weiteren sollten Sie Ihre Browserumleitung auf jedem nur verfügbaren Browser und Betriebssystem testen.
KOMPENDIUM
JavaScript
377
Kapitel 12
Browserunterscheidung
Abbildung 12.6: Netscape 2 dagegen landet bei den alten Browsern.
Wenn neue Browser am Markt erscheinen, sollten Sie auf jeden Fall überprüfen, ob der Test noch funktioniert. Bei Versionsüberprüfungen sollten Sie als Angabe natürlich immer größer als statt gleich verwenden, da anderenfalls spätestens in der nächsten Version, vielleicht aber nur beim MiniUpdate von 7 auf 7.01, die Umleitung nicht mehr funktioniert. Eine weitere sinnvolle Verbesserung in diesem Skript ist natürlich ein <noscript>-Container, der nicht JavaScript-fähige Browser oder Browser mit
deaktiviertem JavaScript abfängt.9 Auf der Seite alte_browser.html sollte ein Link der Art »Ihr Browser kann mehr, hier geht’s zur Super-Seite« integriert sein, falls die Versionsüberprüfung wirklich mal Mist baut oder Sie einen neuen Browser nicht schnell genug integriert haben.
Browser Sniffer Das Thema Browsererkennung wird in der Webentwickler-Community heiß diskutiert. Vertreter neuerer Ansichten gehen häufig davon aus, dass Browserunterscheidung an sich nicht sinnvoll ist und man besser Browser-übergreifend programmieren sollte10; andere sind Sniffer-Fans. Einer der bekanntesten Sniffer ist der Ultimate JavaScript Client Sniffer von Erik Krock, einem Netscape-Mitarbeiter und Mozilla-Entwickler (http:// www.mozilla.org/docs/web-developer/sniffer/browser_type.html). Er ist nicht mehr aktuell, unterstützt beispielsweise Win XP oder neuere Opera-Versionen noch nicht, bildet aber den Vater vieler anderer Sniffer, die durchs Netz geistern. Prinzipiell spricht nichts gegen den Einsatz dieser Sniffer, Sie sollten sie jedoch insbesondere mit aktuellen Browsern testen. Wenn dann neue 9 Eigentlich ist das ja ohnehin obligatorisch, oder? 10 beispielsweise: http://devedge.netscape.com/viewsource/2002/browser-detection/
378
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
Browser hinzukommen, benötigen Sie häufig auch eine neue Sniffer-Version. Stehen die Änderungen dann nicht sofort im Netz zur Verfügung, ist dies ärgerlich, weil viele Nutzer am Anfang neue Browser ausprobieren. Abgesehen davon ist es nicht ganz einfach, Sniffer an die eigenen Bedürfnisse anzupassen. Sie liefern häufig zu viele Informationen. Als Fazit bleibt: Wer gerne auf die Rundumversorgung setzt, erreicht sein Ziel mit einem Sniffer schneller, wer dagegen flexibler sein und mit weniger Code auskommen möchte, sollte die Lösung selbst programmieren.
Sprache feststellen Die Sprache lässt sich relativ einfach feststellen. Sie besteht aus einem Kürzel aus zwei Buchstaben: de steht für Deutsch, en für Englisch, it beispielsweise für Italienisch. Allerdings gibt es hier wieder einen kleinen, aber ärgerlichen Unterschied bei den Browsern. Die Eigenschaft für das navigator-Objekt, um die Sprache (des Browsers) auszulesen, heißt im Internet Explorer browserLanguage, bei Netscape dagegen nur language. Lediglich Opera 7 versteht beides. NS4.x NS6
NS7
browserLanguage language
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 12.5: Eigenschaften zur Spracherkennung
Um dieses Problem zu umgehen, hilft bei der Wahl der Sprache eine Fallunterscheidung: Sprache <script language="JavaScript">
Listing 12.4: Die Sprache feststellen (sprache.html)
if (navigator.browserLanguage) { sprache = navigator.browserLanguage; } else if (navigator.language) { sprache = navigator.language; } else { sprache = "Nicht feststellbar"; }
document.write(sprache); //-->
KOMPENDIUM
JavaScript
379
Kapitel 12
Browserunterscheidung
Die Fallunterscheidung nutzt den Umstand, dass die Bedingung true ergibt, wenn eine Eigenschaft vorhanden ist, false dagegen, wenn der Browser die Eigenschaft nicht unterstützt. Der Netscape Navigator unterstützt navigator.browserLanguage beispielsweise nicht, liefert also false. navigator.language aus der else-if-Bedingung kennt er dagegen und gibt true zurück. Weiterleitung Eine einfache Weiterleitung ist schnell implementiert. Sie liest die Sprache aus und prüft mit indexOf(), ob de oder en vorkommt. Je nachdem wird der Nutzer dann entweder auf die deutsche oder englische Seite weitergeleitet. Hat der Browser eine andere Sprache, bleibt der Nutzer auf der Weiterleitungsseite und sieht die im HTML-Code angelegten Links auf die zwei vorhandenen Sprachversionen. Er kann sich dann selbst entscheiden. Listing 12.5: Je nach Sprache weiterleiten (sprache_umleitung .html)
Sprache <script language="JavaScript">
//-->
English (Englisch)
Deutsch (German)
Die Funktion indexOf() ist einem Vergleich mit == vorzuziehen, da bei einigen Länderkürzeln und Browsern noch Nachsätze folgen. So steht de-at zum Beispiel im Internet Explorer für Österreich, der Navigator gibt Deutschland als de-DE an. Im englischen Sprachraum wird zwischen en-GB und en-US (Netscape) bzw. en-gb und en-us zwischen Großbritannien (gb) und den USA (us) unterschieden.
380
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12 Abbildung 12.7: Die Weiterleitung hat funktioniert und der Nutzer ist auf der deutschen Seite gelandet.
Auch, wenn Sie die Sprache automatisch wählen, sollten Sie dem Nutzer immer die Möglichkeit geben, die Sprache auch zu wechseln. Vielleicht hat er beispielsweise nur einen englischen Browser, weil er die neueste Version ausprobieren möchte, ist aber deutschsprachig. In großen Webprojekten wird eine Sprachunterscheidung auch häufig serverseitig realisiert (siehe Kapitel 12.5 »Serverseitige Browserunterscheidung«), da je nach Sprachversion unterschiedliche Daten aus der Datenbank geholt werden. Dies funktioniert auch bei deaktiviertem JavaScript. Für eine kleinere Webseite ist allerdings auch die Umleitung auf verschiedene Seiten mit Sprachen sinnvoll. Internet Explorer spezial Die Grundlage der Sprachunterscheidung ist nicht das Betriebssystem, sondern die Sprachversion des Browsers. Dies kann unter Umständen unpräzise sein, wenn der Nutzer nur einen englischen Browser hat, aber Deutsch spricht. Microsoft hat dafür zwei Eigenschaften namens systemLanguage und userLanguage eingeführt, die auf die Sprachversion des Betriebssystems bzw. der Benutzereinstellungen zurückgreifen. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
systemLanguage
userLanguage
O7
M1
K3
Tabelle 12.6: Internet ExplorerEigenschaften
Die zwei Eigenschaften werden genauso wie browserLanguage eingesetzt: if (navigator.systemLanguage) { document.write(navigator.systemLanguage); document.write("
"); document.write(navigator.userLanguage); }
KOMPENDIUM
JavaScript
Listing 12.6: Die Eigenschaften des Internet Explorers für die Systemsprache (Ausschnitt aus: sprache_ie.html)
381
Kapitel 12
Browserunterscheidung Die Systemsprache kann in manchen Betriebssystemen geändert werden. In Windows XP finden Sie dies im Menü SYSTEMSTEUERUNG/REGIONS- UND SPRACHOPTIONEN. Auf der Registerkarte REGIONALE EINSTELLUNGEN ändern Sie die Einstellungen per Auswahlliste. Diese Wahl beeinflusst die Eigenschaft userLanguage (nicht systemLanguage11).
Abbildung 12.8: userLanguage gibt
gl für Galizisch an – da kann doch etwas nicht stimmen?
Ältere Browser Für ältere Browser, die die Eigenschaften language oder browserLanguage nicht verstehen, vor allem Netscape 2 und 3 und Internet Explorer 4, können Sie die Angabe auch aus den Eigenschaften appVersion oder userAgent des navigator-Objekts ziehen. Dazu benötigen Sie Folgendes: Eine Variable mit dem Wert der Eigenschaft userAgent var ua = navigator.userAgent;
Eine Fallunterscheidung zwischen den Sprachen, die Sie unterstützen: if (navigator.userAgent.indexOf("de") != -1) { sprache = "de"; } else if (navigator.userAgent.indexOf("en") != -1) { sprache = "en"; }
Diesen Code können Sie nun in Listing 12.5 einfügen. Die Fallunterscheidung kommt in die else-Anweisung der dortigen Fallunterscheidung: Listing 12.7: Weiterleitung nach Sprache für ältere Browser (sprache_alt.html)
Sprache <script language="JavaScript">
382
KOMPENDIUM
JavaScript
navigator-Objekt
Kapitel 12
if (navigator.browserLanguage) { sprache = navigator.browserLanguage; } else if (navigator.language) { sprache = navigator.language; } else { //Ältere Browser: if (navigator.userAgent.indexOf("de") != -1) { sprache = "de"; } else if (navigator.userAgent.indexOf("en") != -1) { sprache = "en"; } }
if (sprache.indexOf("de") != -1) { window.location.href = "index_de.html"; } else if (sprache.indexOf("en") != -1) { window.location.href = "index_en.html"; } //-->
English (Englisch)
Deutsch (German)
Abbildung 12.9: Auch in Netscape 2 funktioniert die Weiterleitung.
Sprachversionen Die folgende Tabelle fasst die wichtigsten Sprachkürzel zusammen. Kürzel
Sprache
Kürzel
Sprache
ar
Arabisch
fi
Finnisch
bg
Bulgarisch
fr
Französisch
KOMPENDIUM
JavaScript
Tabelle 12.7: Einige wichtige Sprachkürzel
383
Kapitel 12 Tabelle 12.7: Einige wichtige Sprachkürzel (Forts.)
Browserunterscheidung
Kürzel
Sprache
Kürzel
Sprache
cs
Tschechisch
hu
Ungarisch
da
Dänisch
it
Italienisch
de
Deutsch
ja
Japanisch
de-at
Deutsch (Österreich)
ko
Koreanisch
de-ch
Deutsch (Schweiz)
nl
Niederländisch
de-li
Deutsch (Liechtenstein)
no
Norwegisch
de-lu
Deutsch (Luxemburg)
pl
Polnisch
el
Griechisch
pt
Portugiesisch
en
Englisch
ru
Russisch
en-au
Englisch (Australien)
sk
Slowakisch
en-ca
Englisch (Kanada)
sr
Serbisch
en-gb
Englisch (Großbritannien)
sv
Schwedisch
en-us
Englisch (USA)
tr
Türkisch
es
Spanisch
zh
Chinesisch
Um ein spezielles Sprachkürzel zu erhalten, können Sie dies auch mit dem Internet Explorer (userLanguage) und einem Betriebssystem testen, das Sprachwechsel erlaubt: Die Sprachkürzel der Browser gleichen im Übrigen nicht vollständig den entsprechenden Toplevels. en-gb steht beispielsweise für Großbritannien, während der Toplevel co.uk ist.
Plugins Das navigator-Objekt besitzt Eigenschaften (beispielsweise plugins), um festzustellen, welche Plugins auf dem Rechner des Nutzers installiert sind. Fehlt beispielsweise das Flash-Plugin oder der Windows-Media-Player, kann JavaScript automatisch nachfragen. Mehr Informationen zur Verwendung erhalten Sie in Kapitel 23 »Kommunikation mit der Außenwelt«.
384
KOMPENDIUM
JavaScript
Browserobjekte
Kapitel 12
Sinnvoll? Ist die Browserüberprüfung mit dem navigator-Objekt wirklich sinnvoll? Hier gibt es nur eine Antwort: Das kommt darauf an. Verwenden Sie sehr viel JavaScript und ist Ihre Website groß, sind zwei Versionen sinnvoll. Wichtig ist aber, dass es eine abgespeckte Version der Website tatsächlich geben muss. Ist Ihnen eine zweite Version zu viel Arbeit, sollten Sie auch auf eine – aufwändig zu aktualisierende – Browserunterscheidung verzichten. Sie müssen die Browserunterscheidung mit jedem neuen Browser testen. Sonst macht sie keinen Sinn. Haben Sie nur auf bestimmten Seiten eine DHTML-Anweisung, ist eine Browserüberprüfung mit den Browserobjekten besser geeignet, da die Browserunterscheidung kaum so genau werden kann und nie exakt feststellt, welches Objekt von einem Browser unterstützt wird. Das automatische Auslesen der Sprachversionen wird im Web aktuell immer mehr verwendet. Es handelt sich prinzipiell um eine gute Technik, die, in Verbindung mit einem <noscript>-Bereich für nicht JavaScript-fähige Browser ausreichend kompatibel ist, wenn der Nutzer jederzeit manuell die Sprachen wechseln kann.
12.4
Browserobjekte
Die Browserunterscheidung mit den Browserobjekten stellt nicht fest, um welchen Browser es sich handelt, sondern nur, ob der Browser ein bestimmtes Objekt verwendet. Ein ähnliches Beispiel haben Sie bereits in Kapitel 12.3 im Abschnitt »Sprache feststellen« gesehen. if (document.getElementById) { document.write("getElementById vorhanden!"); }
Die if-Bedingung aus Listing 12.8 ergibt nur true, wenn der Browser die Methode getElementById() unterstützt.
Listing 12.8: Ist das Browserobjekt vorhanden? (unterscheidung_ browserobjekte. html)
Diese Unterscheidung wird natürlich nicht dazu verwendet, freudig auszugeben, dass die Methode unterstützt wird. Aber in dieser Fallunterscheidung kann getElementById ab jetzt gefahrlos verwendet werden. Ältere Browser kennen getElementById nicht, geben der if-Bedingung false zurück und ignorieren die weiteren Anweisungen.
KOMPENDIUM
JavaScript
385
Kapitel 12
Browserunterscheidung
Abbildung 12.10: Browser und Nutzer freuen sich: getElementById wird unterstützt.
DHTML und Browserunterscheidung In der Praxis wird der Test der Browserobjekte meist in DHTML-Anwendungen eingesetzt.12 Ein einfaches Beispiel soll das hier zeigen. In den folgenden Kapiteln wird die Browserunterscheidung mit Objekten noch häufig verwendet. Das Beispiel blendet einen Text ein, wenn der Nutzer über einen Link fährt (onmouseover) und blendet ihn – in derselben Funktion – wieder aus, wenn er den Link verlässt (onmouseout). Die Browserunterscheidung wird notwendig, wenn auf den leeren Absatz (-Tag) zugegriffen werden soll: Der W3C-konforme Zugriff per getElementById() funktioniert nur in neueren Browsern. Tabelle 12.8:
NS4.x NS6
getElementById()
getElementById
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Der Internet Explorer 4 und ältere Operaversionen benötigen die Kollektion document.all, die alle Elemente der Seite enthält. Neuere Internet Explorer und Opera unterstützen sie immer noch. Der Netscape Navigator 4.x verwendet als einziger document.layers. Zudem ist für den Zugriff auf eine Stileigenschaft wie visibility (Sichtbarkeit) kein style-Objekt vorhanden. Daher bietet es sich an, nach diesen verschiedenen Objekten zu unterscheiden. Eine Variable nimmt bereits die Referenz auf das Absatzobjekt auf. Hier die drei Fälle: 12 Wenn man den DHTML-Begriff weiter fasst und jede Art von Interaktion mit einbezieht, verwenden fast ausschließlich DHTML-Anwendungen die Unterscheidung mit Browserobjekten (auch das Sprachbeispiel wäre dann DHTML).
386
KOMPENDIUM
JavaScript
Browserobjekte
Kapitel 12
if (document.getElementById) { absatz = document.getElementById("text1").style; } else if (document.all) { absatz = document.all("text1").style; } else if (document.layers) { absatz = document.text1; }
Der Rest ist nicht mehr schwierig. Eine weitere Fallunterscheidung fragt ab, ob der Absatz gerade sichtbar ist oder nicht. Je nachdem wird er aus- oder eingeblendet. if (absatz.visibility == "visible" || absatz.visibility == "show") { absatz.visibility = "hidden"; } else { absatz.visibility = "visible"; }
Hier der komplette Code (hervorgehoben ist die Browserunterscheidung): Einblenden mit DHTML <script language="JavaScript">
Listing 12.9: Browserunterscheidung in einem praktischen Beispiel (dhtml.html)
if (document.getElementById) { absatz = document.getElementById("text1").style; } else if (document.all) { absatz = document.all("text1").style; } else if (document.layers) { absatz = document.text1; }
if (absatz.visibility == "visible" || absatz.visibility == "show") { absatz.visibility = "hidden"; } else { absatz.visibility = "visible"; } } //--> Anzeigen
Sichtbar!
KOMPENDIUM
JavaScript
387
Kapitel 12
Browserunterscheidung
Abbildung 12.11: Fährt der Nutzer mit der Maus über den Link, wird der Text »Sichtbar!« angezeigt.
Abbildung 12.12: Verlässt er den Link, wird der Text wieder ausgeblendet.
Der Netscape Navigator 4.x macht bereits in diesem einfachen Beispiel einige Schwierigkeiten: –
Im style-Attribut lässt sich ein Kasten nur unsichtbar schalten, wenn er auch per Stilanweisung positioniert wird.
–
Wollen Sie testen, ob ein Objekt eingeblendet ist, muss die visibilityEigenschaft den Wert show und nicht visible haben!13
Sinnvoll? Die Unterscheidung mit Objekten ist immer dann sehr sinnvoll, wenn Sie das Objekt anschließend verwenden möchten. Bei DHTML ist dies die bei weitem beste Methode, da eine allgemeine Browserunterscheidung Netscape 4.x und Internet Explorer 4 heute wohl noch nicht ausschließen sollte und Sie so für alle Browser auf einer Seite kompatibel programmieren können. Dies erkaufen Sie sich mit zusätzlichen Fallunterscheidungen und damit mehr Unübersichtlichkeit. Am besten lässt sich dieses Problem mit einem sinnvollen Einsatz von Funktionen und Sammelvariablen – die Referenzen allgemein verfügbar zwischenspeichern – lösen.
13 Unsichtbar ist im Netscape 4.x hide und nicht hidden. Bei der Zuweisung funktionieren visible und hidden jedoch.
388
KOMPENDIUM
JavaScript
Browserobjekte
Kapitel 12
Von einer Browser- und Versionsunterscheidung mittels Browserobjekten ist abzuraten. Da die Zuordnung meist nicht so einfach ist wie bei document.layers und Netscape 4.x, sind die Ergebnisse sehr unpräzise und mit einer Versionsfeststellung per navigator-Objekt nicht zu vergleichen. Zum Beleg hier ein kleines Fundstück aus dem Netz (in leicht abgewandelter und vereinfachter Form): Browser mit Objekten feststellen <script language="JavaScript">
Zum einen sind die Ergebnisse mit den Browsern – die eigentlich getestet werden sollen – schlecht. Der Internet Explorer 6 reagiert beispielsweise auf document.docType nicht. Zum anderen bleiben andere Browser wie der Internet Explorer 5.5 – ein wichtiger Zwischenschritt, Opera und Konqueror völlig außen vor. Abbildung 12.13: Der Opera 7 ist ein Internet Explorer 5?!
KOMPENDIUM
JavaScript
389
Kapitel 12
Browserunterscheidung
12.5
Serverseitige Browserunterscheidung
Im HTTP-Header, den der Browser an den Webserver sendet, steht die Browserversion und die Plattform. Die gängigen serverseitigen Programmiersprachen können darauf zugreifen. Sie könnten also auch diese Informationen verwenden, um zwischen den Browserversionen zu unterscheiden. Das einzige Problem ist, dass der HTTP-Header nicht übermittelt, ob JavaScript deaktiviert ist. Sie müssen also dennoch in Ihrem Code <noscript>Container vorsehen. Hier hat die clientseitige Browserüberprüfung Vorteile, da bereits in der Seite mit der Browserunterscheidung der <noscript>-Container integriert sein kann. Die übrigen Seiten benötigen ihn dann nicht mehr.14 Bei der DHTML-Versions- oder Objektüberprüfung kommen Sie ohnehin an clientseitiger JavaScript-Überprüfung mit Browserobjekten nicht vorbei. Bis hier war die serverseitige Browserüberprüfung graue Theorie. Es wird also Zeit, das Ganze in der Praxis näher zu beleuchten. Für das folgende Beispiel kommt JScript .NET zum Einsatz. JScript .NET ist die JavaScriptSprachvariante von Microsoft für den Einsatz mit der .NET-Plattform. .NET für das Internet heißt dabei ASP.NET. Mehr zu JScript .NET erfahren Sie in Kapitel 24 »JScript .NET«. JScript ist als ASP.NET-Programmiersprache nicht sehr weit verbreitet, bietet Ihnen allerdings die gute Gelegenheit, mit Ihrem JavaScript-Wissen serverseitig zu programmieren. ASP.NET besteht hauptsächlich aus dem .NET Framework. Dieses Framework enthält eine sehr große Klassenbibliothek. Die Klassen in dieser Bibliothek enthalten in den Eigenschaften und Methoden die komplette Funktionalität für Ihre Anwendungen. Für unser Beispiel ist die Rückgabe des Request-Objekts interessant. Es liefert die Antworten des Clients – also des Browsers – an den Server. Dieses Objekt enthält ein Unterobjekt Browser, das die Browserinformationen mit einer eigenen Datei, die Browserinformationen enthält, abgleicht und sie in Eigenschaften speichert.15 Folgende Eigenschaften sind hier (unter anderem) von Interesse:
14 wenn Ihre Seiten ab der ersten Seite nur mit JavaScript funktionieren sollen. 15 In der .NET-Klassenbibliothek ist das Browser-Objekt im Namespace System.Web.HttpBrowserCapabilities gespeichert.
390
KOMPENDIUM
JavaScript
Serverseitige Browserunterscheidung
Kapitel 12
Browser – liefert einen String mit dem Browsernamen. MajorVersion – liefert die ganzzahlige Versionsnummer des Browsers,
beim Internet Explorer 5.5 also 5. MinorVersion – liefert die Versionsnummer nach dem Komma, beim Netscape Navigator 2.02 also 02. Version – gibt die komplette Versionsnummer zurück. EcmaScriptVersion – prüft die Versionsnummer des unterstützten ECMAScript-Standards. Etwas verwirrend ist, dass diese Version in JavaScriptVersionsnotation – 1.1, 1.2, 1.316 – ausgegeben wird. 1.4 gibt es natürlich noch nicht, da ECMAScript erst drei Versionen hat.
Um die Klassenbibliothek zu erkunden und beispielsweise alle Eigenschaften des Browser-Objekts zu sehen, verwenden Sie am besten den Class-Browser, der beim .NET Framework SDK (und nur SDK, nicht die kleine Variante Redistributable) in den Quickstart-Tutorials mitgeliefert wird. Sie finden eine Beschreibung in Kapitel 24 »JScript .NET«. Abbildung 12.14: Die Klasse mit den Browserinformationen im .NET Framework
16 Die Version 1.3 entspricht also JavaScript 1.5.
KOMPENDIUM
JavaScript
391
Kapitel 12
Browserunterscheidung Das folgende Beispiel verwendet die fünf Eigenschaften und gibt die Ergebnisse in einem ASP.NET Web Control () aus:
Listing 12.11: Serverseitige Browserunterscheidung (browserpruefung.aspx)
<script runat="server"> function Ausgabe(o: Object, e: EventArgs) { var var var var var
bro = Request.Browser.Browser; maj = Request.Browser.MajorVersion; min = Request.Browser.MinorVersion; vers = Request.Browser.Version; ecma = Request.Browser.EcmaScriptVersion;
ausgabe.Text ausgabe.Text ausgabe.Text ausgabe.Text ausgabe.Text
= bro + "
"; += "MajorVersion: " + maj + "
"; += "MinorVersion: " + min + "
"; += "Version: " + vers + "
"; += "ECMAScript:" + ecma;
} Serverseitig Browser auslesen
Sie können das Beispiel nur testen, wenn Sie unter Windows den Internet Information Service (in früheren Windows-Versionen Internet Information Server) installiert haben17 und das .NET Framework besitzen. Wie die Installation funktioniert, erfahren Sie in Kapitel 24 »JScript .NET«, das einen Einstieg in die serverseitige Programmierung mit ASP.NET bietet. Des Weiteren erfahren Sie dort, was Sie bei der serverseitigen Programmierung beachten müssen und wie Sie am besten vorgehen.
17 Er wird bei Windows NT, 2000 und XP Professional auf der CD-ROM mitgeliefert. Unter anderen Windows-Betriebssystemen müssen Sie darauf verzichten.
392
KOMPENDIUM
JavaScript
Serverseitige Browserunterscheidung
Kapitel 12 Abbildung 12.15: Der Netscape Navigator meldet sich mit Version 5, ist aber ein Navigator 7.
Abbildung 12.16: Opera 7 wird gut erkannt.
Abbildung 12.17: Der Internet Explorer 6 traut sich nur ECMAScript v2 zu.
KOMPENDIUM
JavaScript
393
13
Bilder
Als Netscape 3 ein eigenes Bildobjekt besaß1, begann der Rollover-Boom im Internet. Jede bessere (heute auch jede schlechtere) Website schmückt sich mit einer Schaltfläche, die Farbe oder Form wechselt. Bilder haben allerdings noch mehr Power. In Formularen können Sie Schaltflächen oder Kontrollkästchen ersetzen. Darüber hinaus lassen sich Bilder sehr einfach animieren. Dies fällt zwar in den Bereich DHTML, ist aber ohne CSS-Stilanweisungen und auch in sehr alten Browsern möglich. In den Browsern ab Netscape 3 und Internet Explorer 4 ist das image-Objekt komplett integriert. Der Internet Explorer 3 besitzt es eigentlich nicht, weil es in der Macintosh-Version 3.01 des Internet Explorers noch mit heißer Nadel in abgespeckter Form implementiert wurde.
13.1
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 13.1: Das image-Objekt
Rollover
Als Rollover-Effekt bezeichnet man den Austausch von einem Bild durch ein anderes. Dieser Bildaustausch erfolgt bei den Ereignissen onmouseover (wenn der Nutzer die Grafik mit der Maus überfährt) und onmouseout (wenn der Mauszeiger die Grafik wieder verlässt). Sie benötigen für einen Rollover-Effekt zwei Bilder mit unterschiedlichen Zuständen. Die folgenden Beispiele verwenden die Dateien schalt1.gif (blaue Schaltfläche) und schalt2.gif (dieselbe Schaltfläche in Rot). Der Zugriff auf das Bild erfolgt über das document-Objekt und den Namen des Bildes. Der Name muss im name-Attribut des -Tags angegeben sein. Um das Bild zu ändern, verwenden Sie die Eigenschaft src des imageObjekts. Damit weisen Sie die Bildquelle neu zu.2 1 2
entspricht JavaScript 1.1 src steht für source (Quelle)
KOMPENDIUM
JavaScript
395
Kapitel 13 Listing 13.1: Rollover-Effekt im HTML-Attribut (rollover.html)
Bilder
Die Zeilen aus Listing 13.1 erledigen Folgendes: Im onmouseover-Attribut wird direkt die Bildquelle in schalt2.gif geändert. Das onmouseout-Attribut setzt wieder auf Bild schalt1.gif zurück. Wenn Sie den Objektaufruf direkt in die Ereignisattribute schreiben, müssen die Anführungszeichen innerhalb der JavaScript-Anweisung andere sein als beim Attribut. Im Beispiel steht der Attributwert in doppelten Anführungszeichen. Die JavaScript-Anweisung darin verwendet einfache Anführungszeichen. Abbildung 13.1: Rechts: Der Nutzer fährt über die Schaltfläche. Diese wechselt die Farbe (im Druck: die Graustufe).
Rollover-Funktion Der Rollover-Effekt lässt sich auch sehr einfach in Funktionen auslagern. Dadurch wird der Code übersichtlicher: Listing 13.2: Rollover-Effekt mit zwei Funktionen (rollover_funktion. html)
Rollover <script language="JavaScript">
//-->
396
KOMPENDIUM
JavaScript
Rollover
Kapitel 13
Automatisiert Wollen Sie die Funktionen für den Rollover-Effekt mehrmals verwenden, bietet es sich an, mit Parametern beim Funktionsaufruf zu arbeiten, die zeigen, welches Bild jeweils geändert werden soll. Das folgende Beispiel nutzt dies: Zuerst übergibt es eine Nummer an die Funktion. onmouseover="over('1')"
Diese wird als Parameter z in der Funktion übernommen. function over(z) {
Aus dem Parameter und einem Text, der bei allen Schaltflächen gleich ist, wird der Name des Bildes erstellt: var name = "schalt" + z;
Nun kommt eine weitere Art des Bildzugriffs ins Spiel: die Kollektion3 images[]. Sie ist im Prinzip ein Array mit allen Bildern der Webseite. Die Bilder können entweder mit ihrem Index, z.B. images[0] oder mit ihrem Namen, images["Bildname"], angesprochen werden. Für das Beispiel wird der Bildname durch die Variable name ersetzt: document.images[name].src="schalt2.gif";
Ein Direktzugriff über document.name ist hier nicht möglich, da die Variable name nicht als image-Objekt angesehen wird. Der Interpreter sucht, statt den Wert der Variablen zu verwenden, nach einem Bild mit dem name-Attribut name.
3
Eine Kollektion ist ein, von JavaScript zur Verfügung, gestellter Container für Elemente. Funktional entspricht eine Kollektion einem Array.
KOMPENDIUM
JavaScript
397
Kapitel 13
Bilder Hier sehen Sie das vollständige Beispiel:
Listing 13.3: Ein automatisiertes Rollover (rollover_automatisch.html)
Rollover <script language="JavaScript">
//-->
Abbildung 13.2: Jeweils eine Funktion erledigt das Mouseover bzw. Mouseout für alle Schaltflächen.
Ältere Browser Ältere Browser, sogar Netscape 4.x, unterstützen die Ereignisse onmouseover und onmouseout im -Tag nicht. Hier müssen Sie sie stattdessen in einen Link packen. Tabelle 13.2: onmouseover und onmouseout im -Tag
398
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Rollover
Kapitel 13
Wollen Sie auf sehr alten Browsern, also Netscape 2 und Internet Explorer 3 (Windows), eine Fehlermeldung aufgrund des nicht vorhandenen imageObjekts vermeiden, müssen Sie auch eine Fallunterscheidung einbauen, die testet, ob das Objekt vorhanden ist. if (document.images) { Anweisungen; }
Das folgende Beispiel wandelt Listing 13.3 ab und macht es auch für ältere Browser kompatibel: Rollover in alten Browsern <script language="JavaScript">
Listing 13.4: Rollover in einem Link (rollover_ aeltere.html)
Denken Sie daran, das Attribut border = "0" in das -Tag zu packen, wenn Sie einen Link außen herum legen. Anderenfalls wird das Bild automatisch mit Rahmen in der Linkfarbe angezeigt. Wollen Sie keinen Verweis im Link einfügen, ersetzen Sie die URL in href durch ein Doppelkreuz (#)4. Damit scrollen allerdings manche Browser bei langen Seiten mit Ankern nach oben.
4
auch Hash
KOMPENDIUM
JavaScript
399
Kapitel 13
Bilder
Abbildung 13.3: Auch Netscape 4.x kann nun mit Rollover umgehen.
Zufall Der Zufall ist ein gutes Instrument, um Interaktivität interessant zu machen. Der Nutzer weiß nie, was als Nächstes kommt. Diese Ungewissheit wirkt abwechslungsreich. Auf der CD-ROM zum Buch finden Sie im Ordner code\kap13 die Beispielbilder dio.gif und dio1.gif bis dio5.gif. Eine Zufallszahl zwischen 0 und 1 erzeugen Sie mit Math.random(). Sie lässt sich mit einer einfachen Rechnung in jeden beliebigen Zahlenbereich umwandeln.5 In diesem Beispiel soll beim Rollover eines aus fünf verschiedenen Bildern zufällig aufgerufen werden. Der Trick ist, den Namen der Grafik aus einer Zeichenkette ("dio") und der Zufallszahl zwischen 1 und 5 zu bilden. Diese Anweisungen werden in eine Funktion verpackt und nur noch in den bereits bekannten Funktionen over() und out() aufgerufen. Nachfolgend der vollständige Code: Listing 13.5: Mit Zufall lassen sich schöne Effekte erzielen. (rollover_zufall. html)
Rollover mit Zufall <script language="JavaScript">
400
siehe Kapitel 6.2 unter »Math« im Abschnitt »Zufallszahlen«
KOMPENDIUM
JavaScript
Rollover
Kapitel 13
}
function over(z) { var name = "dio" + z; document.images[name].src = zufall(); } function out(z) { var name = "dio" + z; document.images[name].src = "dio.gif"; } //--> Abbildung 13.4: Welche Diode erscheint, ist purer Zufall.
Experimentieren Sie ein wenig mit dem Zufall. In diesem Buch wird er Ihnen noch häufiger begegnen, beispielsweise in diesem Kapitel unter 13.4 »Animation?«.
Tipps und Tricks Sie können natürlich bei den onmouseover- und onmouseout-Ereignissen auch ein beliebiges Bild austauschen. Warum sollte sich nicht die Farbe der Überschrift ändern, wenn der Nutzer über eine Schaltfläche fährt? Oder es tauchen zusätzliche Menüpunkte auf. So lässt sich sogar eine Navigation mit Bildern erzeugen.
KOMPENDIUM
JavaScript
401
Kapitel 13
Bilder Ebenfalls sehr praktisch ist die Möglichkeit, mehrere Bilder gleichzeitig zu tauschen. So können Sie sogar kompliziertere Schaubilder nur mit Bildern erstellen. Bei anderen Ereignissen können Sie natürlich auch Bilder ändern. Ein Beispiel wäre ein Bildwechsel bei onclick. Der Nutzer klickt auf eine Schaltfläche und irgendwo ändert sich ein Bild.
13.2
Vorladen
Die bisher verwendeten Grafiken waren allesamt sehr einfach und klein. Das muss allerdings nicht immer so sein. Wenn Sie viele Grafiken auf der Seite haben oder die Grafiken sehr groß werden, muss der Nutzer auf einen Rollover-Effekt unter Umständen eine Weile warten. Das ist natürlich optisch nicht akzeptabel. Daher können Sie Grafiken vorladen. Dieser Vorgang heißt auch Precaching6 oder Preloading. Precaching ist insbesondere bei Animationen sinnvoll, damit die Animation runder abläuft. Laden Sie Ihre Webseiten auf jeden Fall zum Testen auf den Webserver und probieren Sie dann aus, wie schnell die Seite lädt, wenn Sie eine langsame (also keine DSL- und möglichst keine ISDN-) Verbindung haben. Das Precaching folgt einer ganz einfachen Idee. Zuerst legen Sie ein neues image-Objekt an: var bild = new Image();
Anschließend weisen Sie der Objektinstanz mit der Eigenschaft src als Quelle das Bild zu, das Sie vorladen möchten. bild.src = "schalt2.gif";
Diese zwei Zeilen können Sie nun einfach in eines der Rollover-Beispiele aus dem letzten Abschnitt einfügen. Natürlich ist es auch erlaubt, das Vorladen in einer Funktion zu erledigen. Sie sollten die Funktion allerdings schon im Skript-Teil und nicht erst beim onload-Ereignis aufrufen, damit das oder die Bilder sofort vorgeladen werden.
6
402
Dieser Begriff stammt von dem Wort Cache, dem Zwischenspeicher des Browsers, in den das Bild vorgeladen wird.
KOMPENDIUM
JavaScript
Vorladen
Kapitel 13
Für das folgende Beispiel ist Listing 13.2 die Grundlage. Abgeändert wurde, dass in der Funktion over die Objektinstanz bild statt der Bildquelle angesprochen wird: Vorladen <script language="JavaScript">
Informationen per E-Mail?
Wollen Sie einen Anruf?
Das Aussehen von Auswahllisten und Textfeldern aller Art lässt sich nur über Stylesheet-Anweisungen – die nur in neueren Browsern funktionieren – ändern.
KOMPENDIUM
JavaScript
409
Kapitel 13
Bilder
Abbildung 13.6: Der Nutzer klickt den Radiobutton an …
Abbildung 13.7: … und die Farbe ändert sich.
13.4
Animation?
Die einfachste Art der Animation ist die Animation durch Bildwechsel. Diese Form der Animation machen sich beispielsweise GIF-Animationen zunutze. Ist es aber einmal notwendig, statt GIFs JPEGs zu verwenden – weil mehr Farben erforderlich sind oder Fotos animiert werden sollen –, hilft JavaScript weiter.
Dateiformate Das praktische an Bildanimationen mit JavaScript ist, wie bereits erwähnt, dass das Dateiformat keine Rolle spielt. Sie können also eine Animation mit allen drei im Web verbreiteten Bildformaten durchführen: GIF (Compuserve Graphics Interchange Format) ist das älteste Webformat. Es unterstützt eine Farbtiefe von 8 Bit (entspricht 256 Farben) und komprimiert verlustfrei. Das GIF-Format komprimiert insbesondere 410
KOMPENDIUM
JavaScript
Animation?
Kapitel 13
flächige Grafiken sehr gut, ist also für Schaltflächen und Ähnliches sehr gut geeignet. Als besondere Funktionen können Sie Teile der GIF-Grafik transparent schalten und eine GIF-Datei als Animation speichern, also mit mehreren Bildern, die hintereinander ablaufen. Das JPEG-Format (Joint Photographic Experts Group) hat eine größere Farbtiefe von 16 Bit (entspricht über 16,77 Mio. Farben), komprimiert allerdings verlustbehaftet; das heißt, je niedriger die Dateigröße werden soll, desto niedriger muss die Qualität gewählt werden. Die Qualitätsverluste äußern sich in Treppenbildung.10 Das PNG-Format (Portable Network Graphics) gibt es in mehreren Varianten. Als PNG-8 mit 8 Bit und 256 Farben oder als PNG-24 mit 16 Bit und über 16,77 Mio. Farben. Das PNG-Format komprimiert verlustfrei, bietet ebenfalls Transparenz, aber keine Animation. Das PNG-24 erreicht deutlich höhere Dateigrößen als JPEG, da es nicht verlustbehaftet komprimiert.
Bildertausch Im Prinzip ist der Bildertausch in der Animation nur eine Fortsetzung des Rollover-Effekts. Die einzige Komponente, die neu hinzukommt, ist der Zeitabstand, in dem die Bilder getauscht werden. Dafür sorgt die Methode setTimeout("Funktion()", Zeit) des window-Objekts. Sie ruft eine Funktion zeitverzögert auf. Die Verzögerung wird im zweiten Parameter Zeit in Millisekunden angegeben. setTimeout() gibt es bereits in den Uralt-Browsern Netscape Navigator 2 und
Internet Explorer 3 in beiden Versionen. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 13.4: Die Methode setTimeout() des window-Objekts
Ein einfaches Beispiel illustriert dies: Beim Laden der Seite wird nach 1.000 Millisekunden mit setTimeout() eine Animationsfunktion aufgerufen. Als Parameter wird 0 übergeben. Dieser Parameter legt fest, welches Bild aus dem Bilder-Array zuerst aufgerufen wird. onload="setTimeout('ani(0)', 1000)"
10 Das Bild wirkt so, als hätte es viereckige Punkte; das nennt man auch pixelig.
KOMPENDIUM
JavaScript
411
Kapitel 13
Bilder setTimeout() erlaubt die Parameterübergabe von einem oder mehreren Para-
metern auf zwei Arten: Innerhalb des Funktionsaufrufs, wie in diesem Beispiel gesehen. Wollen Sie hier Variablenwerte verwenden, müssen Sie diese mit dem Namen der Funktion konkatenieren, da dieser ein String ist: setTimeout("ani(" + i + ")", 1000);
Als weitere Parameter. Dazu wird die Funktion nicht als String und ohne Klammern übergeben: setTimeout(ani, 1000, i);
Die zweite Variante ist allerdings auf den Netscape Navigator ab Version 4.x und Mozilla beschränkt, wird also in der Praxis kaum verwendet. Im nächsten Schritt wird in der Animationsfunktion (ani()) geprüft, ob das letzte Bild bereits erreicht ist. Ist dies nicht der Fall, wird die Bildquelle auf das nächste Bild geändert, i um eins erhöht und die Funktion über setTimeout() nach 1.000 Millisekunden erneut aufgerufen. function ani(i) { if (i < bilder.length) { document.dio.src = bilder[i]; i++; setTimeout("ani(" + i + ")", 1000); } }
Haben Sie es bemerkt? Hier handelt es sich um einen rekursiven Funktionsaufruf (siehe Kapitel 5.1, Abschnitt »Rekursion«). Natürlich können Sie die Zeitverzögerung, in der die Animation ausgeführt wird, frei wählen und dem Array mehr oder weniger Bilder hinzufügen. Nachfolgend sehen Sie den vollständigen Code: Listing 13.11: Eine einfache Animation (animation.html)
Animation <script language="JavaScript">
412
KOMPENDIUM
JavaScript
Animation?
Kapitel 13 i++; setTimeout("ani(" + i + ")", 1000);
} }
//--> Abbildung 13.8: Die Animation hüpft von Bild zu Bild.
Bei Animationen sollten Sie die Bilder vorladen (siehe Kapitel 13.2 »Vorladen«). Der Übersichtlichkeit halber fehlt das Vorladen bei diesen Arbeitsbeispielen. Die soeben realisierte Animation ließe sich auch mit einer Schleife konstruieren. Einen Ansatz hierzu finden Sie auf der CD-ROM unter animation_ schleife.html. Endlose Animation Bis jetzt war die Animation auf einen Durchlauf beschränkt. Aus Listing 13.11 lässt sich allerdings schnell eine Endlosanimation machen. Eine einfache if-Fallunterscheidung setzt den Zähler (i) wieder auf 0, wenn das letzte Bild ausgegeben wurde: endlose Animation <script language="JavaScript">
Listing 13.12: Eine endlose Animation (animation_endlos. html)
function ani(i) { if (i < bilder.length) { document.dio.src = bilder[i]; i++ } if (i == bilder.length) {
KOMPENDIUM
JavaScript
413
Kapitel 13
Bilder i = 0; }
setTimeout("ani("+i+")", 1000); } //-->
Beachten Sie, dass setTimeout() einmal zu viel aufgerufen wird, wenn Sie für die zweite Fallunterscheidung eine else-Anweisung verwenden. if (i < bilder.length) { document.dio.src = bilder[i]; i++ } else () { i = 0; }
Der Grund: Nach der Erhöhung von i um 1 wird die Fallunterscheidung verlassen, der else-Fall also nicht mehr überprüft. Beim letzten Bild der Animation wäre i also zuerst 4 und würde dann um 1 erhöht. Erst beim nächsten setTimeout()-Aufruf wäre die Bedingung nicht mehr erfüllt. setInterval() setTimeout() ist nicht die einzige Methode des window-Objekts, die sich für Animationen eignet. Die zweite wichtige Methode ist setInterval(Funktion, Zeit). Sie ruft eine Funktion regelmäßig nach einer über den Parameter Zeit angegebenen Zeitspanne in Millisekunden auf. setInterval() ist ein wenig jünger als setTimeout(), da sie erst in der vierten Generation von Netscape und Internet Explorer integriert wurde. Die Methode steht allerdings heute in allen wichtigen Browsern zur Verfügung. Tabelle 13.5: Die Methode setInterval() des window-
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Objekts
Die endlose Animation aus dem letzten Abschnitt lässt sich auch mit setInterval() realisieren. Dazu wird eine Funktion eingefügt, die den setInterval()-Aufruf enthält.
414
KOMPENDIUM
JavaScript
Animation?
Kapitel 13
endlose Animation <script language="JavaScript">
Listing 13.13: Die Animation mit setInterval()
endlos abspielen (animation_endlos_ setinterval.html)
function ani(i) { if (i < bilder.length) { document.dio.src = bilder[i]; i++ setTimeout("ani("+i+")", 1000); } } function start() { ani(0); setInterval("ani(0)", 5000); }
//-->
Überschneiden sich Zeitintervalle wie in diesem Beispiel, kann es zu Fehlern kommen, da der JavaScript-Interpreter zum Abarbeiten der Funktionsaufrufe eine – zwar sehr kurze, aber dennoch vorhandene – Zeitspanne benötigt. Dies ist bei einem kleinen Beispiel wie diesem belanglos, kann aber bei umfangreicherem Code problematisch werden. Mehrmals ablaufen lassen Eine endlos ablaufende Animation ist natürlich noch nicht der Weisheit letzter Schluss. Besser wäre es, flexibel wählen zu können, wie oft eine Animation abläuft. Um dies zu zeigen, wird Listing 13.12 ein wenig umgearbeitet: Eine neue Zählervariable z speichert, wie oft die Animation bisher ablief. Immer, wenn i wieder auf 0 gesetzt wird, erhöht sich z um 1, da ein Schleifendurchlauf beendet ist. Die setTimeout()-Anweisung wird nur ausgeführt, wenn z kleiner als 4 ist, also nur bis zum vierten Schleifendurchlauf.
KOMPENDIUM
JavaScript
415
Kapitel 13
Bilder Hier sehen Sie das komplette Beispiel:
Listing 13.14: Eine Animation mehrmals abspielen (animation_mehrmals.html)
Animation mehrmals abspielen <script language="JavaScript">
function ani(i) { if (i < bilder.length) { document.dio.src = bilder[i]; i++ } if (i == bilder.length) { i = 0; z++;
} if (z < 4) { setTimeout("ani("+i+")", 1000); }
} //-->
Bildertausch mit der Funktion Zufall Um ein wenig mehr Pep in Animationen zu bringen, kommt nun der Zufall ins Spiel. Die Methode zur Gewinnung einer Zufallszahl zwischen 0 und 1, Math.random(), haben Sie bereits kennen gelernt.11 Sie bildet die Basis jeder zufallsgesteuerten Animation. Im folgenden Beispiel verwenden wir die Methode, um fünf Leuchtdioden in zufälliger Reihenfolge in verschiedenen Farben aufleuchten zu lassen. Zuerst wird beim Laden des Dokuments nach einer Zeitverzögerung von 5 Sekunden (= 5.000 Millisekunden) die Animationsfunktion aufgerufen. onload="setTimeout('ani()', 5000)"
11 siehe Kapitel 6.2 unter »Math« im Abschnitt »Zufallszahlen«
416
KOMPENDIUM
JavaScript
Animation?
Kapitel 13
Diese Funktion ruft mit setInterval() alle 200 Millisekunden die Funktion zufall() auf. function ani() { setInterval('zufall()', 200); }
Die Funktion zufall() gewinnt zwei Zufallszahlen zwischen 1 und 5. Eine Zahl ist für den Dateinamen und die zweite für das Bild im HTML-Code vorgesehen. So wird also bei jedem Aufruf der Funktion eines der fünf Bilder dio1.gif bis dio5.gif zufällig ausgewählt und im nächsten Schritt der Name des Bildes, das ausgetauscht werden soll (dio1 bis dio5). function zufall() { var x = 1 + (Math.round(Math.random() * 4)); var z = 1 + (Math.round(Math.random() * 4)); var neu = "dio" + x + ".gif"; var name = "dio" + z; document.images[name].src = neu; }
Nachfolgend sehen Sie den kompletten Code: Animation mit Zufall <script language="JavaScript">
Listing 13.15: Eine einfache Animation mit Zufall (zufall_animation. html)
//-->
KOMPENDIUM
JavaScript
417
Kapitel 13
Bilder
Abbildung 13.9: Die Lämpchen leuchten fröhlich nacheinander.
Besonderheiten setTimeout() und setInterval() sind praktisch zu handhaben. Dennoch gilt es einiges zu beachten:
Alle Anweisungen nach setTimeout() und setInterval() werden sofort und nur einmal ausgeführt. Nur der Code in der aufgerufenen Funktion wird zeitverzögert oder mehrmals aufgerufen. setTimeout() und setInterval() können so genannte Identifier erhalten.
Dazu müssen Sie nur einer Variablen zugewiesen werden. Die Variable enthält dann den Identifier. Er wird verwendet, um die beiden Methoden zu beenden. Dafür gibt es die Methoden clearTimeout() und clearInterval(). var id = setTimeout("Funktion", 1000); clearTimeout(id); clearTimeout() und clearInterval() gibt es bereits ebenso lange wie ihre Gegenstücke setTimeout() und setInterval(). Beispiele zu den beiden Metho-
den finden Sie in den folgenden Abschnitten. Alle vier sind Methoden des window-Objekts. clearTimeout() Das folgende Beispiel verwendet clearTimeout(), um eine endlos ablaufende Animation zu beenden. Klickt der Nutzer auf die Schaltfläche, wird die Funktion ende() aufgerufen. Sie verwendet clearTimeout() mit der Variablen id als Parameter. Diese globale Variable enthält den Identifier der setTimeout()-Anweisung aus der Animationsfunktion. Beachten Sie, dass id tatsächlich als globale Variable deklariert sein muss. Listing 13.16: Mit clearTimeout() eine Animation stoppen (clearTimeout.html)
418
clearTimeout() <script language="JavaScript">
KOMPENDIUM
JavaScript
Animation?
Kapitel 13
var id;
function ani(i) { if (i < bilder.length) { document.dio.src = bilder[i]; i++; } if (i == bilder.length) { i = 0; } id = setTimeout("ani("+i+")", 1000);
} function ende() { clearTimeout(id); }
//--> Beenden
Abbildung 13.10: Die Animation ist angehalten.
clearInterval() Das folgende Beispiel verwendet clearInterval(), um die zufallsgesteuerte Animation abzubrechen. Hier wurde der setInterval()-Aufruf nicht in einer Funktion, sondern direkt im Skript ausgeführt. Daher steht die Variable id automatisch als globale Variable zur Verfügung. Animation mit Zufall <script language="JavaScript">
KOMPENDIUM
JavaScript
Listing 13.17: Eine Animation mit clearInterval()
beenden (clearInterval())
419
Kapitel 13
Bilder document.images[name].src = neu; } var id = setInterval('zufall()', 200); function ende() { clearInterval(id); }
//-->
Beenden
Abbildung 13.11: Die Schaltfläche hält nun die Animation an.
Größenänderung Die Änderung der Bildgröße ist mit Vorsicht zu genießen. GIF, PNG und JPEG-Bilder sind so genannte Bitmap- oder Pixelbilder. Sie bestehen aus einzelnen Bildpunkten oder auch Pixeln.12 Jeder Bildpunkt hat eine Farbe und durch das Aneinanderreihen sehr vieler Bildpunkte entsteht das Bild. Nehmen Sie beispielsweise an, ein Bild hat 200 (Breite) * 100 (Höhe) Pixel. Würden Sie Breite und Höhe verdoppeln, hätte das Bild die Maße 400 * 200 Pixel. Der Haken daran: Irgendwo müssen die zusätzlichen Pixel herkommen. Bei einer Verkleinerung auf 100 * 50 Pixel gibt es ebenfalls einen Haken: Welche Pixel sollen gelöscht werden? Bildbearbeitungsprogramme verwenden dafür die so genannte Interpolation, eine mathematische Berechnung der zusätzlichen oder wegfallenden Bildpixel. Vergrößern Sie dagegen ein Bild im Browser mit den HTML-Attributen width und height oder mit 12 Da Bilder, die für das Internet produziert werden, meist dieselbe Auflösung wie der Bildschirm haben, entspricht ein Pixel des Bildes einem Pixel des Bildschirms. Bilder, die gedruckt werden sollen, benötigen höhere Auflösungen.
420
KOMPENDIUM
JavaScript
Animation?
Kapitel 13
JavaScript, behält das Bild seine Originalgröße und nur die dargestellte Größe wird geändert. Dies geschieht ebenfalls durch Interpolation. Allerdings interpolieren Browser meist wesentlich schlechter als Bildprogramme. Außerdem ist eine nachträgliche Korrektur durch Scharfzeichnen (schärfen) oder Ähnliches nicht möglich. Das ist verständlich, wenn Sie bedenken, dass Bildbearbeitungsprogramme Spezialisten und Browser eher Mädchen für alles sind. Vektorgrafiken haben das Skalierproblem13 nicht. Da sie aus Punkten, deren Verbindungen und Füllungen bestehen, können sie mathematisch exakt größer oder kleiner gerechnet werden. Allerdings sind Vektorgrafiken auch selten so detailliert wie Pixelbilder. Das bekannteste Vektorgrafikund Animationsformat im Netz ist Flash (bzw. SWF). Ein neueres standardisiertes und herstellerunabhängiges Format ist SVG (Scalable Vector Graphics). Sollten Sie nun Größenänderungen im Browser grundsätzlich unterlassen? Wenn es sich vermeiden lässt, auf jeden Fall. Eine Ausnahme bildet die Animation von flächigen und geometrischen Pixelgrafiken. Das folgende Skript ändert die Höhe (Eigenschaft height des image-Objekts) eines 1-Pixel großen Balkens. Der Netscape Navigator 4.x unterstützt height und width zwar, kann sie allerdings nur lesen und nicht setzen. Die folgende Animation funktioniert dort also nicht. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
height
()
width
()
Tabelle 13.6: Die Eigenschaften height und width des image-Objekts
Den Balken finden Sie unter balken.gif auf der CD-ROM. Die Animationsfunktion wird mit setInterval() alle 100 Millisekunden aufgerufen. Soll es schneller gehen oder die Animation zügiger ablaufen, wählen Sie einen kleineren Wert, ansonsten einen größeren. Viele Programmiersprachen animieren mit einem kleinen Flackern zwischen den Bildern, weil erst das alte gelöscht und dann das neue Bild innerhalb einer Millisekunde eingefügt werden muss. Da JavaScript dies vermeidet, sieht eine Animation mit setInterval() »sauber« aus.
13 Unter Skalieren versteht man die Änderung der Bildgröße.
KOMPENDIUM
JavaScript
421
Kapitel 13
Bilder In der Animationsfunktion ändert sich die Höhe des Bildes um 1. Wählen Sie einen größeren Wert, wenn die Animation schneller ablaufen soll. i++; document.balken.height = i;
Die Breite muss ebenfalls gesetzt werden, auch wenn sie gleich bleibt. Ansonsten würde der Balken proportional in Höhe und Breite skaliert. document.balken.width = 4;
Die if-Anweisung testet, wie hoch die Grafik bereits ist. Als Maß verwendet das Skript die Eigenschaft availHeight und zieht von ihr 200 Pixel ab. availHeight gibt die Größe des Platzes auf dem Bildschirm an, den der komplette Browser (inklusive Leisten) einnehmen kann. Elemente wie die Windows- oder KDE-Taskleiste werden abgezogen. if (i >= screen.availHeight-200)
Im Netscape Navigator 4.x ist screen ein eigenständiges Objekt und muss daher ohne vorangehendes window. geschrieben werden. Da Sie window in den anderen Browsern einfach weglassen können, sollten Sie dies also auf jeden Fall tun. Eine Alternative wäre window.innerHeight. Diese Eigenschaft gibt die Höhe des Raumes im Browser an, der für das Dokument reserviert ist. Allerdings gibt es diese Eigenschaft nur für Netscape ab Version 4.x. Ist i, die Zählervariable, bereits zu hoch, löscht clearInterval() das Animationsintervall. clearInterval(id);
Hier der komplette Code: Listing 13.18: Eine einfache Größenanimation (animation_groesse .html)
Animation mit Bildgröße <script language="JavaScript">= screen.availHeight-200) clearInterval(id);
422
KOMPENDIUM
JavaScript
Animation?
Kapitel 13
} function start() { id = setInterval('ani()', 100);
} //-->
Abbildung 13.12: Die Bildgröße wird erhöht und die Animation läuft von oben nach unten.
Auf der CD-ROM finden Sie unter dem Namen code\kap13\animation_ groesse_setTimeout.html das Skript mit derselben Funktionalität nur unter Verwendung von setTimeout(). Wollen Sie auf Ihrer Seite Thumbnails (kleine Bilder) anbieten, die beim Anklicken größer gezoomt werden, sollten Sie nicht die Größenskalierung verwenden. Sie sollten vor allem nicht die Bilder für die Übersicht verklei-
KOMPENDIUM
JavaScript
423
Kapitel 13
Bilder nern, da die große Variante dennoch geladen werden muss. Tauschen Sie stattdessen bei einem Mausklick das größere mit dem kleineren Bild und geben Sie für das neue Bild die (großen) Originalmaße an.
Tipps und Tricks Es gibt auch eine dritte Art der Animation: die Positionsänderung. Sie erfolgt – auch für Bilder – über Stilanweisungen (CSS) und fällt unter den Oberbegriff DHTML. Mehr dazu erfahren Sie in Kapitel 19 »CSS und JavaScript« und in Kapitel 20 »DHTML«. Die verschiedenen Animationsarten lassen sich natürlich auch mischen. So können Sie beispielsweise eine Größenanimation mit einem Bildtausch verbinden oder den Nutzer Bilder per Drag&Drop platzieren lassen, die beim Anklicken die Farbe wechseln.
13.5
Formatierung und Verschönerung
Das -Tag besitzt einige Attribute, die das Aussehen und das »Drumherum« steuern. Vier davon sind besonders interessant, da sie auf mehreren Browsern verfügbar sind: align – erlaubt, die Ausrichtung von Text an einem Bild zu ändern. Die Eigenschaft entspricht dem align-Attribut des -Tags. border – gibt die Rahmendicke in Pixeln an. hspace – bestimmt den horizontalen Abstand neben dem Bild. vspace – legt den vertikalen Abstand fest.
In Netscape 4.x sind all diese Attribute nur les- und nicht schreibbar. Tabelle 13.7: Weitere Eigenschaften des image-Objekts
NS4.x NS6 align
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
border
()
hspace
()
vspace
()
Das folgende Beispiel setzt alle vier Eigenschaften ein. Sie sehen die Ausgangssituation in Abbildung 13.13. Der Code besteht nur aus einem Bild mit zugehörigem Text:
424
KOMPENDIUM
JavaScript
Formatierung und Verschönerung
Kapitel 13 Abbildung 13.13: Das Ausgangsbild
Drück mich
Als erste Änderung wird im onload-Ereignis eine Funktion format() aufgerufen. Sie ändert nun die vier Eigenschaften: Die Eigenschaften für Bild-Attribute <script language="JavaScript">
Listing 13.19: Bildattribute ändern (attribute.html)
function format() { document.schalt.align = "middle"; document.schalt.border = 2; document.schalt.hspace = 6; document.schalt.vspace = 10; }
Drück mich Abbildung 13.14: Das Ausgangsbild wurde kräftig durcheinander gewirbelt.
KOMPENDIUM
JavaScript
425
Kapitel 13
Bilder Die vier Eigenschaften lassen sich auch dann mit JavaScript ändern, wenn sie bereits im -Tag definiert sind.
Alternativ-Text Der Alternativ-Text steht in HTML immer im alt-Attribut. Der Text wird angezeigt, wenn eine Grafik nicht dargestellt werden kann14 oder als Hilfetext-Kasten, wenn der Nutzer mit der Maus über die Grafik fährt. In JavaScript greifen Sie mit der Eigenschaft alt des image-Objekts auf den Alternativ-Text zu und können ihn auch ändern. Sie sollten diesen Text immer angeben, da sich ansonsten insbesondere Nutzer mit deaktivierten Grafiken ärgern. In Netscape 4.x ist die alt-Eigenschaft nur les- und nicht schreibbar. Tabelle 13.8: Die alt-Eigenschaften des image-Objekts
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel fügt nachträglich einen Alternativ-Text hinzu: Listing 13.20: Alternativ-Text mit JavaScript (alt.html)
Alternativ-Text <script language="JavaScript"> function alt() { document.schalt.alt = "Klick mich!"; }
Wenn Sie bei einer Animation aus mehreren Bildern für jedes Bild einen eigenen Alternativ-Text wünschen, hilft die alt-Eigenschaft weiter. Sie können die Alternativ-Texte ebenso wie die Bildnamen in einem Array speichern und mit einer Schleife auslesen.
14 Mögliche Gründe sind meist deaktivierte Grafiken oder ein fehlerhafter Link.
426
KOMPENDIUM
JavaScript
Imagemaps und JavaScript
13.6
Kapitel 13
Imagemaps und JavaScript
Für Imagemaps gibt es drei interessante JavaScript-Anwendungen: In href-Attributen der <area>-Tags können Sie auch JavaScript-Funktionen aufrufen. Dies funktioniert genauso wie bei gewöhnlichen Links und wird daher hier nicht erläutert. In Imagemap-Bereichen, also <area>-Tags, stehen auch Ereignisse wie onmouseover und ommouseout zur Verfügung. Sie können also beispielsweise beim Überfahren eines Imagemap-Bereichs das komplette Bild ändern. Opera in Version 6 und frühere Versionen hatten beim onmouseout-Ereignis einen Bug, sodass Rollover-Effekte nicht mehr funktionieren. Mit der Eigenschaft useMap des image-Objekts weisen Sie einem Bild eine Imagemap zu. Der Name der Imagemap folgt in Klammern mit vorangestelltem Doppelkreuz (#)15. In Opera kann useMap nicht gesetzt, sondern nur gelesen werden. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
()
Tabelle 13.9: Die Eigenschaft useMap des imageObjekts
Das folgende Beispiel verwendet ein einfaches Bild grafik.gif, das aus zwei Farbflächen besteht. Sie finden es auf der CD-ROM im Ordner code\kap13. Dieses Bild soll mit einer Imagemap versehen werden. Der rote Bereich links verweist auf die Webadresse von Markt+Technik (oder eine beliebige andere Seite), der rechte blaue auf Hauser & Wenz. Diese Zuordnung soll sich drehen, wenn der Nutzer eine Schaltfläche anklickt. Der Lösungsansatz ist so gut wie einfach: Sie legen zwei Imagemaps an und wechseln mit useMap die Imagemap. Dazu ist eine einfache Fallunterscheidung mit einer if-Anweisung ausreichend: function map() { if (document.grafik.useMap == "#karte") { document.grafik.useMap = "#karte_gedr"; } else { document.grafik.useMap = "#karte";
15 auch Hash
KOMPENDIUM
JavaScript
427
Kapitel 13
Bilder } }
Hier der komplette Code: Listing 13.21: Mit useMap Imagemaps tauschen (usemap.html)
usemap <script language="JavaScript">
//--> Drehen <map name="karte"> <area shape="rect" coords="0,0 50, 100" href="http://www.mut.de" / > <area shape="rect" coords="50,0 100, 100" href="http://www.hauserwenz.de" /> <map name="karte_gedr"> <area shape="rect" coords="0,0 50, 100" href="http://www.hauserwenz.de" /> <area shape="rect" coords="50,0 100, 100" href="http://www.mut.de" />
Um den Effekt des Beispiels zu überprüfen, müssen Sie natürlich wissen, wohin der Link führt. Sie sehen ihn in der Statusleiste des Browsers.
428
KOMPENDIUM
JavaScript
Imagemaps und JavaScript
Kapitel 13 Abbildung 13.15: Links ist der Link auf Markt+Technik (siehe Statusleiste).
Abbildung 13.16: Nach Anklicken der Schaltfläche DREHEN ist links nun der Link auf Hauser & Wenz.
KOMPENDIUM
JavaScript
429
14
Navigationshilfen
In diesem Kapitel sind kleine, aber wertvolle Skripten versammelt, die alle dabei helfen, Ihre Seiten besser nutzbar zu machen. Als wichtige Objekte kommen gleich zu Beginn das history-Objekt für die Browser-History und das location-Objekt für Weiterleitungen zum Einsatz. Den Links und dem link-Objekt ist ein eigener Abschnitt gewidmet. Anschließend geben Sie Text in der Statusleiste aus, erfahren, wie Laufschriften für Newsticker funktionieren und integrieren eine Druckfunktion mit JavaScript.
14.1
history-Objekt
Das history-Objekt enthält die History des Browsers, also die zuletzt besuchten Seiten. Es ist ein Unterobjekt von window; richtig heißt es also: window.history
Allerdings kann window auch problemlos weggelassen werden.1 Mit den Methoden dieses Objekts können Sie die ZURÜCK- und VORWÄRTS-Schaltflächen2 Ihres Browsers per JavaScript simulieren: back() – die zuletzt besuchte Seite forward() – die nächste Seite in der History. Diese Seite ist immer dann vorhanden, wenn Sie vorher mit back() oder der Browser-Schaltfläche ZURÜCK in der History nach hinten gegangen sind. go(Ort) – springt auf eine bestimmte Seite in der History, die bei Ort
angegeben ist. Die Angabe erfolgt als ganze Zahl. 1 geht also eine Seite in der History nach vorne, -1 eine Seite nach hinten. Alternativ kann auch eine URL oder der Seitentitel angegeben werden. Wenn und nur wenn er in der History vorhanden ist, springt der Browser dorthin.
1
2
In manchen Fällen, beispielsweise beim screen-Objekt, ist dies sogar sinnvoll, da der Netscape Navigator 4.x screen nur als eigenes Objekt kennt. Bei anderen Objekten wie document kann ein Weglassen dagegen zu Fehlern führen. Die Bezeichnungen für diese Schaltflächen variieren. Der Netscape Navigator verwendet beispielsweise WEITERLEITEN statt VORWÄRTS.
KOMPENDIUM
JavaScript
431
Kapitel 14
Navigationshilfen Mit go(0) laden Sie die aktuelle Seite neu. Allerdings je nach Browser entweder aus dem Cache (Zwischenspeicher) oder durch erneutes Anfordern vom Server. Letzteres finden Sie häufig beim Internet Explorer. length – gibt an, wie viele Elemente in der History sind. Daraus lässt
sich leider nicht viel schließen, da der Nutzer beliebig mit dem Browser, über die Schaltflächen VORWÄRTS und ZURÜCK und mit Menübefehlen, in der History navigieren kann. Der Ausgangspunkt, das heißt die aktuelle Position in der History, ist also nicht feststellbar. Einzige Ausnahme: Wenn die Länge der History 1 ist, handelt es sich um die erste, in der History geladene Seite. Das folgende Beispiel setzt die drei Methoden ein, um per Link die Navigationsschaltflächen des Browsers nachzubauen: Listing 14.1: Eine selbst gebaute Browsernavigation (history.html)
Die History <script language="JavaScript">
//--> Zurück
Vorwärts
Zwei zurück
In der Praxis wird die selbst definierte History nur selten verwendet, da die meisten Nutzer die Browser-Schaltflächen gewohnt sind.
Bei Frames geht der Internet Explorer nur mit den URLs in der Adressleiste zurück. Mehr dazu erfahren Sie in Kapitel 18 »Frames«.
432
KOMPENDIUM
JavaScript
history-Objekt
Kapitel 14 Abbildung 14.1: Die Browsernavigation in der HTMLSeite
Netscape Navigator Der Netscape Navigator ab Version 4 und der Mozilla besitzen drei Eigenschaften, die den anderen Browsern fehlen: current – die URL der aktuellen Seite next – die URL der Seite, die sich als nächste Seite (Schaltfläche VORWÄRTS)
in der History befindet
previous – die URL der zuletzt besuchten Seite
Diese Eigenschaften wirken auf den ersten Blick recht unsicher. Oder können Sie sich vorstellen, dass es erbaulich ist, wenn eine beliebige Website immer erfährt, von welchem Ort der Nutzer auf diese Seite surft? Allzu große Sorge ist allerdings unbegründet. Diese Informationen werden nur an so genannte Signed Scripts, also Skripten mit Zertifikat, oder nach der Bestätigung eines Browserdialogs ausgegeben. Der Nutzer muss also auf jeden Fall zustimmen. Abbildung 14.2: Der Browser verweigert die Erlaubnis.
Mehr zum Thema Sicherheit erfahren Sie in Kapitel 22 »JavaScript und Sicherheit«.
KOMPENDIUM
JavaScript
433
Kapitel 14
Navigationshilfen
14.2
Weiterleitung und das location-Objekt
Das location-Objekt dient hauptsächlich zur Weiterleitung auf eine andere Seite, weil das Objekt eigentlich alles rund um die URL der aktuell im Fenster geöffneten Seite enthält. Zur Weiterleitung dient nur eine Eigenschaft des Objekts: href. Sie erhält als Wert die neue Adresse, die relativ oder absolut angegeben werden kann. Die Umleitung erfolgt sofort: Listing 14.2: Umleiten mit href (href.html)
Seite umleiten <script language="JavaScript">
} //--> Auf Markt+Technik umleiten
Alternativ zu href können Sie auch die Methode assign("URL") verwenden. Sie hat dieselbe Wirkung, ist aber in der Praxis weniger in Gebrauch.3 window.location.assign("http://www.mut.de");
Die Eigenschaft href und die Methode assign() gibt es bereits in den sehr alten Browsern Netscape 2 und Internet Explorer 3 in beiden Varianten. Tabelle 14.1:
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
href
assign()
href und assign()
3
434
Der Grund hierfür wurde noch nie wirklich geklärt. Eine Vermutung ist, dass sich href an das href-Attribut eines HTML-Links anlehnt und deswegen beliebter ist. Eine zweite, dass assign() als Methode natürlich nicht gelesen, sondern nur gesetzt werden kann. Aber wahrscheinlich hat nur irgendjemand einmal mit href begonnen und alle anderen haben abgeschrieben.
KOMPENDIUM
JavaScript
Weiterleitung und das location-Objekt
Kapitel 14
Zeitversetzt umleiten Um erst nach einer festlegbaren Zeitspanne umzuleiten, eignet sich am besten setTimeout(). Im folgenden Beispiel startet ein Anklicken der Schaltfläche die Umleitung. Im Textfeld wird die Wartezeit durch eine kleine Animation verkürzt, indem jede Sekunde (setInterval()) ein Punkt ausgegeben wird: Seite umleiten <script language="JavaScript">
Listing 14.3: Zeitversetzt umleiten (umleitung_ zeitversetzt.html)
//--> Wartezeit
Abbildung 14.3: Die Wartezeit wird mit einer Anzeige der bereits vergangenen Sekunden »belohnt«.
KOMPENDIUM
JavaScript
435
Kapitel 14
Navigationshilfen
Anker usw. Einige Eigenschaften des location-Objekts liefern nützliche Informationen über die URL bzw. lassen sich auch einzeln setzen: hash – enthält den Teil der URL nach dem Doppelkreuz (#, auch Hash). Damit haben Sie direkten Zugriff auf den Anker. hostname – liefert den Namen des Hosts ohne Port, beispielsweise
www.mut.de. host – gibt den Host mit Port zurück, beispielsweise www.beispiel. de:80. port – enthält nur den Port, beispielsweise den Standard-Webport 80. pathname – steht für den Pfad einer Adresse, beispielsweise /daten/
index.html. protocol – enthält das Protokoll, also http:, ftp: oder Ähnliches. search – liefert den Suchstring hinter dem Fragezeichen (?) in der URL.
Alle Eigenschaften sind bereits in sehr alten Browsern ab Netscape 2 und Internet Explorer 3 in beiden Varianten verfügbar. Tabelle 14.2: Eigenschaften des location-Objekts
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Neu laden Die Methode reload() des location-Objekts sieht auf den ersten Blick sehr praktisch aus. Sie besitzt zusätzlich einen Parameter, der angibt, ob die Seite vom Server oder aus dem Browsercache geladen werden soll. reload(true);
gibt an, dass die Seite vom Server neu angefordert werden soll. Eine Version im Cache soll ignoriert werden. reload(false);
holt die Seite aus dem Browsercache, wenn sie dort vorhanden ist – ansonsten vom Server. Diese Methode wird auch verwendet, wenn der Parameter fehlt.
436
KOMPENDIUM
JavaScript
Weiterleitung und das location-Objekt
Kapitel 14
Das Problem mit reload() ist, dass das Verhalten des Browsercache nicht standardisiert ist. Daher ist es nahezu unvorhersagbar, ob der Browser tatsächlich so reagieren wird, wie per reload() gewünscht. Die Methode replace("URL") leitet den Nutzer auf eine neue Seite weiter, ohne dass die alte in der History verbleibt. reload() und replace() sind in älteren Browsern ab Netscape 3 und Internet Explorer 4 verfügbar. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 14.3: reload() und replace()
Die Methode go() des history-Objekts lädt mit history.go(0);
die Seite neu, ohne Scroll-Position und Einträge in Formularelemente zu verlieren. Nur globale Variablen und Funktionsaufrufe, beispielsweise mit setInterval() oder setTimeout, werden gestoppt. Zum Testen fügen Sie folgenden Code in Listing 14.3 ein: function los() { setTimeout("umleiten()", 10000); id = setInterval("ausgeben()", 1000);
Listing 14.4: Neu laden mit go() (go.html)
setInterval("neu laden()", 3000);
} . . . function neu laden() { history.go(0); } Abbildung 14.4: Das Skript wird bei drei Punkten gestoppt.
KOMPENDIUM
JavaScript
437
Kapitel 14
Navigationshilfen
14.3
Links
Links dienten in den bisherigen Kapiteln hauptsächlich dazu, JavaScriptCode aufzurufen. Neben dieser Möglichkeit können Sie allerdings auch noch auf einige Eigenschaften von Links zugreifen. Der Zugriff auf einen Link erfolgt meist auf einem der drei folgenden Wege: Über die ID per getElementById(ID). Dies funktioniert nur in neueren Browsern. Tabelle 14.4: getElementById()
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Über document.all.ID für den Internet Explorer 4 (und höher) Über die Kollektion document.links[Index], die alle Links eines Dokuments beinhaltet. Sie enthält entweder den Index oder den Namen (name-Attribut) des Links. Dies funktioniert auch in älteren Browsern. Tabelle 14.5: document.links
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Linkziel ändern Die zwei Eigenschaften href und target für -Tags sind besonders interessant. Allerdings ist hier Vorsicht geboten, da diese Eigenschaften nur für echte Links gelten, also -Tags mit href-Attribut, nicht aber für Anker, die ohne href-Attribut auskommen. Die href-Eigenschaft des link-Objekts gibt es bereits in sehr alten Browsern ab Netscape 2 und Internet Explorer 3 in beiden Versionen. Tabelle 14.6: href-Eigenschaft
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel greift mit document.links[] auf den ersten Link im Skript mit dem Index 0 zu und ändert dann – je nach vorher angegebener URL – mit href das Ziel des Links.
438
KOMPENDIUM
JavaScript
Links
Kapitel 14
Zugriff auf einen Link <script language="JavaScript"> Drucken Abbildung 14.18: Das Dialogfeld DRUCKEN erscheint.
KOMPENDIUM
JavaScript
457
Kapitel 14
Navigationshilfen In einer Seite mit Frames kann der Druckbefehl für jeden Frame einzeln gegeben werden.11 Um alle Frames zu drucken, können Sie im Frameset den Druckbefehl aufrufen. Unter Windows scheitert allerdings der Netscape Navigator 4.x an dieser Aufgabe. Hier müssen Sie alle Frames einzeln ansprechen – am besten mit der frames[]-Kollektion – und drucken. Der Internet Explorer besitzt zwei eigene Ereignisse für das Drucken. onbeforeprint vor dem Druck und onafterprint nach dem Druck. Im Internet Explorer 4 unter Windows12 können Sie auch über ActiveX-Objekte drucken.
11 Die Grundlagen zu Frames finden Sie in Kapitel 18 »Frames«. 12 nur Win32, also kein Win 3.1
458
KOMPENDIUM
JavaScript
15
Fenster
In manchen Bereichen des Internets springen dem ahnungslosen Nutzer beim Aufrufen – zugegebenermaßen meist zweifelhafter – Webseiten dutzende von neuen Browserfenstern entgegen. Die Begeisterung über diesen Angriff ist natürlich meistens begrenzt. Die sich öffnenden Fenster – auch Popups genannt – sind aber nicht nur auf unseriösen Seiten zu finden, sondern werden auch für Navigationsleisten, Sitemaps oder seriöse Werbemeldungen verwendet. Dieses Kapitel erklärt die Hintergründe von Popups, zeigt zuerst welche Dialogfelder mit JavaScript aufrufbar sind und bietet zuletzt einige besondere Funktionen, beispielsweise wie sich der Fensterinhalt scrollen und das Fenster selbst – allerdings nur in manchen Browsern – bewegen lässt. Die hier verwendeten Methoden und Eigenschaften gehören alle zum window-Objekt. Das ist natürlich logisch, da es sich als Oberobjekt aller Browserobjekte um das Browserfenster kümmert.
15.1
Dialogfelder
Dialogfelder sind kleine Fenster, bei denen der Nutzer in irgendeiner Form reagieren muss. Er tritt mit dem Browser und damit mit der Webseite in einen Dialog.
Warnmeldung Das einfachste Dialogfenster, das in diesem Buch oft zum Einsatz kam, ist die Warnmeldung: window.alert("Meldung");
Listing 15.1: alert()
(alert.html)
KOMPENDIUM
JavaScript
459
Kapitel 15
Fenster Diese Zeile erzeugt eine Warnmeldung mit dem Text »Meldung«. Der Nutzer kann dies nur bestätigen. Die Meldung selbst ist zwar normalerweise ein String, kann aber auch ein beliebiger anderer Datentyp sein.
Abbildung 15.1: Die Warnmeldung
alert() gibt es bereits in Uralt-Browsern wie Netscape 2 und 3 und Internet
Explorer 3 in beiden Versionen. Tabelle 15.1: alert()
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Abbildung 15.2: Uralt-Browser wie hier Netscape 2 fügen leider noch ein, dass es sich um einen JavaScript-Aufruf handelt. Neuere Netscape-Browser und Mozilla schreiben das in die Titelleiste.
In der Praxis wird diese Meldung hauptsächlich verwendet, um den Nutzer auf einen Fehler, beispielsweise ein falsch ausgefülltes Formularelement, aufmerksam zu machen. In der Entwicklungsphase eignet sich die Warnmeldung hervorragend, um zwischendurch Werte von Variablen zu testen und auszugeben.1 Vorsicht ist allerdings bei der Verwendung in Schleifen geboten. Ist die Schleife endlos und Sie haben darin eine Warnmeldung, hilft es nur noch, den Browser gewaltsam zu beenden. alert() hält normalerweise das JavaScript-Skript an. In den Netscape Navi-
gator-Versionen 3 und 4 für Linux/Unix tritt allerdings ein anderes Verhalten auf. Hier wird das Skript weiter ausgeführt.
1
460
vor allem, da alert() alle Datentypen ausgeben kann!
KOMPENDIUM
JavaScript
Dialogfelder
Kapitel 15
Bestätigung Ein Dialogfeld mit window.confirm("Frage") erlaubt dem Nutzer bereits mehr Interaktion als alert(). Sie stellen in der Meldung eine Frage, die der Nutzer dann mit OK bestätigen oder mit ABBRECHEN verneinen kann. JavaScript liefert bei OK das Ergebnis true, bei ABBRECHEN false. Wenn das Bestätigungsdialogfeld erscheint, wird das Skript angehalten und wartet auf die Nutzereingabe. var erg = window.confirm("Haben Sie einen Führerschein?"); if (erg) { window.alert("Ein Mietwagen ist reserviert."); } else { window.alert("Sie können leider keinen Wagen mieten!"); }
Listing 15.2: confirm()
(confirm.html)
Listing 15.2 fragt den Nutzer, ob er einen Führerschein hat. Je nach Antwort erhält er eine Meldung. Abbildung 15.3: Klickt der Nutzer an, dass er einen Führerschein hat …
Abbildung 15.4: … wird ihm bestätigt, dass er einen Mietwagen erhält.
confirm() ist bereits genauso lange enthalten wie alert(), also seit Netscape 2
beziehungsweise Internet Explorer 3 in der ersten Version. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 15.2: confirm()
In Opera 6 kann der Nutzer angeben, dass er künftig nicht mehr von dem Bestätigungs- oder Ausgabefenster gefragt werden soll. Opera merkt sich dann die Antwort. Dies gilt, wenn das Dokument mit NEULADEN neu aufgerufen wird, nicht aber bei einem »harten« Neuladen (z.B. mit (Enter) in der Adressleiste).
KOMPENDIUM
JavaScript
461
Kapitel 15
Fenster
Abbildung 15.5: Im Opera kann der Nutzer die Nachfrage deaktivieren.
In der Praxis wird confirm() hauptsächlich zum Bestätigen von Bedingungen verwendet, die der Website-Betreiber nicht selbst prüfen muss. Ein Beispiel ist die bekannte Frage, ob die AGBs gelesen wurden. Allerdings bleibt hier das Problem, dass der Nutzer JavaScript deaktiviert haben könnte. Dann müssen Sie eine Alternative bieten.
Eingabefenster Das dritte Browser-übergreifende Dialogfeld ist das Eingabefenster. window.prompt("Beschreibung", Voreinstellung)
Dieses Fenster bittet den Nutzer in einem Beschreibungstext, etwas in das Textfeld einzugeben. Die Voreinstellung zeigt bereits einen Wert im Textfeld an, kann aber auch weggelassen werden. Allerdings erscheint dann in manchen Browsern undefined als Vorausfüllung. Verwenden Sie also besser einen leeren String, wenn Sie das Feld freilassen möchten. prompt() gibt es seit Netscape 2 und Internet Explorer 3 in der ersten Ver-
sion. Tabelle 15.3: prompt()
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel fragt den Nutzer in zwei Eingabefeldern nach zwei Zahlen und addiert diese anschließend: Listing 15.3: prompt()
(prompt.html)
462
var x = window.prompt("Erste Zahl?", ""); var y = window.prompt("Zweite Zahl?", ""); var erg = parseFloat(x) + parseFloat(y); alert(erg);
KOMPENDIUM
JavaScript
Dialogfelder
Kapitel 15 Abbildung 15.6: Geben Sie eine Zahl ein.
Abbildung 15.7: Das Ergebnis wird mit alert() ausgegeben.
Beachten Sie, dass der Rückgabewert von prompt()immer ein String ist. Benötigen Sie eine Zahl, sollten Sie den String in eine Zahl verwandeln, ansonsten kann es bei einer Addition wie im letzten Beispiel zu einer StringKonkatenation kommen. Wollten Sie dieses Beispiel in der Praxis einsetzen, müssten Sie zusätzlich eine Überprüfung einfügen, falls der Nutzer keine Zahl eingibt. In der Praxis kommt prompt() relativ selten zum Einsatz, da nur genau eine Eingabe abgefragt werden kann. Mit einem Formular – das eventuell noch in einem kleinen neuen Browserfenster geöffnet werden kann – haben Sie als Entwickler mehr Freiheiten.
Dialogfelder im Internet Explorer Der Internet Explorer bietet noch einige Besonderheiten, was Dialogfelder betrifft: Die Methode window.showModalDialog("URL", Parameterarray, "Einstellungen") ruft ein Dialogfeld auf, dass der Nutzer verlassen muss, bevor es im Browserfenster weitergeht (daher modal). Dieses Dialogfeld hat noch weitere Optionen. Als Parameter müssen Sie eine URL angeben. Die dort angegebene Seite ist der Inhalt des Dialogfeldes. Optional können Sie an das Dialogfeld mit einem Array Werte übergeben. Diese Werte werden dann im Skript des Dialogfelds (im mit URL aufgerufenen Dokument) mit dialogArguments[] ausgelesen. Ebenfalls optional können Sie noch weitere Optionen für das Dialogfeld angeben. Hier die wichtigsten: – dialogWidth – Breite des Dialogfelds in Pixeln (px) – dialogHeight – Höhe des Dialogfelds in Pixeln (px)
KOMPENDIUM
JavaScript
463
Kapitel 15
Fenster – dialogLeft – Position des Dialogs von links (auf dem Bildschirm relativ zur linken oberen Ecke des Dialogs). Angabe in Pixeln (px) – dialogTop – Position des Dialogs von oben (auf dem Bildschirm relativ zur linken oberen Ecke des Dialogs). Angabe in Pixeln (px) – center – richtet den Dialog mittig im Fenster aus, wenn der Wert yes oder 1 ist. Dies ist auch die Standardeinstellung. – resizable – gibt an, ob die Größe des Dialogs änderbar ist (yes oder 1) oder nicht (no oder 0). – scroll – legt fest, ob im Dialogfeld gescrollt werden darf (yes oder 1) oder nicht (no oder 0). – status – erlaubt dem Dialog eine Statusleiste (yes oder 1) oder lässt sie weg (no oder 0). Die Methode window.showModelessDialog("URL", Parameterarray, "Einstellungen") arbeitet genau wie showModalDialog(), allerdings muss das Dialogfeld nicht beendet werden, um ins Hauptfenster zurückzukehren. window.createPopup() erzeugt ein kleines Popup, das direkt über der Seite liegt. Es wird erst mit der Methode show(x, y, Breite, Höhe, Objekt)2 angezeigt und muss komplett per Skript gefüllt werden. Des Weiteren besitzt es keinen Fensterrahmen oder sonstige Fenstereigenschaften. Eine externe URL wie bei den anderen beiden Methoden ist also nicht möglich.
Tabelle 15.4: Die besonderen Dialogfenster des Internet Explorers
NS4.x NS6 showModalDialog() showModelessDialog() createPopup a.
NS7
IE4 IE5
IE5.5 IE6
()a
O7
M1
K3
showModelessDialog() ist im Internet Explorer 5.x beim Mac nicht vorhanden.
showModalDialog() Das folgende Beispiel speichert die Namenseingabe des Nutzers (mit prompt()) in einem Array. Das Array wird bei showModalDialog() als Parameter-Array übergeben:
2
464
Das Objekt ist ein optionaler Parameter. Er gibt ein Objekt an, zu dem die x- und y-Koordinate in Relation stehen.
KOMPENDIUM
JavaScript
Dialogfelder
Kapitel 15
showModalDialog() <script language="JavaScript">
Listing 15.4: Ein Dialogfeld mit showModalDialog() (showModal-
Dialog.html)
//-->
Die Datei inhalt.html, die im Dialogfeld dargestellt wird, greift über die Eigenschaft dialogArguments[] auf die Elemente des übergebenen Arrays zu: Dialogfeld
Hallo <script language="JavaScript"> im Dialogfeld!
Listing 15.5: Die Datei mit dem Inhalt des Dialogfelds (inhalt.html)
Abbildung 15.8: Der Nutzer gibt seinen Namen ein …
Abbildung 15.9: … und das Dialogfeld kennt ihn.
KOMPENDIUM
JavaScript
465
Kapitel 15
Fenster Dieses Beispiel funktioniert mit showModelessDialog() analog. Sie finden das Beispiel unter showModelessDialog.html auf der CD-ROM im Ordner code\kap15. Wenn Sie die hier vorgestellten Methoden im Web verwenden, müssen Sie natürlich mit einer Browserunterscheidung sicherstellen, dass nur der Internet Explorer den Dialogfeldaufruf erhält. if (window.showModalDialog) { Aufruf; }
createPopup() Das folgende Beispiel für createPopup() lässt das Fenster erscheinen, wenn der Nutzer mit der Maus über einen Link fährt. Das Popup wird mit Stylesheet-Befehlen gefüllt, die von JavaScript aufgerufen werden.3 Zum Schluss zeigt die Methode show() das Popup an. Verlässt der Nutzer den Link mit der Maus, wird das Popup mit hide() wieder ausgeblendet; es ist aber immer noch vorhanden. Listing 15.6: Ein Popup für neuere Internet Explorer (create Popup.html)4
4 createPopup() <script language="JavaScript">
//--> Hauser und Wenz 3 4
466
Mehr zu Stilanweisungen in JavaScript erfahren Sie in Kapitel 19 »CSS und JavaScript«. Dieses Beispiel besitzt der Einfachheit halber keine Browserunterscheidung, die bei einer proprietären Funktion wie dieser in der Praxis noch ergänzt werden muss.
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15 Abbildung 15.10: Wenn der Nutzer über den Link fährt, erscheint das Popup.
15.2
Popups und andere neue Fenster
Ein neues Fenster oder Popup öffnen Sie in JavaScript mit der Methode open(). Diese Methode und ihre Möglichkeiten verdienen eine ausführlichere Beschreibung. open() hat folgende Parameter: window.open("URL", "Name", "Einstellungen", Ersetzen);
Die Parameter sind alle optional. Werden sie alle weggelassen, öffnet der Browser ein leeres Fenster ohne Namen in den Standardeinstellungen des Browserbefehls für ein neues Fenster.5 URL – gibt die Adresse des Dokuments an, in der das Fenster geöffnet
werden soll. Name – steht für den Namen des Fensters. Dies entspricht der Angabe eines Namens im HTML-Attribut target. Für den Namen gibt es noch einige weitere Optionen, die den Werten des target-Attributs in HTML entsprechen:
– _blank – ein neues Fenster ohne Namen – _parent – das Dokument wird im übergeordneten Frameset geöffnet. – _self – das Dokument wird im aktuellen Fenster oder Frame geöffnet.
5
Internet Explorer: DATEI/NEU/FENSTER; Netscape Navigator DATEI/NEU/NAVIGATORFENSTER
KOMPENDIUM
JavaScript
467
Kapitel 15
Fenster – _top – das Dokument wird im aktuellen Fenster auf oberster Ebene geöffnet. Eventuell vorhandene Framesets verschwinden. – _media – das Dokument wird in der Explorer-Leiste MEDIEN des Internet Explorers abgelegt. Dies funktioniert nur im Internet Explorer 6 und ist hauptsächlich für Musik und Videos sinnvoll. – _search – das Dokument wird in der Explorer-Leiste SUCHEN abgelegt. Auch dies funktioniert nur im Internet Explorer, allerdings bereits ab Version 5. Einstellungen – enthält Konfigurationsmöglichkeiten für das neue
Browserfenster. Sie finden diese im Abschnitt »Einstellungen«. Ersetzen – enthält einen Boolean, der angibt, ob das neue Fenster das aufrufende Dokument in der History ersetzt (true) oder nicht (false, Standardeinstellung). window.open() sollte nicht in der Kurzform open() geschrieben werden, da auch document eine open()-Methode besitzt.
Das folgende Beispiel öffnet eine Seite in einem neuen Fenster. Zusätzliche Einstellungen werden nicht vorgenommen: Listing 15.7: Ein Fenster öffnen (open.html)
open() <script language="JavaScript">
//--> Hauser und Wenz open() gibt es seit Netscape 2 und Internet Explorer 3 in der ersten Version.
468
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15 Abbildung 15.11: Die neue Webseite wurde in einem neuen Fenster geöffnet.
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 15.5: window.open()
Einstellungen Bis jetzt war das Öffnen des neuen Fensters noch keine Kunst und hätte auch über das target-Attribut in HTML bewerkstelligt werden können. Erst die möglichen Einstellungen machen es richtig interessant. Die Einstellungen werden durch Kommata getrennt hintereinander angegeben.6 Eigenschaft und Wert sind durch ein Ist-Gleich (=) verbunden: window.open("http://www.hauser-wenz.de", "Fenster1", "width=750,height=500");
Diese Zeilen erzeugen ein neues Browserfenster mit einer Breite von 750 Pixeln und einer Höhe von 500 Pixeln. Viele Einstellungen erwarten Wahrheitswerte als Angabe. Wahrheitswerte werden hier allerdings nicht mit true oder false angegeben, sondern mit yes und no.
6
Sie sollten nach den Kommata keine Leerzeichen einfügen, da Netscape 4.x damit Probleme hat.
KOMPENDIUM
JavaScript
469
Kapitel 15
Fenster
Abbildung 15.12: Die Homepage öffnet sich in einem Fenster mit festgelegter Größe.
window.open("http://www.hauser-wenz.de", "Fenster1", "width=750,height=500,resizable=no");
Mit dieser Zeile wird ein Browserfenster erzeugt, das nicht in der Größe veränderbar ist. Alternativ zu yes kann auch die 1 und alternativ zu no die 0 verwendet werden. Wenn Sie den Wert weglassen, wird automatisch von yes ausgegangen. Folgende Zeile verhindert also auch, dass das Browserfenster eine variable Größe hat: window.open("http://www.hauser-wenz.de", "Fenster1", "width=750,height=500,resizable");
Sobald auch nur eine der Einstellungen in open() vorgenommen wird, werden alle anderen Einstellungen automatisch auf no geschaltet. Dies sehen Sie auch an dem Beispiel in Abbildung 15.12. Die folgende Tabelle zeigt alle möglichen Einstellungen. Bei Wahrheitswerten wird nur die Bedeutung von yes erklärt, no ist das Gegenteil. Die Kurzformen dürfen ebenfalls verwendet werden. Tabelle 15.7 gibt für die Einstellungen an, mit welchem Browser sie jeweils kompatibel sind.
470
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Einstellung
Beschreibung
alwaysLowered
Neues Fenster steht immer hinter anderen Browserfenstern (yes). Funktioniert nur mit einem signierten Skript im Netscape (siehe Kapitel 22 »JavaScript und Sicherheit«).
alwaysRaised
Neues Fenster steht immer vor anderen Browserfenstern (yes). Funktioniert nur mit einem signierten Skript im Netscape.
channelmode
Stellt den Internet Explorer ab Version 4 bei yes im ChannelModus dar, das heißt, Adressleiste und Menüleiste verschwinden und der Browser ist in der maximierten Ansicht. Standardeinstellung ist immer no.
dependent
Macht bei yes das neu geöffnete Fenster vom vorigen abhängig. Wird dies geschlossen, schließt sich auch das neu geöffnete.
directories
Blendet bei yes die Symbolleiste mit Links und Ähnlichem ein. Im Internet Explorer heißt sie beispielsweise LINKS, im Netscape Navigator und Mozilla PERSÖNLICHE SYMBOLLEISTE bzw. PERSONAL TOOLBAR. Ist im Netscape Navigator ab Version 6 die Symbolleiste im Originalfenster ausgeblendet, wird sie auch nicht im neuen Fenster angezeigt.
fullscreen
Zeigt bei yes im Internet Explorer ab Version 4 das neue Fenster in der maximierten Ansicht über den gesamten Bildschirm an.
height
Gibt die Höhe des neuen Fensters in Pixeln an. Dazu muss allerdings keine Angabe der Einheit erfolgen.
hotkeys
Deaktiviert bei no die meisten Tastenkürzel (außer beispielsweise zum Schließen des Browsers) für ein neues Fenster. Dies funktioniert allerdings nur bei signierten Skripten im Netscape Navigator.
innerHeight
Legt die innere Höhe, also die Höhe des Dokumentfensters im Netscape Navigator und Mozilla in Pixeln fest. Wird die Größe zu klein, benötigen Sie dazu ein signiertes Skript.
innerWidth
Legt die innere Breite, also die Breite des Dokumentfensters im Netscape Navigator und Mozilla in Pixeln fest. Wird die Größe zu klein, benötigen Sie dazu ein signiertes Skript.
left
Gibt die x-Koordinate in Pixeln von der linken oberen Ecke des Bildschirms aus an und ist auf den Internet Explorer ab Version 4 beschränkt.
location
yes blendet die Adressleiste des Browsers mit der URL ein.
menubar
yes zeigt die Menüleiste des Browsers an.
KOMPENDIUM
JavaScript
Kapitel 15 Tabelle 15.6: Einstellungen für Fenster
471
Kapitel 15 Tabelle 15.6: Einstellungen für Fenster (Forts.)
Fenster
Einstellung
Beschreibung
outerHeight
Legt die äußere Höhe, also die Höhe des Browserfensters im Netscape Navigator und Mozilla in Pixeln fest. Wird die Größe zu klein, benötigen Sie dazu ein signiertes Skript.
outerWidth
Legt die äußere Breite, also die Breite des Browserfensters im Netscape Navigator und Mozilla in Pixeln fest. Wird die Größe zu klein, benötigen Sie dazu ein signiertes Skript.
resizable
Gibt an, ob das Browserfenster vom Nutzer in der Größe geändert werden darf (yes), oder nicht (no).
screenX
Gibt die x-Koordinate in Pixeln von der linken oberen Ecke des Bildschirms aus an und ist auf Netscape ab Version 4 und Mozilla beschränkt.
screenY
Gibt die y-Koordinate in Pixeln von der linken oberen Ecke des Bildschirms aus an und ist auf Netscape ab Version 4 und Mozilla beschränkt.
scrollbars
yes zeigt die Scroll-Balken im Browser an.
status
yes zeigt die Statusleiste im Browser an.
titlebar
no blendet die Titelleiste des Browsers aus. Funktioniert nur mit
einem signierten Skript in Netscape ab Version 4. Im Internet Explorer muss es sich um eine HTML Applicationa (HTA) oder um ein sicheres Dialogfeld handeln. Mehr dazu erfahren Sie in Kapitel 22 »JavaScript und Sicherheit«. toolbar
Blendet bei yes die Werkzeugleiste mit Vor, Zurück, Neuladen usw. an. Im Internet Explorer heißt sie STANDARDSCHALTFLÄCHEN, im Netscape Navigator NAVIGATIONS-SYMBOLLEISTE.
top
Gibt die y-Koordinate in Pixeln von der linken oberen Ecke des Bildschirms aus an und ist auf den Internet Explorer ab Version 4 beschränkt.
width
Gibt die Breite des neuen Fensters in Pixeln an, ohne dass die Einheit angegeben sein müsste.
z-lock
Bei yes wird das neu geöffnete Browserfenster nicht über anderen Fenstern angezeigt, wenn es den Fokus erhält.
a.
Quelle zu HTA: http://msdn.microsoft.com/library/default.asp?url=/workshop/author/hta/overview/htaoverview.asp
472
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15
Auf der CD-ROM finden Sie zu den Einstellungen, die nicht in anderen Beispielen in diesem Kapitel verwendet werden, jeweils ein kurzes Beispiel. Die Dateien sind mit den Namen der Einstellungen bezeichnet, beispielsweise toolbar.html für die Einstellung toolbar, und befinden sich im Ordner code\kap15. NS4.x NS6
NS7
IE4 IE5
alwaysLowered
alwaysRaised
channelmode dependent
directories
fullscreen
IE5.5 IE6
O7
M1
hotkeys
innerHeight
innerWidth
location
menubar
outerHeight
outerWidth
resizable
screenX
screenY
scrollbars
status
titlebar
toolbar
top
KOMPENDIUM
JavaScript
Tabelle 15.7: Browserkompatibilität der Einstellungen
height
left
K3
473
Kapitel 15 Tabelle 15.7: Browserkompatibilität der Einstellungen (Forts.)
Fenster
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
width
z-lock
Die verschiedenen Browser-spezifischen Einstellungen behindern sich nicht gegenseitig, da die Browser die Einstellungen ignorieren, die sie nicht unterstützen. So geben Sie die Position des Fensters im Internet Explorer mit left und top an, im Netscape Navigator und Mozilla dagegen mit screenX und screenY. Der Opera kennt viele Einstellungen nicht, da das Fenster entkoppelt von der Oberfläche als frei schwebendes Fenster oder Register gehandhabt wird. Volle Kontrolle Mit einem signierten Skript erhalten Sie in Netscape bereits eine recht große Kontrolle über den Browser. Das folgende Beispiel erstellt ein neues Browserfenster, das sich immer im Vordergrund befindet (alwaysRaised), nicht in der Größe veränderbar (resizable) ist und ohne Titelleiste (titlebar) auskommt. Die Breite und Höhe wird nachträglich auf die Maße des Bildschirms eingestellt. Listing 15.8: Volle Kontrolle über den Netscape Navigator (kontrolle.html)
open() <script language="JavaScript">
} //--> Hauser und Wenz
474
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15 Abbildung 15.13: Der Nutzer muss Zugriffsrechte vergeben.
Abbildung 15.14: Die Webseite beherrscht den gesamten Bildschirm und hat nun keinen Rahmen mehr.
Unsignierte Skripte funktionieren nur dann, wenn Sie lokal darauf zugreifen oder eine Sicherheitseinstellung für den Browser ändern. Mehr dazu in Kapitel 22 »JavaScript und Sicherheit«. Opera Der Opera zeigt beim Fenster-Handling einige Eigenheiten. Im neuen Opera 7 werden Fenster mit open() automatisch in einem neuen Register, nicht aber in einem neuen Browserfenster geöffnet. Das Ausblenden von Leisten bewirkt also nichts.
Fokus Wenn Sie ein neues Fenster mit JavaScript aufrufen, erscheint es im Vordergrund, es erhält also den Fokus. Dieses Verhalten ist auch meist gewünscht. Rufen Sie dagegen aus einem Fenster das neue Fenster erneut auf und ein Fenster mit diesem Namen ist bereits geöffnet, erhält es nicht den Fokus. Das ist meist nicht gewünscht und insbesondere bei einer Sitemap oder einer Werbung sehr ärgerlich, da der Nutzer sie auch beim zweiten Laden noch sehen sollte.
KOMPENDIUM
JavaScript
475
Kapitel 15
Fenster In diesem Fall hilft die Methode focus() des window-Objekts. Sie gibt einem Fenster (oder Formularelement) den Fokus. In diesem Beispiel soll das neu aufgerufene Fenster beim Laden den Fokus erhalten. Dazu dient das onloadEreignis im -Tag: onload="this.focus()" this steht für das aktuelle Fenster.
Der Zugriff auf das Fenster kann jedoch auch aus dem aufrufenden Skript in Verbindung mit dem Fensternamen erfolgen. Dies ist beispielsweise bei einer externen URL sinnvoll. Listing 15.9: Den Fokus vergeben (focus.html)
open() <script language="JavaScript">
} //--> Hauser und Wenz
Das Gegenstück zu window.focus() ist blur(). Damit nehmen Sie einem Fenster den Fokus.
Popup unterdrücken Neuere Browser wie der Netscape Navigator 7.01 bieten dem Nutzer die Möglichkeit, Popup-Fenster zu unterdrücken. Für denselben Zweck gibt es auch – meist kostenlos erhältliche – Ergänzungen zu den wichtigsten Browsern. Im Fall des Netscape Navigators ändert der Nutzer das Verhalten unter BEARBEITEN/EINSTELLUNGEN/POPUP-FENSTER. Allerdings werden hier als Popups nur die Fenster blockiert, die im onload-Ereignis aufgerufen werden. Die per onclick aufgerufenen neuen Fenster bleiben davon unberührt. Das heißt, der böswillige Webentwickler könnte per onclick auch mehrere Fenster öffnen. Aber das sind Sie ja nicht …
476
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15 Abbildung 15.15: Popups unterdrücken
Eine ähnliche Popup-Kontrolle wie Netscape besitzen auch Mozilla und Opera. Im Opera 7 hat der Nutzer unter DATEI/VOREINSTELLUNGEN/FENSTER (engl. Version FILE/PREFERENCES/WINDOWS) sogar noch mehr Wahlmöglichkeiten: Er kann alle Popup-Fenster zurückweisen, auch solche, die per Klick aufgerufen wurden. Er kann nur die selbst angeforderten Popup-Fenster, d.h. die per Klick aufgerufenen, anzeigen. Er kann Popup-Fenster im Hintergrund öffnen lassen. Tools zur Popup-Unterdrückung arbeiten meist nach einem gemeinsamen Prinzip. Sie durchsuchen den Quellcode nach einer window.open()-Anweisung. Eine andere Vorgehensweise besteht darin, dass Sie window.open() mit eval() aus mehreren Strings zusammensetzen. Diese Vorgehensweise funktioniert bei Browsern nicht, da diese den Fensteraufruf selbst unterdrücken. Fazit Die entscheidende Frage wird zukünftig noch an Bedeutung gewinnen: Wie gehen Sie als Webentwickler mit geblockten Popups um. Hierauf gibt es zwei Antworten: Sie sollten nicht komplett auf teilweise sinnvolle Popups verzichten. Allerdings müssen Sie auf der anderen Seite Alternativlösungen bieten. Öffnet sich ein Fenster nicht, sollte der Nutzer also nicht im Regen stehen. Popups, die sich beim Anklicken öffnen, wie beispielsweise eine Sitemap, sind heute
KOMPENDIUM
JavaScript
477
Kapitel 15
Fenster noch weitgehend sicher, automatisch geladene Popups dagegen erzeugen beim Nutzer häufig bereits zwangsläufig ein merkwürdiges Gefühl, da sie mittlerweile als unseriös angesehen werden oder mit Werbung assoziiert werden.
In Popups schreiben In einem neu geöffneten Fenster können Sie ein neues Dokument oder einen externen Link laden. Alternativ lässt sich das Fenster allerdings auch komplett mit per Skript erstelltem Inhalt füllen. Im folgenden Beispiel enthält ein Text einen Begriff, der in einem PopupFenster näher erläutert werden soll. Der Begriff wird also in einen Link gepackt. Sobald der Nutzer darauf klickt, soll sich ein Fenster mit einem Beschreibungstext öffnen. In der Funktion oeffnen(), die beim Anklicken des Links aufgerufen wird, erhält zuerst die Variable fenster die Referenz auf das neu geöffnete Fenster. Die URL als erster Parameter erhält keine Angaben und es wird auch kein Fenstername vergeben. var fenster = window.open("", "", "width=300,height=200,resizable=no");
Eine Variable speichert nun den HTML-Quellcode für die neue Seite: var text = "Neues Fenster"; text += "Skriptsprache
Eine Scriptsprache führt "; text += "kleinere Programme, so genannte Skripten, aus.
"; text += "";
Die Variable wird mit document.write() in das neue Fenster geschrieben: fenster.document.write(text);
Der Optik halber ändert eine Stilanweisung auch die Hintergrundfarbe. Beachten Sie, dass sie in älteren Browsern – beispielsweise Netscape 4.x – nicht funktioniert. fenster.document.body.style.backgroundColor = "orange";
Zum Schluss schließt die document.close()-Anweisung das Schreiben in das neue Fenster. Fehlt die Anweisung, zeigen der Internet Explorer 4 und die neueren Netscape-Browser sowie Mozilla ein Wartesymbol7 als Mauszeiger, da für sie das Schreiben noch nicht abgeschlossen ist. fenster.document.close(); 7
478
je nach Betriebssystem und Cursor-Satz beispielsweise eine Sanduhr
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15
Hier der vollständige Code: open() <script language="JavaScript">
Listing 15.10: In ein neues Fenster schreiben (popup_schreiben. html)
var fenster = window.open("", "", "width=300,height=200,resizable=no"); var text = "Neues Fenster"; text += "Scriptsprache
Eine Skriptsprache führt "; text += "kleinere Programme, so genannte Skripten, aus.
"; text += ""; fenster.document.write(text); fenster.document.body.style.backgroundColor = "orange"; fenster.document.close();
} //--> JavaScript ist eine Scriptsprache. Abbildung 15.16: Das neue Fenster wird mit den Inhalten geöffnet, die im alten Fenster definiert wurden.
KOMPENDIUM
JavaScript
479
Kapitel 15
Fenster Auf älteren Browsern (z.B. Internet Explorer 4) oder langsameren Systemen kann es zu einem Fehler kommen, wenn das Fenster zu langsam geöffnet und bereits in das Fenster geschrieben wird. Um dies zu verhindern, schreiben Sie erst nach einer mit setTimeout() produzierten Zeitverzögerung in das neue Fenster:
Listing 15.11: Erst nach einer Zeitverzögerung das Dokument füllen (popup_schreiben_ timeout.html)
open() <script language="JavaScript">
} function schreiben() { var text = "Neues Fenster"; text += "Scriptsprache
Eine Scriptsprache führt "; text += "kleinere Programme, so genannte Skripten, aus.
"; text += ""; fenster.document.write(text); fenster.document.body.style.backgroundColor = "orange"; fenster.document.close(); }
//--> JavaScript ist eine Scriptsprache.
Beachten Sie, dass die Referenz auf das Fenster – hier die Variable fenster – global sein muss, also auch in der Funktion zum Schreiben zur Verfügung stehen muss.
Fenster schließen Das Gegenstück zu window.open() bildet window.close(), um ein beliebiges Browserfenster wieder zu schließen. close() gibt es seit Netscape 2 und Internet Explorer 3 in der ersten Version. Tabelle 15.8: window.close()
480
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15
In einem einfachen Beispiel wird zuerst ein neues Fenster geöffnet. var fenster = window.open("neu.html", "Fenster1", "width=300,height=200,resizable=no");
In der Datei neu.html für das neue Fenster befindet sich ein Link, der das neue Fenster schließt. Beachten Sie auch, dass das Fenster sich beim Laden automatisch selbst den Fokus gibt. Neues Fenster <script language="JavaScript">
Listing 15.12: Ein neues Fenster öffnen (fenster_schliessen. html)
Listing 15.13: Das Fenster lässt sich direkt wieder schließen (neu.html).
//--> Fenster schließen
Alternativ können Sie das Fenster natürlich auch aus der aufrufenden Datei schließen. Für diesen Fall sollten Sie allerdings überprüfen, ob das Fenster bereits erstellt wurde oder aber bereits wieder geschlossen ist, da der Browser ansonsten einen Fehler liefert. Ob ein Fenster geschlossen ist, stellen Sie mit der Eigenschaft closed fest. open() <script language="JavaScript">
Listing 15.14: Ein neues Fenster im aufrufenden Fenster schließen (fenster_schliessen 2.html)
function schliessen() { if (fenster && !fenster.closed) { fenster.close(); } }
//--> Neues Fenster
Neues Fenster wieder
KOMPENDIUM
JavaScript
481
Kapitel 15
Fenster schließen
Abbildung 15.17: Das neue Fenster aus dem Ursprungsfenster schließen
closed gibt es seit Netscape 3 und Internet Explorer 4. Tabelle 15.9: closed
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
opener In vielen Fällen ist es nicht nur interessant, das neue Fenster fernzusteuern, sondern auch, aus dem neuen Fenster auf das Ursprungsfenster zuzugreifen. Dazu dient die Eigenschaft opener des window-Objekts. Sie verweist auf das Fenster, das ein Fenster per JavaScript geöffnet hat. In der Praxis wird diese Eigenschaft vor allem für Sitemaps8 verwendet.
8
482
Eine Sitemap zeigt die Struktur einer Webseite und verlinkt zu den wichtigsten Unterpunkten.
KOMPENDIUM
JavaScript
Popups und andere neue Fenster
Kapitel 15
Netscape 2 unterstützt opener noch nicht, die späteren Browser sind jedoch damit vertraut. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 15.10: opener
Eine Sitemap sehen Sie im folgenden Beispiel. Das Beispiel besteht aus zwei Dateien: der Homepage (home.html), von der aus die Sitemap aufgerufen wird. Ist sie bereits geöffnet, kann sie über denselben Link wieder geschlossen werden.9 Dazu prüft eine Fallunterscheidung, ob das Fenster mit der Sitemap aktuell geöffnet ist. Homepage <script language="JavaScript">
Listing 15.15: Die Homepage (home.html)
if (fenster && !fenster.closed) { fenster.close(); } else { fenster = window.open("site.html", "sitemap", "width=200,height=300,resizable=no"); }
} //--> Sitemap
Die Sitemap selbst besteht aus mehreren Links. Die Links rufen jeweils im onclick-Ereignis eine Funktion auf. Diese Funktion verwenden window.opener, um auf das Hauptfenster zu verweisen und ändern dessen Adresse mit location.href. Neues Fenster <script language="JavaScript">
Zum Aufrufen der Funktion wird im Beispiel aus Listing 16.6 das onclickEreignis der Checkbox verwendet. Alternativ können Sie natürlich auch eine Schaltfläche anklicken oder den Formularversand5 verwenden. Die Eigenschaft defaultChecked überprüft, ob die Checkbox standardmäßig angeklickt ist (true), also das HTML-Attribut checked besitzt. Neben dieser Eigenschaft gibt es noch einige Eigenschaften, die ebenfalls Textfelder besitzen: type liefert beispielsweise den Typ, also checkbox, name enthält den Namen der Checkbox und value kann einen Wert enthalten, den serverseitige Skripten nutzen können. 5
Grundsätzliches zur Schaltfläche SUBMIT erfahren Sie im Abschnitt »Submit«.
KOMPENDIUM
JavaScript
503
Kapitel 16
Formulare
Abbildung 16.9: Die Checkbox wurde angewählt.
Tabelle 16.9: Weitere Eigenschaften von Checkboxen
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
In verschiedenen serverseitige Programmiersprachen werden in der Regel auch für Checkboxen (wie für Radiobuttons) gleiche Namen vergeben. Die Checkboxen stehen dann in einem Array zur Verfügung. In manchen Sprachen, beispielsweise PHP, müssen in diesem Fall nach dem Namen auch eckige Klammern erscheinen.
Radiobutton Radiobuttons sind ein wenig schwieriger zu behandeln als Checkboxen, da sie immer in Rudeln auftreten. Radiobuttons, die denselben Namen haben, bilden eine Gruppe. Aus dieser Gruppe darf per Definition nur eine der Optionen ausgewählt sein. Wenn das name-Attribut gleich ist, bleibt die Frage, wodurch die einzelnen Optionen voneinander unterschieden werden können. Eine Möglichkeit ist das value-Attribut. Jeder Radiobutton erhält einen eigenen Wert.6 value gibt es bereits in den ersten Browsern mit JavaScript-Unterstützung. Tabelle 16.10: value-Eigenschaft
6
504
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Eine Alternative wäre die Verwendung des id-Attributs. Dies ist allerdings in der Praxis weniger gebräuchlich.
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Eine der Hauptanwendungen von Radiobuttons in Formularen besteht darin, den Nutzer aus mehreren Alternativen eine auswählen zu lassen. Das Paradebeispiel – nämlich das Geschlecht des Nutzers – wird auch im folgenden Skript verwendet. Das Skript übermittelt als Parameter mit dem Schlüsselwort this die Referenz auf den soeben angeklickten Radiobutton. this spielt bei Formularen eine große Rolle, da es einfach im Ereignis an eine Funktion übergeben werden kann und Sie sich die umständliche Adressierung des Formularelements über document.Formularname.Elementname sparen. Radiobuttons <script language="JavaScript"> <select name="auswahl" onchange="ausgabe()"> Option 1 Option 2 Option 3
Die hier verwendeten und einige andere wichtige Eigenschaften für Auswahllisten können Sie der folgenden Tabelle entnehmen. Darüber hinaus finden Sie in Tabelle 16.12 eine Übersicht über die Browserkompatibilität.
KOMPENDIUM
JavaScript
507
Kapitel 16
Formulare
Abbildung 16.11: Die Warnmeldung gibt Index und Text der Option aus.
Tabelle 16.11: Wichtige Eigenschaften für Auswahllisten
508
Eigenschaft
Beschreibung
options[Index]
Kollektion (Array) aus allen Optionen einer Auswahlliste. Ein Element wird mit der Indexnummer aufgerufen. Name oder ID funktionieren nicht.
defaultSelected
Ergibt true, wenn die Option standardmäßig ausgewählt ist. Kann nur gelesen, nicht gesetzt werden. Die Einstellung wird mit dem HTML-Attribut selected im -Tag vorgenommen.
index
Der Index eines Elements. Er kann nur ausgelesen werden. Dies ist meist nicht sehr sinnvoll, da Elemente vorher mit Index angesprochen werden müssen.
selectedIndex
Der Index der ausgewählten Option. Er kann auch geändert werden. In Auswahllisten, bei denen mehrere Optionen ausgewählt werden können, enthält er den Index der ersten ausgewählten Option. Ist kein Element ausgewählt, entspricht selectedIndex -1.
size
Gibt an, wie viele Zeilen der Auswahlliste sichtbar sind. Eine einzeilige Auswahlliste heißt auch Pulldown-Menü.
text
Der Text innerhalb der -Tags. Er kann auch geändert werden.
value
Der Wert, der im value-Attribut eines -Tags angegeben wurde. Er ist auch änderbar. Der Zugriff erfolgt wie bei text über die options-Kollektion.
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
options
defaultSelected
index
selectedIndex
size text
value
Tabelle 16.12: Wichtige Eigenschaften für Auswahllisten (Browserkompatibilität)
Die drei Eigenschaften defaultSelected, text und value stehen für das <select>-Objekt9 und das -Objekt zur Verfügung. Dass dies programmiertechnisch nicht dasselbe ist, werden Sie im Abschnitt »Auswahllisten bearbeiten« sehen, in dem Methoden vorgestellt werden, die in verschiedenen Browsern unterschiedlichen Objekten zugeordnet werden. Mehrere Optionen auswählen Damit der Nutzer mehrere Optionen auswählen kann, müssen Sie das HTML-Attribut multiple in das <select>-Tag schreiben. Die gleichnamige Eigenschaft multiple erlaubt Ihnen in neueren Browsern, per JavaScript eine Auswahlliste von einer auf mehrere Optionen und zurück umzuschalten. Das folgende Skript liest alle ausgewählten Optionen einer Auswahlliste aus und bietet zusätzlich eine Schaltfläche, um multiple umzuschalten. Das Auslesen erfolgt mit einer Schleife, die mit length die Zahl der Elemente der Auswahlliste aufnimmt und über selected für jede Option prüft, ob sie ausgewählt ist (true) oder nicht (false). Auswahlliste mit mehreren Optionen <script language="JavaScript">
Listing 16.10: Eine Auswahlliste mit mehreren Optionen auslesen (auswahlliste_ multiple.html)
Zugriff über options-Kollektion
KOMPENDIUM
JavaScript
509
Kapitel 16
Formulare function mehrere() { if (document.formular.auswahl.multiple == true) { document.formular.auswahl.multiple = false; } else { document.formular.auswahl.multiple = true; } }
//--> <select name="auswahl" multiple> Option 1 Option 2 Option 3 Abbildung 16.12: Die Auswahlliste im Original
Abbildung 16.13: Ein Klick auf die Schaltfläche AUSGEBEN ruft die gleichnamige Funktion auf und gibt Index und Text der ausgewählten Optionen aus.
510
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Der Netscape Navigator 4 unterstützt multiple nicht. Sie können hier die Art der Auswahlliste an der type-Eigenschaft erkennen. Der type ist bei Mehrfachauswahl select-multiple und bei Einfachauswahl select-one.
length
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
multiple selected
Tabelle 16.13: Weitere Eigenschaften für Auswahllisten (Browserkompatibilität)
Abbildung 16.14: Ein Klick auf die Schaltfläche MEHRERE? erlaubt dem Nutzer nur noch eine Option auszuwählen.
Auswahllisten bearbeiten Das Bearbeiten von Auswahllisten ist nicht ganz so unkompliziert wie das Abfragen. Sie haben mehrere Möglichkeiten: Sie können den Text einer bestehenden Option mit der Eigenschaft text ändern. document.formular.auswahl.options[0].text = "Markt+Technik"
Sie ändern den Wert einer bestehenden Option mit value. document.formular.auswahl.options[0].value = "http://www.mut.de"
Sie löschen eine Option. Dazu setzen Sie die Option auf null. Die Zahl der Optionen, also die length-Eigenschaft der Auswahlliste, verringert sich um 1. document.formular.auswahl.options[0] = null;
KOMPENDIUM
JavaScript
511
Kapitel 16
Formulare Sie erstellen ein neues Option-Objekt und fügen es hinzu (Beispiel siehe Listing 16.11). Das Objekt erhält als Parameter den Text10 und optional einen Wert11. Ebenfalls optional ist der Standardstatus, der angibt, ob die Option standardmäßig aktiviert (selected) ist (true) oder nicht (false). Die vierte Option gibt den aktuellen Status an: aktiviert ist true, nicht aktiviert false. var obj = new Option("Text", "Wert", Standardstatus, Status); liste.options[Index] = obj;
Sie verwenden die Methoden add() und remove(), um Elemente hinzuzufügen oder zu entfernen. Option-Objekt hinzufügen und löschen Das folgende Beispiel erstellt beim Anklicken der Schaltfläche HINZUFÜGEN eine neue Option, die als Text den Wert eines Textfelds erhält. Die neue Option wird an das Ende der Auswahlliste angefügt. Eine zweite Schaltfläche dient dazu, die aktuell ausgewählte Option zu entfernen. Die Funktion weg() setzt die Option mit dem Index auf null. Listing 16.11: Ein neues OptionObjekt hinzufügen und eine Option löschen (option_objekt.html)
Einer Auswahlliste ein Objekt hinzufügen und löschen <script language="JavaScript">
//--> <select name="auswahl" size="3"> Option 1 Option 2 Option 3
10 entspricht der text-Eigenschaft 11 entspricht der value-Eigenschaft
512
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Abbildung 16.15: Eine neue Option hinzufügen (oben): Sie erscheint am Ende der Liste (unten).
Wenn Sie ein neues Objekt einer bestehenden Option zuweisen, wird diese Option ersetzt. Die folgende Fallunterscheidung wandelt die Funktion zum Hinzufügen aus Listing 16.11 so ab, dass – falls ein Objekt ausgewählt ist – das ausgewählte Objekt durch das neue Objekt ersetzt wird. Ist dies nicht der Fall, wird das neue Objekt am Ende angehängt. if (liste.selectedIndex != -1) liste.options[liste.selectedIndex] = obj; else liste.options[liste.length] = obj; }
KOMPENDIUM
JavaScript
Listing 16.12: Eine bestehende Option ersetzen (option_objekt_ ersetzen.html)
513
Kapitel 16
Formulare
Abbildung 16.16: Ein Objekt auswählen (oben) und wieder entfernen (unten)
Abbildung 16.17: Die neue Option (oben) ersetzt die ausgewählte (unten).
514
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Wollen Sie die bestehende Option nicht ersetzen, sondern die neue Option dazwischen einfügen, müssen Sie alle nachfolgenden Optionen verschieben. Dazu dient eine einfache for-Schleife. function einfuegen() { var liste = document.formular.auswahl; var obj = new Option(document.formular.eingabe.value, "Neue Option"); if (liste.selectedIndex != -1) { for (var i = liste.length; i>liste.selectedIndex;i--) { liste.options[i] = new Option(liste.options[i-1].text); } liste.options[liste.selectedIndex] = obj; } else { liste.options[liste.length] = obj; } }
Listing 16.13: Ein neues Objekt einfügen (option_objekt_ einfuegen.html)
Abbildung 16.18: Eine neue Option soll vor Option 2 eingefügt werden (oben). Unten sehen Sie das Ergebnis.
KOMPENDIUM
JavaScript
515
Kapitel 16
Formulare Das Auswählen und Entfernen von Optionen auf die in diesem Abschnitt beschriebene Methode funktioniert in allen Browsern ab Netscape 3 und Internet Explorer 4.
Tabelle 16.14: Option-Objekt:
Löschen und Einfügen von neuen Optionen
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
add() und remove() Das Einfügen von neuen Objekten ist mit dem im letzten Absatz beschriebenen Vorgehen recht arbeitsaufwändig. Daher gibt es in neueren Browsern die add(Objekt, Index)-Methode. Sie erlaubt es Ihnen, ein Objekt an einen beliebigen Index zu schieben. Die nachfolgenden Optionen werden verschoben. Zum Löschen einer Option bietet sich remove(Index) an. Auch hier ist die Angabe des Index ausreichend. Das Problem bei beiden Methoden: Für den Netscape Navigator 6 und höher sowie Mozilla gehören die Methoden zum Select-Objekt, für den Internet Explorer und Opera dagegen zum Option-Objekt oder zum SelectObjekt.12 Um auf Nummer Sicher zu gehen, sollten Sie immer eine Fallunterscheidung verwenden, wie sie in Listing 16.14 gezeigt wird. Tabelle 16.15: add() und remove() – unterschieden nach Zugehörigkeit
NS4.x NS6 zu SelectObjekt zu OptionObjekt
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel verwendet add(), um eine neue Option einzufügen und remove(), um die ausgewählte Option zu entfernen. Listing 16.14: add() und remove()
(add_remove.html)
add() und remove() <script language="JavaScript">
516
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
else liste.add(obj, liste.selectedIndex);
} else { if (liste.options.add) liste.options.add(obj); else liste.add(obj);
} } function weg() { var liste = document.formular.auswahl; if(liste.options.remove) { liste.options.remove(liste.selectedIndex); } else { liste.remove(liste.selectedIndex); }
} //--> <select name="auswahl" size="3"> Option 1 Option 2 Option 3 Option 4 Option 5
Die Wirkung dieses Beispiels gleicht Listing 16.13. Das Ergebnis sehen Sie in Abbildung 16.18. Es gäbe noch weitere Möglichkeiten, neue Optionen einzufügen. Beispielsweise ließe sich ein neues Element mit der Methode createElement() erstellen oder mit getElementById() in eine Option einfügen. Da dies allerdings nur auf neuere Browser beschränkt ist, wird diese Möglichkeit hier nicht behandelt. Auswahlliste als Navigationselement Einer der häufigsten Einsatzzwecke ist, Auswahllisten mit Links zu versehen und als Navigationselemente oder kleine Sitemaps zu verwenden. Die Methoden, die bei dieser Aufgabe angewendet werden, sind alle vergleich-
KOMPENDIUM
JavaScript
517
Kapitel 16
Formulare bar. Der einzige Unterschied liegt in der Art der Datenspeicherung. Folgende Möglichkeiten erscheinen sinnvoll: Ablegen der URLs in einem Array. Der Index der URL im Array sollte dem Index der Option entsprechen. Ablegen der URLs direkt in der Auswahlliste im value-Attribut. Weniger sinnvoll ist es, die URLs als Text der Auswahlliste zu verwenden, da sie meist entweder nichts sagend oder zu lang sind. In der Praxis ist die zweite Methode am häufigsten anzutreffen. Hier sehen Sie ein einfaches Beispiel:
Listing 16.15: Eine Auswahlliste mit Links (auswahlliste_ links.html)
Auswahlliste mit Links <script language="JavaScript">
//--> <select name="auswahl" size="3" onchange="verweis()"> Markt+Technik Hauser und Wenz Spiegel Online
Auf der CD-ROM finden Sie die erste Methode mit den URLs, die im Array gespeichert sind.13 Die Datei hat den Namen auswahlliste_links_array.html und befindet sich im Ordner code\kap16. Ihrer Fantasie sind – mal wieder – keine Grenzen gesetzt. Sie sollten noch eine Alternative einbauen, falls kein Element angeklickt wurde. Natürlich können Sie den Link auch in einem neuen Fenster öffnen oder auch relative Links verwenden. Sie sollten allerdings nicht Ihre ganze Navigation auf dieser Methode aufbauen, wenn Sie nicht sicher wissen oder anfänglich überprüfen, ob Ihre Nutzer JavaScript besitzen bzw. aktiviert haben.
13 Ein erweitertes Beispiel mit Arrays finden Sie auch im nächsten Absatz »Navigation über mehrere Ebenen«.
518
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Es ist natürlich auch möglich, den Code zum URL-Wechsel in das onchangeEreignis zu packen. Dies ist meist jedoch nicht sehr übersichtlich. Da die erste Option bei einer einzeiligen Auswahlliste (size="1") nicht von onchange berücksichtigt wird, müssten Sie hier eine Option ohne Link mit einem Text wie beispielsweise »Bitte wählen« einfügen. Navigation über mehrere Ebenen Auswahllisten lassen sich auch dazu verwenden, über mehrere Ebenen zu navigieren. Damit sind komplexere Navigationen möglich. Allerdings haben sich in der Praxis maximal zwei Ebenen bewährt, mehr sollten es nicht sein. Das folgende Beispiel verwendet eine Auswahlliste, die die Unterscheidung der Kategorie ermöglicht. Der Nutzer kann hier zwischen Verlagen oder Nachrichten wählen. Je nach Wahl wird die zweite Auswahlliste mit Verlags-Websites oder Nachrichtenportalen aus den Arrays verlage oder nachr gefüllt. Die Wahl erfolgt in der Funktion über den ausgewählten Index in der Kategorien-Auswahlliste. Die einzelnen Optionen werden in die zweite Auswahlliste mit einer for-Schleife aus dem jeweiligen Array eingelesen: function wechseln() { var kat = document.formular.kategorie; var ang = document.formular.angebot; if (kat.selectedIndex == 1) arr = verlage; else arr = nachr; for(var i in arr) { ang.options[i] = new Option(arr[i]); } }
Die Funktion für die zweite Auswahlliste funktioniert nach einem ähnlichen Prinzip. Wählt der Nutzer einen Eintrag, wird zuerst überprüft, ob ein Element ausgewählt wurde und ob die zweite Liste mehr als ein Element enthält. Ist dies der Fall, stellt eine Fallunterscheidung fest, welche Kategorie in der ersten Auswahlliste ausgewählt ist. Je nach Kategorie wird das richtige URL-Array für Verlage oder Nachrichtenportale verwendet. Die Umleitung erfolgt schließlich mit window.loction.href und der URL, deren Index mit dem in der Liste ausgewählten Eintrag übereinstimmt.
KOMPENDIUM
JavaScript
519
Kapitel 16 Listing 16.16: Zwei Auswahllisten bilden bereits eine komplette Navigation (auswahlliste_ navi.html).
Formulare function verweis() { var ang = document.formular.angebot; var kat = document.formular.kategorie; if (ang.selectedIndex != -1 && ang.length > 1) { if (kat.selectedIndex == 1) arr = v_url; else arr = n_url; window.location.href = arr[ang.selectedIndex]; } }
Hier sehen Sie den kompletten Code: Navigation mit mehreren Auswahllisten <script language="JavaScript"> 1) { if (kat.selectedIndex == 1) arr = v_url; else
520
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
arr = n_url; window.location.href = arr[ang.selectedIndex]; } }
//--> <select name="kategorie" size="1" onchange="wechseln()"> Bitte wählen Verlage Nachrichten <select name="angebot" size="1" onchange="verweis()"> Abbildung 16.19: Der Nutzer wählt die Kategorie VERLAGE (links). Daraufhin erscheinen rechts die erhältlichen Verlage. Wenn sich der Nutzer einen Verlag aussucht …
Verwenden Sie das HTML-Tag , um Auswahllisten noch übersichtlicher zu formatieren. Das Attribut label im Tag enthält eine Beschreibung der Gruppe. Es steht auch als JavaScript-Eigenschaft ab Netscape Navigator 6 und Internet Explorer 6 zur Verfügung.
Datei-Upload Der Datei-Upload dient dazu, Dateien auf den Server zu laden. Er bietet dem Nutzer also die Möglichkeit, im Dateisystem des Computers eine Datei zu suchen und diese an den Server zu übertragen. Da der Server hier im Spiel ist, erfolgt die Kontrolle normalerweise über eine serverseitige Technologie wie PHP oder ASP.NET.
KOMPENDIUM
JavaScript
521
Kapitel 16
Formulare
Abbildung 16.20: ... gelangt er auf dessen Homepage.
Die einzige wirklich interessante Einstellung in JavaScript ist das value-Attribut. Es enthält den Namen der Datei, die hochgeladen werden soll. Diese Eigenschaft kann beispielsweise in JavaScript überprüft werden, um festzustellen, ob eine Datei angehängt wurde. Listing 16.17: Überprüfen, ob beim Datei-Upload eine Datei angehängt ist (dateiupload.html)
Datei-Upload <script language="JavaScript">
//-->
522
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Abbildung 16.21: JavaScript testet und meldet, dass keine Datei angehängt wurde.
Mehr zur Vollständigkeitsüberprüfung für andere Formularelemente erfahren Sie in Kapitel 21 »Vollständigkeitsüberprüfung und reguläre Ausdrücke«.
Schaltflächen Gelegentlich – beispielsweise bei Auswahllisten als Navigationselementen14 – benötigt ein Formular keine Schaltfläche. Dies wird allerdings eher die Ausnahme sein. In den meisten Fällen muss der Nutzer nach dem Ausfüllen des Formulars eine Schaltfläche anklicken, die das Formular versendet, in eine Datenbank schreibt oder überprüft. Die nächsten Abschnitte zeigen die Funktionsweise der verschiedenen Schaltflächen: Button Das -Tag ist eine Schaltfläche, die unabhängig von einem Formular ist, also keine einschließenden -Tags benötigt. Diesen Vorteil erkaufen Sie sich damit, dass diese Art von Schaltflächen erst in neueren Browsern ab Netscape 6 und Internet Explorer 4 funktioniert. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 16.16: -Tag
Der Konqueror stellt die Schaltfläche über die gesamte Fensterbreite dar. Dies ist der optischen Wirkung natürlich nicht zuträglich. Abhilfe schafft nur die Angabe einer Breite per Stylesheet-Befehl mit width. 14 siehe Abschnitt »Bild «
KOMPENDIUM
JavaScript
523
Kapitel 16
Formulare
Abbildung 16.22: Der Konqueror zeigt die Schaltfläche zu breit an.
Heißt das, Sie sollten das -Tag meiden? In vielen Fällen kann es durchaus sinnvoll sein, da Sie darin jeden beliebigen HTML-Code (außer Formularelemente und Links) einschließen können. So lässt sich auch ein Bild auf die Schaltfläche legen. JavaScript ist die beste Möglichkeit, die Schaltfläche zum Leben zu erwecken. Denkbar sind verschiedene Ereignisse wie onmouseover oder onclick. Das folgende Beispiel setzt onclick ein, um zu zählen, wie oft der Nutzer die Schaltfläche betätigt: Listing 16.18: Eine Schaltfläche mit -Tag (button.html)
Button <script language="JavaScript">
//--> Klicken!
524
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16 Abbildung 16.23: Der Autor verwendet kostbare Zeit darauf, diese Schaltfläche achtmal anzuklicken …
Das -Tag kann auch die Funktionsweise eines Submit- oder ResetButtons annehmen. Ändern Sie dazu einfach das Attribut type auf submit oder reset. Die Standardeinstellung für type ist button. Diese muss allerdings nicht angegeben werden. Normale Schaltfläche Die normale Schaltfläche erhält ihre Funktionalität wie ebenfalls erst über JavaScript bei verschiedenen Ereignissen wie onclick und onmouseover. Da die Schaltfläche allerdings Teil des Formulars ist, können Sie darauf auch wie auf ein Formularfeld zugreifen. Also entweder mit Namen: document.Formularname.Schaltflächenname;
oder über die forms- und elements-Kollektionen. Dies benötigen Sie nicht, wenn Sie mit der Schaltfläche eine Funktion starten möchten, die sich um andere Formularelemente kümmert.15 Wollen Sie allerdings eine Eigenschaft der Schaltfläche selbst ändern, benötigen Sie den Zugriff. Im folgenden Beispiel wird die Eigenschaft value verwendet, um die Beschriftung einer Schaltfläche zu ändern, wenn der Nutzer sie anklickt. Die Beschriftung enthält, wie oft der Nutzer den Button angeklickt hat. Normale Schaltfläche <script language="JavaScript">
Listing 16.19: Die Eigenschaft einer Schaltfläche ändern (input_button.html)
15 In den letzten Abschnitten werden die normalen Schaltflächen sehr häufig so verwendet.
KOMPENDIUM
JavaScript
525
Kapitel 16
Formulare i++; document.formular.schalt.value = i + "ter Klick"; }
//--> Abbildung 16.24: Die Schaltflächenbeschriftung zeigt, wie oft der Nutzer den Button angeklickt hat.
Das onclick-Ereignis reagiert in diesem Beispiel in den Browsern zu langsam. Das heißt, der Nutzer kann mit der Maus öfter klicken, als die Funktion ausgeführt wird. In dieser Anwendung hat dies keine große Bedeutung. Wenn Sie allerdings eine Schaltfläche für ein Spiel verwenden wollen, sollten Sie diese Zeitverzögerung einkalkulieren, da sie nicht verhindert werden kann. Neben der value-Eigenschaft gibt es noch einige weitere Eigenschaften, die die folgende Tabelle zusammenfasst. Sie gelten nicht nur für die normale Schaltfläche mit type="button", sondern auch für Submit- und Reset-Buttons (siehe die folgenden beiden Abschnitte), nicht aber für -Schaltflächen. Tabelle 16.17: Wichtige Eigenschaften für Schaltflächen
526
Eigenschaft
Beschreibung
defaultValue
Standardwert und damit Standardbeschriftung einer Schaltfläche. Erscheint immer, wenn ein Formular mit einem Reset-Button zurückgesetzt wird. Kann auch geändert werden.
name
Der Name einer Schaltfläche im Code. Er kann geändert werden.
size
Die Breite einer Schaltfläche in Zeichen. Auch diese Eigenschaft kann per JavaScript geändert werden.
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Eigenschaft
Beschreibung
type
Art des Buttons. Kann die Ausprägungen button, submit oder reset annehmen. Kann nur gelesen werden.
value
Der Wert, der gleichzeitig die Beschriftung der Schaltfläche ist. Er kann ebenfalls geändert werden. Browser vor Internet Explorer 4, Netscape Navigator 6 und Opera 7 passen allerdings die Größe der Schaltfläche nicht automatisch an die neue Beschriftung an. Im Bild sehen Sie Netscape 4.78 beim 107. Klick:
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
defaultValue
name
size
type
value
Tabelle 16.18: Wichtige Eigenschaften für Schaltflächen (Browserkompatibilität)
Submit Der Submit-Button () hat zwar die gleichen Eigenschaften wie eine normale Schaltfläche, kann allerdings auch ohne JavaScript eine Handlung vornehmen. Er versendet das Formular.16
16 Da Browser tolerant sind, kann – oder besser sollte – ein Formular nur einen Submit-Button besitzen.
KOMPENDIUM
JavaScript
527
Kapitel 16
Formulare Die Informationen, die zum Versand benötigt werden, stehen als HTMLAttribute im -Tag: method – steht für die Versandmethode. action – enthält die Adresse, an die versendet wird. Hier wird auch unterschieden, ob der Versand an ein serverseitiges Skript oder per E-Mail erfolgt.
In Kapitel 16.3 »Formular versenden …« zeigen wir Ihnen die verschiedenen Versandmethoden, Versandarten und den Versand per JavaScript. Neben der Möglichkeit des Versands gibt es allerdings noch ein Ereignis, das eintritt, wenn der Nutzer den Submit-Button anklickt. Dieses Ereignis heißt onsubmit und steht ebenfalls im -Tag. Dort muss es true zurückliefern, damit das Formular versendet wird.17 Tabelle 16.19: onsubmit
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
onsubmit wird in der Praxis dazu verwendet, zu überprüfen, ob das Formular
vollständig ausgefüllt wurde oder ob der Nutzer es tatsächlich abschicken möchte.18 Das folgende Beispiel fragt beim Nutzer noch einmal mit einem Bestätigungsdialog (window.conform) nach, ob die Daten übertragen werden sollen. Die Übertragung erfolgt dann an ein serverseitiges Skript (im action-Attribut): Listing 16.20: Vor der Weiterleitung nachfragen (input_submit.html)
Versand überprüfen <script language="JavaScript">
//-->
17 Diese Rückgabe ähnelt der, die für das Schreiben in die Statusleiste beim onmouseover- bzw. onmouseout-Ereignis notwendig ist (siehe Kapitel 14.4 »Statusleiste«). 18 Die Vollständigkeitsüberprüfung finden Sie in Kapitel 21 »Vollständigkeitsüberprüfung und reguläre Ausdrücke«.
528
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Abbildung 16.25: Vor der Übertragung wird der Nutzer gefragt.
Mit können Sie auch eine Grafik zur VERSENDEN-Schaltfläche machen. Für den JavaScript-Programmierer ändert sich dadurch nichts. Reset Die Reset-Schaltfläche setzt alle Formularelemente auf die Standardwerte zurück. Auch hier ist zuerst kein JavaScript erforderlich. Allerdings kann es sinnvoll sein, nachzufragen, ob der Nutzer seine Formularwerte tatsächlich vollständig löschen möchte. Hierfür gibt es das Ereignis onreset im Tag. Es erwartet wie onsubmit eine Rückgabe von true. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 16.20: onreset
Das folgende Beispiel zeigt eine Überprüfung, bevor das Formular geleert wird: Reset überprüfen <script language="JavaScript">
KOMPENDIUM
JavaScript
Listing 16.21: Das Leeren des Formulars überprüfen (input_reset.html)
529
Kapitel 16
Formulare //-->
Abbildung 16.26: Der Nutzer muss bestätigen, ob er das Formular leeren will …
Abbildung 16.27: … und das Textfeld wird dann auf den Standardwert zurückgesetzt.
Trotz Überprüfung sind Reset-Schaltflächen nicht ganz ungefährlich, insbesondere bei längeren Formularen. Sie sollten auf jeden Fall die Reset-Schaltfläche optisch und lokal weit genug entfernt von der Submit-Schaltfläche positionieren (also anders als in unserem einfachen Beispiel ).
530
KOMPENDIUM
JavaScript
Formularelemente
Kapitel 16
Mit der Methode reset() des form-Objekts19 setzen Sie das Formular mittels JavaScript zurück: document.formular.reset();
Allerdings sollten Sie damit vorsichtig umgehen, um nicht das Formular zu löschen, ohne dass der Nutzer den Grund nachvollziehen kann.
fieldset, legend Die beiden Tags und bilden zusammen die Möglichkeit, ein Formular in mehrere Bereiche aufzuteilen, die jeweils optisch in einem Kasten liegen. Die einzige sinnvolle JavaScript-Eigenschaft für diese Elemente ist align, die die Ausrichtung enthält. Sie entspricht dem HTML-Attribut align. Beachten Sie, dass der Rahmen des über die gesamte Fensterbreite verläuft, wenn Sie nicht per Stylesheet-Angabe eine feste Breite vergeben. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
align
Ein Beispiel finden Sie auf der CD-ROM fieldset_legend.html im Ordner code\kap16.
unter
Tabelle 16.21: , und die zugehörige Eigenschaft align
dem
Namen
Den Text im -Tag können Sie beispielsweise mit innerHTML und Zugriff über getElementById() ändern.
label Das -Tag verbindet mit dem HTML-Attribut for die Beschreibung für ein Formularelement mit dem Element selbst. Bei Radiobuttons oder Checkboxen hat dies den Vorteil, dass ein Klick auf die Beschreibung auch automatisch das Kästchen aktiviert. Aus Sicht des JavaScripters gibt es dafür nur eine Eigenschaft: htmlFor, mit der Sie die Verbindung der Beschriftung zu einem beliebigen Formularelement herstellen können. Als Wert muss nur die ID (nicht der Name!) des Formularelements übergeben werden. 19 Dieses Objekt gehört zum -Tag. Die Methode ist in allen neueren Browsern enthalten.
KOMPENDIUM
JavaScript
531
Kapitel 16
Formulare
Abbildung 16.28: Ein Anklicken der Beschreibung aktiviert den zugehörigen Radiobutton20.
Tabelle 16.22:
20
NS4.x NS6
und die
zugehörige Eigenschaft htmlFor
NS7
IE4 IE5
IE5.5 IE6
O7
M1
htmlFor
K3
Browser, die das Tag nicht unterstützen, ignorieren es und stellen nur den Beschreibungstext neben dem Formularelement dar.
16.3
Formular versenden …
Mit einem Formular muss irgendetwas geschehen. Grundsätzlich haben Sie folgende Möglichkeiten: Das Formular an ein serverseitiges Skript übergeben. Ein Beispiel und nähere Informationen dazu erhalten Sie im Abschnitt »… an serverseitiges Skript«. Clientseitiges JavaScript erledigt hier häufig noch vor dem Versand die Vollständigkeitsüberprüfung (siehe Kapitel 21 »Vollständigkeitsüberprüfung und reguläre Ausdrücke«). Das Formular direkt per E-Mail versenden. Nähere Informationen erhalten Sie im Abschnitt »… per E-Mail«. Das Formular mit der JavaScript-Methode submit() versenden. Hierzu finden Sie mehr im Abschnitt »… per Methode«. Die Formularelemente in ein Cookie speichern und später per JavaScript wieder auslesen. So lässt sich ein Warenkorb mit JavaScript realisieren. Alternativ können Sie die Formularelemente in ein verstecktes Textfeld in einen unsichtbaren Frame speichern. Beide Methoden lernen Sie in Kapitel 17 »Cookies« kennen.
20 Das Beispiel finden Sie auf der CD-ROM unter dem Namen label.html im Ordner code\kap16.
532
KOMPENDIUM
JavaScript
Formular versenden …
Kapitel 16
… an serverseitiges Skript Serverseitigen Skripte dienen meist dazu, Formularinhalte auszuwerten, in Datenbanken zu schreiben oder per E-Mail zu verschicken. Um dies zu ermöglichen, benötigen Sie natürlich eine beliebige serverseitige Programmiersprache auf Ihrem Webserver. Im Formular selbst müssen Sie außerdem einige Einstellungen vornehmen: Die erste Wahl gilt der Versandmethode (method-Attribut des Tags). – GET verschickt die Daten nach einem Fragezeichen (?) an die URL angehängt. Die Namen der Formularelemente (name) und die Werte (value) werden paarweise durch kaufmännische Und (&) getrennt hintereinander gehängt. GET hat den Nachteil, dass die Zahl der Zeichen je nach Browser bzw. Webserver beschränkt ist. Spätestens bei 2.000 Zeichen ist Schluss. Außerdem wird die per GET modifizierte URL im Browser abgelegt, ist also unsicher. – POST sendet die Daten im HTTP-Header, also im Kopf des Webprotokolls HTTP (HyperText Transfer Protocol). Die Formatierung entspricht der bei GET mit Name-Werte-Paaren, die durch kaufmännische Und voneinander getrennt sind. Die Funktionen escape() und unescape() wandeln Strings in URLs um bzw. wieder zurück. Diese und einige neuere Funktionen finden Sie in Kapitel 5.3 im Abschnitt »URLs« erläutert. Als Nächstes geben Sie unter action das serverseitige Skript an. Dies kann als absolute URL oder relativ erfolgen. Beim Versand an den Server schaltet sich JavaScript im Ereignis onsubmit ein, um beispielsweise eine Vollständigkeitsüberprüfung durchzuführen oder eine Nachfrage abzusetzen. Listing 16.20 zeigt ein Beispiel für den serverseitigen Versand mit JavaScript-Nachfrage.
… per E-Mail Formulare können per E-Mail verschickt werden, indem Sie im action-Attribut mit mailto: eine E-Mail-Adresse angeben.
Die obige Zeile versendet das Formular an die E-Mail-Adresse des Autors. Zusätzlich haben Sie die Möglichkeit, einen Betreff anzugeben:
KOMPENDIUM
JavaScript
533
Kapitel 16
Formulare Der Betreff muss in URL-Kodierung angegeben sein.21 Mit dem Attribut enctype geben Sie zusätzlich die Art der versendeten Daten an. text/plain steht beispielsweise für puren Text. Wird dieses Attribut weggelassen, erfolgt der Versand als Attachment in URL-kodierter Form.
Beim Empfänger kommt die Mail als Name und Werte-Paar mit allen Formularelementen an. Hat das Formular nur ein Textfeld mit Namen eingabe und der Nutzer gibt test ein, erscheint also: eingabe=test
in der Mail. Bis hierher wirkt das hier geschilderte Verfahren – das häufig auch mailtoVerfahren genannt wird – wie der perfekte Weg, um Formulare zu mailen. Leider ist das nicht so. Folgende Probleme trüben das Bild: Der Internet Explorer 3 unterstützt den Befehl nicht. Das ist aufgrund des verschwindend geringen Marktanteils allerdings nicht allzu beunruhigend. Der zweite Nachteil wirkt schwerer: Den Versand erledigt nicht der Browser selbst. Er benötigt vielmehr ein E-Mail-Programm, das er zuerst aufrufen muss. Die schlechte Nachricht: Verschiedene E-MailProgramme verhalten sich sehr unterschiedlich. Manche übernehmen in Verbindung mit bestimmten Browsern den Betreff oder gar die Empfängeradresse nicht korrekt. Viele Nutzer wollen außerdem lieber von Ihren Freemail-Accounts eine E-Mail an Firmen schreiben, haben diese aber beispielsweise nicht als Versandadresse in den Mailprogrammen eingegeben. Abbildung 16.29: Auch wenn der Versand funktioniert, erhält der Nutzer vorher Warnmeldungen, die er bestätigen muss.
21 siehe Kapitel 5.3 im Abschnitt »URLs«
534
KOMPENDIUM
JavaScript
Formular versenden …
Kapitel 16
Unter dem Strich bleibt, dass der Versand mit mailto: auf einem nicht vernachlässigbaren Teil der Rechner (sicherlich 20%) Schwierigkeiten bereitet. Daher werden in der Praxis meist serverseitige Skripten zum Versand von Formularen verwendet. Die mailto-Methode gilt dagegen als eher unprofessionell und eignet sich maximal für kleinere, privat betriebene Websites.
… per Methode Mit der Methode submit() können Sie ein Formular per JavaScript übertragen. Damit lässt sich zum einen jedes beliebige anklickbare HTML-Element für den Versand verwenden und zum anderen können Sie bei einer Überprüfung selbst steuern, wann das Formular versendet wird und sind nicht mehr darauf beschränkt, beim Ereignis onsubmit true zurückzuliefern. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 16.23: Die Methode submit() des form-Objekts
Im folgenden Beispiel wird ein Formular versendet, wenn der Nutzer in das Textfeld »Sesam« eingibt. Dies ist natürlich kein guter Passwortschutz, da der gewünschte Text im Quellcode steht. Es illustriert allerdings die Verwendung von submit(): Versand per Methode <script language="JavaScript">
Listing 16.22: Per Methode versenden (versand_methode. html)
//-->
KOMPENDIUM
JavaScript
535
Kapitel 16
Formulare
Abbildung 16.30: Nur das richtige Wort erlaubt den Versand.
Anweisungen direkt nach der submit()-Methode brechen die Übertragung ab. Das heißt, beispielsweise eine Umleitung auf eine Seite, auf der Sie sich für die E-Mail bedanken, ist auf diese einfache Art nicht möglich. Der Einsatz von setTimeout() ist hier sehr unsicher, da nicht klar ist, wie lange die Übermittlung dauern wird.
536
KOMPENDIUM
JavaScript
17
Cookies
Der Begriff Cookies ist älter als das World Wide Web. Bereits vor der Erfindung des HyperText-Prinzips durch Tim Berners-Lee und seine Arbeitsgruppe am CERN geisterten die Begriffe Cookie und MagicCookie durch die IT-Landschaft. Damals bezeichnete ein Cookie einen kleinen Datenblock, der meist zur Identifikation oder für Zugriffsrechte diente und durchaus auch im Hacker-Bereich gebräuchlich war. Mit dieser ursprünglichen Bedeutung haben Cookies im Web heute kaum mehr etwas zu tun. Dort ist ein Cookie eine kleine Textdatei bzw. ein Textfragement, das der Browser auf dem Rechner des Nutzers anlegt. Das heißt, der Browser hat die Kontrolle über die Datei. Der Inhalt kann allerdings mit einer Skriptsprache geändert werden. Dazu ist es wichtig, zu verstehen, warum Cookies eingeführt wurden. Das Webprotokoll HTTP dient zur Übermittlung der notwendigen Daten einer Webseite. Es unterliegt allerdings einer Beschränkung: Es ist ein statusloses Protokoll. Statuslos bedeutet, das Protokoll hat kein Gedächtnis, weiß also nicht, ob es Daten bereits einmal geschickt hat und es kann auch nicht zur Identifizierung des Nutzers herangezogen werden. An dieser Stelle kommen Cookies ins Spiel. Mit einer Skriptsprache kann der Webprogrammierer Informationen in das Cookie schreiben. Diese Informationen müssen aus reinem Text bestehen, da es sich um eine Textdatei handelt. Diese Informationen stehen dem Programmierer nun auch auf anderen Webseiten (derselben Website) zur Verfügung. Mit einer serverseitigen Skriptsprache funktioniert dies folgendermaßen: 1.
Der Browser schickt per HTTP die vorhandenen Cookies des Servers.1
2.
Mit der serverseitigen Skriptsprache können Sie ein neues Cookie setzen oder bestehende ändern und löschen.
3.
Die Änderungen werden per HTTP an den Browser geschickt.
1
Der Server erhält nur Cookies, die er selbst gesetzt hat. Damit wird das Ausspionieren des Nutzers verhindert (siehe Kapitel 17.1 im Abschnitt »Sicherheit«).
KOMPENDIUM
JavaScript
537
Kapitel 17
Cookies JavaScript erlaubt als clientseitige Skriptsprache ebenfalls den Zugriff auf Cookies. So können Sie häufig anfallende Aufgaben im Web – wie einen Login oder den Transport von Werten über mehrere Seiten – auch mit JavaScript bewältigen.
17.1
Geschichte
Bevor Sie die ersten Code-Zeilen in JavaScript zu sehen bekommen, finden Sie hier wichtige Details zur Geschichte, den Standards und insbesondere der Sicherheitsdiskussion rund um Cookies.2 Ins Leben gerufen wurden die Cookies von Netscape. Dementsprechend entstand die erste offizielle Dokumentation, die Sie heute noch unter http:// www.netscape.com/newsref/std/cookie_spec.html finden können. Diese Spezifikation ist allerdings nie ein offizieller Standard geworden. Andere Browser haben sie vielmehr stillschweigend übernommen. Cookies werden also von allen relevanten Browsern unterstützt. Tabelle 17.1: Cookies und ihr JavaScript-Zugriff
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Die Cookie-Spezifikation hat mittlerweile die IETF (Internet Engineering Task Force) übernommen. Sie finden den offiziellen Standard unter http:// www.ietf.org/rfc/rfc2965.txt.
Beschränkungen Die Spezifikationen führen zu einigen Beschränkungen für Cookies, die in der Praxis von den meisten Browsern eingehalten werden und die dafür sorgen, dass mit Cookies kein Missbrauch betrieben werden kann: Ein Cookie darf nur 4 Kbyte groß sein. Dies entspricht 4.096 Byte und – da ein Byte einem ASCII-Zeichen entspricht – auch 4.096 ASCII-Zeichen. Ein Browser lässt nicht mehr als 300 Cookies zu. Sobald mehr Cookies vorhanden sind, werden die ältesten automatisch gelöscht.3
2 3
538
Ursprünglich angeheizt wurde diese Diskussion durch einen Artikel in einem amerikanischen Computermagazin, der Cookies verteufelt hat. Dies ist eine einfache Form des First-In/First-Out-Prinzips.
KOMPENDIUM
JavaScript
Geschichte
Kapitel 17
Nur die Domain, die ein Cookie gesetzt hat, darf es auslesen. Daher darf www.spiegel.de keine Cookies von www.focus.de lesen.4 Eine Domain oder ein Webserver darf maximal 20 Cookies setzen. Auch hier gilt das First-In/First-Out-Prinzip. Die ältesten Cookies werden also zuerst gelöscht. Cookies können an den Pfad gebunden werden, aus dem sie gesetzt wurden. Ist kein Pfad gesetzt, ist das Cookie für alle Pfade der Domain verfügbar. Als Alternative kann ein Pfad angegeben werden, aus dem eine Cookie ausgelesen wird. Der Originalpfad darf das Cookie dann allerdings weder ändern noch auslesen. Ein Beispiel wäre ein Cookie, das von www.hauser-wenz.de mit dem Pfad support gesetzt wurde. Es kann von www.hauser-wenz.de/publikationen nicht ausgelesen werden.
Sicherheit Bei den genannten5 Beschränkungen stellt sich die Frage, welches Sicherheitsproblem eigentlich bei Cookies besteht? Dass Cookies Viren einschleusen könnten oder böse Dateien enthalten, wird dadurch ausgeschlossen, dass der Browser sie kontrolliert und es sich wirklich nur um reine Textdateien handelt. Das Problem liegt eher im Bereich des Datenschutzes und insbesondere bei den Third Party Cookies6. Die ersten beiden Parteien sind der Nutzer und der Anbieter der Website, die der Nutzer aufruft. Meist hat der WebsiteAnbieter allerdings Werbebanner und als Partner einen Vermarkter. Dieser Vermarkter kann nun – von seinem Server aus – beim Nutzer ein Cookie setzen. Wenn ein Vermarkter genügend Partner hat, findet er über eine andere Webseite, die der Nutzer dann ansurft, diesen Nutzer wieder, da das Cookie vom Server des Vermarkters gesetzt wurde. Daraus ergibt sich – schrittweise – ein Abbild des Surfverhaltens. Auch wenn die Vermarkter damit noch keine persönlichen Informationen über den Nutzer erhält, da seine Identität nicht über das Cookie herausgefiltert werden kann, ist dies dennoch nicht unbedenklich. Die Browserhersteller haben größtenteils darauf reagiert und erlauben dem Nutzer, Cookies von Drittanbietern gesondert zu sperren.
4 5 6
Es gab eine Sicherheitslücke im Internet Explorer 5, die dies außer Kraft setzen konnte. Sie wurde jedoch schnell wieder geschlossen. Interessante und teilweise tendenziöse Artikel zum Thema finden Sie beispielsweise unter http://www.cookiecentral.com. Eine Eindeutschung ergibt in etwa: Cookies einer dritten Partei oder Cookies von Drittanbietern.
KOMPENDIUM
JavaScript
539
Kapitel 17
Cookies
Abbildung 17.1: Im Internet Explorer können Sie unter EXTRAS/INTERNETOPTIONEN auf der Registerkarte DATENSCHUTZ/ERWEITERT Cookies von Drittanbietern sperren.
Für den Webprogrammierer ist die Sicherheitsdiskussion daher von Bedeutung, da er damit rechnen muss, das einige Nutzer Cookies abschalten oder zumindest einzeln manuell bestätigen und nur Cookies akzeptieren, wenn sie von der Notwendigkeit und der Seriosität einer Website überzeugt sind. In Kapitel 17.3 »Cookietest« zeigen wir Ihnen, wie Sie feststellen können, ob ein Browser Cookies unterstützt. Sie sollten den Nutzer aber darauf hinweisen, dass und zu welchem Zweck Sie Cookies verwenden. Insbesondere bei Shop-Anwendungen, wo Cookies oft unumgänglich sind, sollten Sie das Thema offensiv angehen und Ihren Kunden reinen Wein einschenken.
Cookies im Browser Ein Webprogrammierer sollte den Spuren seiner Cookies auch im Browser folgen können, um die Anwendungen gut testen zu können. Daher finden Sie in diesem Abschnitt Informationen, wo die wichtigsten Browser Cookies speichern und wie sie eingesetzt werden können. Internet Explorer Der Internet Explorer legt ein eigenes Verzeichnis für die Cookies an. Dort werden die Cookies jedoch erst nach dem Ende der Browsersitzung, also wenn der Browser geschlossen wurde, gespeichert. Davor sind die Cookies nur im Hauptspeicher vorhanden. In älteren Windows-Versionen ist dieses Verzeichnis WINDOWS/COOKIES oder WINNT/COOKIES. Unter Windows 2000 und XP befinden sich die Cookies im Verzeichnis DOKUMENTE UND EINSTELLUNGEN/[NUTZERNAME]/ COOKIES. Jedes einzelne Cookie ist eine .txt-Datei.
540
KOMPENDIUM
JavaScript
Geschichte
Kapitel 17 Abbildung 17.2: Ein Cookie von Amazon
Die Sicherheitseinstellungen im Internet Explorer sind recht differenziert. Als Programmierer sollten Sie nie vergessen, dass der Nutzer Cookies sehr exakt steuern kann. Sie finden die Einstellungen im Menü EXTRAS/INTERNETOPTIONEN. Dort lassen sich unter ALLGEMEIN die COOKIES LÖSCHEN. Auf der Registerkarte DATENSCHUTZ kann die Cookie-Verwaltung sehr detailliert eingestellt werden. Das Sicherheitslevel lässt sich per Schieberegler steuern. Unter ERWEITERT hat der Nutzer die Möglichkeit, sämtliche Parameter einzeln einzustellen. Auch für einzelne Websites lassen sich Cookie-Einstellungen vornehmen. Die meisten Nutzer nehmen diese Einstellungen jedoch nicht vor oder kennen Sie nicht. Daher haben viele Nutzer die Einstellung MITTEL, die die Standardeinstellung ist. Wenn Sie im Internet Explorer Cookies ausschalten, also das höchste Sicherheitsniveau wählen, können Sie immer noch aus einer lokalen Datei Cookies anlegen. Netscape Navigator und Mozilla Der Netscape Navigator speichert Cookies in der Datei cookies.txt. Beim Mac heißt die Datei allerdings MagicCookie. In neueren Netscape-Versionen ab 6 steht ein eigener COOKIE-MANAGER zur Verfügung. Die Einstellungen für Cookies finden Sie unter BEARBEITEN/EINSTELLUNGEN. Im Register RIVATSPHÄRE & SICHERHEIT enthält der Eintrag COOKIES die verschiedensten Einstellungen. Durch Anklicken des Menüpunkts GESPEICHERTE COOKIES VERWALTEN öffnet sich der COOKIE-MANAGER, der es Ihnen ermöglicht, einzelne oder alle Cookies zu löschen. In Kapitel 22 »JavaScript und Sicherheit« erfahren Sie mehr zu den Privatsphärenstufen und wie Sie in JavaScript damit umgehen. Opera Opera legt die Cookies in einer .dat-Datei ab, die je nach Opera-Version und Betriebssystem unterschiedlich benannt ist. Mögliche Namen sind cookie.dat und cookie4.dat. Die .dat-Datei benötigt zum Bearbeiten einen eigenen Editor. Glücklicherweise stellt Opera bzw. Josef Segur den Opera File Explorer zur Verfügung, der diese Datei öffnen und ändern kann. Sie finden ihn unter http://www.opera. com oder direkt unter http://www.users.westelcom.com/jsegur/.
KOMPENDIUM
JavaScript
541
Kapitel 17
Cookies In Opera stellt der Nutzer die Sicherheitseinstellungen für Cookies unter DATEI/EINSTELLUNGEN/PRIVATSPHÄRE ein.7 Konqueror Im Konqueror sind die benötigten Sicherheitseinstellungen für Cookies unter EINSTELLUNGEN/KONQUEROR EINRICHTEN zu finden. Ein hübscher Kuchen neben dem Eintrag COOKIES weist den Weg. Auf der Registerkarte VERWALTUNG können Sie hier auch die bestehenden Cookies ändern.
17.2
Mit Cookies arbeiten
Für Cookies gibt es in JavaScript ein eigenes Objekt namens cookie8. Es ist ein Unterobjekt von document und steuert alle Cookies, die die Seite setzt oder ausliest.
Setzen und auslesen Ein Cookie ist schnell gesetzt. Weisen Sie document.cookie einfach ein Cookie als Wert zu. Die Syntax sieht wie folgt aus: document.cookie = "Cookiename=Wert";
Auf den Cookienamen folgt der Wert. Natürlich sind für ein Cookie auch weitere Angaben möglich, die Sie in den folgenden Abschnitten kennen lernen werden. Um das Cookie wieder auszulesen, müssen Sie erneut auf document.cookie zugreifen. Der Wert des Cookies muss allerdings immer in URL-kodierter Form vorliegen. Am einfachsten geschieht die Umwandlung mit der Funktion escape(). Für die Rückumwandlung steht unescape() zur Verfügung.9 Im folgenden Beispiel schreibt der Nutzer einen Text in ein Textfeld. Dieser Text wird beim Anklicken der Schaltfläche COOKIE SETZEN in einem Cookie mit dem Namen cookie1 abgelegt, nachdem er zuvor in URL-Codierung umgewandelt wurde. Klickt der Nutzer anschließend auf die Schaltfläche COOKIE AUSLESEN, wird das Cookie wieder ausgelesen und mit unescape() in den ursprünglichen Zustand umgewandelt.
7 8 9
542
oder in der englischen Version FILE/PREFERENCES/PRIVACY Beachten Sie, dass im Gegensatz zu vielen Kollektionen wie beispielsweise window.frames[] oder document.forms[] document.cookie im Singular verwendet wird. Diese Funktionen finden Sie in Kapitel 5.3 im Abschnitt »URLs«.
KOMPENDIUM
JavaScript
Mit Cookies arbeiten
Kapitel 17
Cookies <script language="JavaScript"> CSS wechseln
Eigenschaft | Beschreibung |
disabled | Deaktiviert ein Stylesheet. |
Stylesheet wechseln Abbildung 19.6: Ein Anklicken der Schaltfläche wechselt …
Abbildung 19.7: … das aktive Stylesheet.
Die Eigenschaft disabled gibt es auch für <style>-Element-Objekte, wenn Sie darauf beispielsweise mit getElementById() zugreifen. Wesentlich gebräuchlicher ist allerdings der Zugriff über die styleSheets-Kollektion, da sie auch mit eingebundene Stylesheets enthält.
592
KOMPENDIUM
JavaScript
styleSheets-Kollektion und Regeln
Kapitel 19
Weitere Methoden Neben disabled gibt es einige alternative Methoden, die allerdings alle einen Haken haben: Für ein styleSheet-Objekt gibt es die Eigenschaft href, die die URL des Stylesheets enthält. Da diese Eigenschaft allerdings in den meisten Browsern mit Ausnahme des Internet Explorers ab Version 4 unter Windows (nicht beim Mac) nicht gesetzt werden kann, sollte sie in der Praxis nicht zum Einsatz kommen. Die Methode addImport(URL) des styleSheet-Objekts erlaubt die Angabe eines externen Stylesheets, das importiert werden soll. Die zugehörige – und nur lesbare – Eigenschaft imports enthält alle importierten styleSheet-Objekte als Array.13 Diese Methode ist allerdings auf den Internet Explorer ab Version 4 beschränkt. Die Methode createStyleSheet(URL) erzeugt ein neues styleSheet-Objekt, das auch direkt angewendet wird. Sie funktioniert nur im Internet Explorer ab Version 4.14 Das neue styleSheet-Objekt ist sofort Teil der styleSheets-Kollektion, also des DOM, und kann – auch wenn es leer erstellt wurde – mit anderen Methoden wie beispielsweise addRule()15 gefüllt werden. Da die hier vorgestellten Methoden auf einige wenige Browser oder Plattformen beschränkt sind, haben sie in der Praxis wenig Einsatzberechtigung.
19.4
styleSheets-Kollektion und Regeln
Die styleSheets-Kollektion16 hat noch mehr zu bieten, außer dem Wechsel von Stylesheets (siehe voriger Abschnitt). Ein styleSheet-Objekt aus der Kollektion enthält mehrere Stil-Befehle oder auch -Regeln. Diese Regeln wiederum sind ebenfalls Objekte und in einer eigenen Kollektion versammelt.
Regeln Haben Sie es bemerkt? Im letzten Abschnitt war der Name der Kollektion mit Regeln nicht zu finden. Dies ist keine Unterlassungssünde, sondern den unterschiedlichen Implementationen in den Browsern zu verdanken. In den verschiedenen Browsern haben die Kollektionen daher auch unterschiedliche Namen: 13 Formal-logisch ist jedes importierte Objekt wiederum ein styleSheet-Objekt und unterstützt auch die zugehörigen Eigenschaften wie disabled oder href. 14 nicht im IE 4 für Mac 15 siehe Kapitel 18.4, Abschnitt »JavaScript-Zugriff« 16 Der Name styleSheet-Objekt ist übrigens nicht vollständig regelkonform. Eigentlich müsste das Objekt CSSStyleSheet-Objekt heißen.
KOMPENDIUM
JavaScript
593
Kapitel 19
CSS und JavaScript cssRules – ist die Kollektion in Netscape, Mozilla und Konqueror. rules – heißt sie im Internet Explorer. Einzige Ausnahme ist der Inter-
net Explorer 5 beim Macintosh, denn er unterstützt beide Namen für die Kollektion. Tabelle 19.5: Regelkollektionen
NS4.x NS6 cssRules
NS7
rules a.
IE4 IE5
IE5.5 IE6
O7
()a
M1
K3
beim Mac ab Version 5
Der Zugriff erfolgt bei beiden direkt über den Index. Jede Regel (Block mit optionalem Tag, Klasse und den Stil-Befehlen in geschweiften Klammern) erhält eine Indexnummer, beginnend bei 0. Die erste Regel des ersten styleSheet-Objektes wird also wie folgt angesprochen: document.styleSheets[0].cssRules[0];
oder im Internet Explorer document.styleSheets[0].rules[0];
Setzen können Sie einen Stil-Befehl mit dem style-Objekt document.styleSheets[0].cssRules[0].style.color = "green";
bzw. document.styleSheets[0].rules[0].style.color = "green";
Die unterschiedlichen Namen der Kollektion zwingen den Programmierer in der Praxis dazu, eine Fallunterscheidung zu schreiben. Dazu sind, wie in Kapitel 12 »Browserunterscheidung« nachzulesen, verschiedene Ansätze möglich. Im folgenden Beispiel kommt document.all zum Einsatz, um die Internet Explorer herauszufiltern. Das Skript ändert die Schriftart in den zwei Regeln für den Körper der HTML-Seite (body) und für Tabellenzellen (td). Die neue Schriftart kann der Nutzer in ein Textfeld eingeben. Auf eine Überprüfung der korrekten Eingabe verzichtet das Skript, damit der Code nicht zu umfangreich wird. Hier der komplette Code.
594
KOMPENDIUM
JavaScript
styleSheets-Kollektion und Regeln Regeln <style type="text/css"> body {font-family:Arial;background-color:red} td {font-family:Arial;color:white}
Kapitel 19 Listing 19.6: Mit der Regelkollektion Browser-übergreifend arbeiten (regeln.html)
.tabueb {font-weight:bold} <script language="JavaScript">
//--> CSS wechseln
Eigenschaft | Beschreibung |
disabled | Deaktiviert ein Stylesheet. |
Weitere Eigenschaften und Methoden Das styleSheet-Objekt hat noch weitere Eigenschaften und Methoden, die gelegentlich zum Einsatz kommen. Die folgende Tabelle gibt einen Überblick über ausgewählte Eigenschaften des styleSheet-Objekts.
KOMPENDIUM
JavaScript
595
Kapitel 19
CSS und JavaScript
Abbildung 19.8: Der Nutzer tippt die gewünschte Schriftart ein, klickt auf die Schaltfläche …
Abbildung 19.9: … und die Schrift wird über die Regelkollektionen geändert.
Tabelle 19.6: Einige weitere Eigenschaften des styleSheetObjekts
596
Eigenschaft
Beschreibung
cssText
String mit den Stylesheet-Regeln. Nur ab Internet Explorer 5.
media
Enthält und erlaubt das Setzen eines bestimmten Medientyps für ein Stylesheet. Dies entspricht dem HTML-Attribut media.
KOMPENDIUM
JavaScript
styleSheets-Kollektion und Regeln
Kapitel 19
Eigenschaft
Beschreibung
ownerNode
Alle drei Eigenschaften enthalten eine Referenz auf den Dokumentknoten des styleSheet-Objekts. Dies ist meist das <style>- oder -Element. ownerNode ist die Netscape Variante ab Version 6. owningElement die Internet ExplorerVariante ab Version 4 und owningNode die (falsche) Benennung im Internet Explorer 5 für den Mac.
owningElement owningNode
parentStyleSheet
Referenz auf das styleSheet-Objekt, das ein importiertes Stylesheet aufnimmt. Bei per @import eingebundenen Stylesheets ist das Ergebnis null, da sie direkt importiert werden.
readOnly
Zeigt an, ob ein Stylesheet extern (true) ist oder innerhalb eines <style>-Blocks definiert wurde (false). Funktioniert nur im Internet Explorer ab Version 4.
title
Wert des title-Attributs eines Stylesheets; setz- und lesbar.
NS4.x NS6
NS7
IE4 IE5
cssText media
ownerNode
owningElement
parentStyleSheet
readOnly
title a.
IE5.5 IE6
O7
M1
K3
Tabelle 19.6: Einige weitere Eigenschaften des styleSheetObjekts (Forts.)
Tabelle 19.7: Weitere Eigenschaften des styleSheetObjekts
beim Mac owningNode
Die Methoden des styleSheet-Objekts dienen dazu, Regeln hinzuzufügen und zu entfernen. Wie die folgende Tabelle zeigt, sind die Methoden für Internet Explorer und Netscape Navigator unterschiedlich.
KOMPENDIUM
JavaScript
597
Kapitel 19 Tabelle 19.8: Weitere Methoden des styleSheetObjekts
Tabelle 19.9: Weitere Methoden des styleSheetObjekts
CSS und JavaScript
Methode
Beschreibung
addRule()
Fügt eine neue Regel hinzu. Ist der optionale Index angegebenen, wird die Regel an dieser Stelle eingefügt, anderenfalls am Ende; Internet Explorer ab Version 4.
insertRule("Rule", Index)
Fügt eine neue Regel ein; nur Netscape 6 und höher sowie Mozilla.
removeRule(Index)
Entfernt eine Regel; Internet Explorer ab Version 4.
deleteRule(Index)
Löscht eine Regel; Netscape Navigator ab Version 6 und Mozilla.
NS4.x NS6
NS7
addRule()
IE4 IE5
IE5.5 IE6
O7
M1
K3
insertRule()
deleteRule()
removeRule()
19.5
Stylesheets in der Praxis
Der Einsatz von Stylesheets ist heute für einen Webdesigner bereits selbstverständlich. Die Zugriffs- und Arbeitsmöglichkeiten mit JavaScript erfordern eine verstärkte Rücksichtnahme auf die Browserkompatibilität, liefern dafür aber sehr interessante Möglichkeiten. Verzichtet man auf Netscape 4.x-Kompatibilität, lassen sich die wichtigsten Elemente wie beispielsweise das style-Objekt bedenkenlos verwenden. Aber auch wenn Netscape 4.xKompatibilität von Bedeutung ist, lassen sich optische Effekte gut mit Stylesheets realisieren, wenn der Programmierer darauf achtet, dass Netscape 4.x-Nutzer nur auf Optik und Effekte, nicht aber auf Inhalt verzichten müssen. Dasselbe gilt für den Wechsel von ganzen Stylesheets beispielsweise mit disabled. Konqueror- und Opera-Nutzer sehen zwar den Effekt nicht, dürfen aber auch kein komplettes Chaos vorgesetzt bekommen. Testen Sie insbesondere auf den Browsern, die eine Funktion, ein Objekt usw. nicht unterstützen, um zu sehen, ob auch Nutzer dieser Browser mit Ihrer Seite noch etwas anfangen können. Wenn dies nicht der Fall ist, müssen Sie diesen Nutzern Alternativen anbieten.
598
KOMPENDIUM
JavaScript
Stylesheets in der Praxis
Kapitel 19
Dem Einsatz von Stylesheets sind auch Grenzen gesetzt, wenn der Nutzer eigene Stylesheets verwendet, die das Aussehen der Seite mit beeinflussen, oder Stylesheets komplett untersagt.17 Im Internet Explorer können Sie beispielsweise über das Menü EXTRAS/INTERNETOPTIONEN und die Schaltfläche EINGABEHILFEN eigene BENUTZERSTYLESHEETS vergeben.18 In manchen Browsern, beispielsweise Netscape 4.x lassen sich auch Stylesheets deaktivieren.
17 Beim Netscape Navigator 4.x ist dies sogar der Fall, wenn der Nutzer JavaScript deaktiviert, da die CSS-Engine direkt mit JavaScript integriert ist. 18 Ein Stylesheet, das den Rahmen von Tabellen oder -Tags vergrößert, kann sehr praktisch sein, um komplexere Layouts von anderen Seiten genauer anzuschauen.
KOMPENDIUM
JavaScript
599
20
DHTML
Kaum eine DHTML-Abhandlung beginnt ohne eine Diskussion über die Begrifflichkeit. DHTML steht für Dynamic HTML. Der Begriff Dynamic ist schwammig. Da DHTML kein eigener technologischer Standard ist, haben sich daraus eine Vielzahl von Definitionen gebildet. Übrig geblieben sind zwei Ansätze: DHTML als Kombination der Technologien HTML, CSS und JavaScript unter Verwendung eines DOM (Document Object Model) DHTML als (clientseitig) programmierte Interaktion auf einer Website, die zumindest mit HTML arbeitet1 Die Wahrheit – das heißt die Praxis – liegt wohl irgendwo zwischen den beiden Definitionen, denn es scheint weder vollkommen logisch, dass alle drei Technologien inklusive DOM vorhanden sein müssen, noch ist es besonders sinnvoll, per mailto: versendete Formulareingaben als DHTML zu bezeichnen. Nun aber genug der akademischen Diskussionen. In diesem Kapitel erfahren Sie zunächst näheres über die Grundlagen von DHTML. Zum besseren Verständnis der Grundlagen ist es hilfreich in Kapitel 10 »Document Object Model« und Kapitel 12 »Browserunterscheidung« nachzuschlagen, denn dort werden die Grundlagen für DHTML gelegt. In diesem Kapitel finden Sie daher mehrere Verweise auf diese Kapitel. Anschließend finden Sie die DHTML-Beispiele nach Anwendungen sortiert, damit Sie direkt erkennen können, was Ihnen in der Praxis nutzt. Die Anwendungsbeispiele sind in folgende Bereiche unterteilt: Maus – Interaktionen mit der Maus, aber auch die Wandlung des Mauszeigers gehören in diesen Bereich. Navigation – Wie bessert DHTML optisch eine Navigation auf? Welche Lösungen sind möglich? Animation – DHTML und Bewegung auf der Webseite 1
Dies schließt beispielsweise Flash aus.
KOMPENDIUM
JavaScript
601
Kapitel 20
DHTML
20.1
Grundlagen
DHTML ist ab der vierten Generation des Netscape Navigators und Internet Explorers möglich. Dies schließt ältere Browser natürlich aus. Aber auch bei allen Browsern ab der vierten Generation müssen sehr viele Aspekte beachtet werden. Der Netscape Navigator 4.x hat ein komplett eigenes Objektmodell und für DHTML beispielsweise Layer, die kein anderer Browser, also auch keine spätere Netscape-Version, kennt. Der Internet Explorer verwendet ein Objektmodell, das auf document.all beruht. Erst die neueren Browser Internet Explorer 5 und Netscape 6 unterstützen das W3C-DOM.2 Auch im Konqueror, seinem Mac OS X-Ableger Safari und in Opera wird das W3C-DOM gut unterstützt. Wenn Sie mit DHTML arbeiten und auch die vierte Generation der Browser unterstützen möchten, müssen Sie also drei Objektmodelle berücksichtigen. Dazu ist eine effektive Browserunterscheidung notwendig. Im DHTMLBereich wird hier die Unterscheidung mit Browserobjekten bevorzugt.3 Mit dieser Unterscheidung erfahren Sie sofort, ob ein Browser ein Objekt direkt unterstützt. if (document.all)
prüft beispielsweise, ob der Browser document.all unterstützt. Ein Internet Explorer liefert etwas zurück, wodurch die Bedingung als erfüllt (true) gilt. Andere Browser geben undefined zurück, was für die Bedingung false bedeutet. Die Browserunterscheidung mittels navigator-Objekt kann für eine DHTML-Seite unangenehme Konsequenzen haben. Häufig werden nur einige wenige Browser abgeprüft. Neue Browser und »Rand-Browser« wie beispielsweise Safari, Konqueror oder Opera, die sich nicht als anderer Browser ausgeben, bleiben außen vor, obwohl sie das W3C-DOM gut unterstützen. Die Beispiele in diesem Kapitel verwenden die Browserunterscheidung mit Browserobjekten. Einige Beispiele funktionieren allerdings nicht in allen Browsern. In diesem Fall finden Sie jeweils Hinweise und Erklärungen. In den nächsten Abschnitten werden die Besonderheiten einiger Browser im Umgang mit DHTML grundlegend erläutert. Dies ist zum Verständnis der folgenden Beispiele hilfreich.
2 3
602
Nähere Informationen zu DOMs erhalten Sie in Kapitel 10 »Document Object Model«. siehe Kapitel 12.4 »Browserobjekte«
KOMPENDIUM
JavaScript
Grundlagen
Kapitel 20
Netscape 4.x und Layer Aus der Sicht des DHTML-Programmierers ist Netscape 4.x der Albtraum unter den Browsern. Er kocht in allen Bereichen sein eigenes Süppchen. Wie Sie in Kapitel 19 »CSS und JavaScript« nachlesen konnten, ist auch die CSSUnterstützung nur teilweise vorhanden und unterscheidet sich von den anderen Browsern. Beispielsweise besitzt der Netscape Navigator 4.x kein style-Objekt und verfügt über wesentlich weniger Möglichkeiten, Stile zu ändern. Die Ursache dieser Inkompatibilitäten und fehlenden Standardunterstützung liegt hauptsächlich darin, dass Netscape den Browser auf den Markt gebracht hat, bevor viele Konzepte standardisiert wurden. Der Bereich, wo dies am deutlichsten wird, sind Layer. Netscape entwickelte das Tag. Layer waren als frei platzierbare Ebenen gedacht, die auch übereinander geschichtet werden können. Leider ging dieses Konzept nie in den HTML-Standard ein und tauchte in der nächsten Netscape-Version 6 nicht mehr auf. Für DHTML-Programmierer gibt es den angenehmen Umstand, dass im Navigator 4.x auch -Blöcke als Layer angesehen werden. Sie können auf diese Elemente also direkt mit document.ID
zugreifen.
Internet Explorer 4 Der Internet Explorer 4 hat zwar auch ein eigenes Objektmodell, macht es dem Programmierer aber nicht ganz so schwer. Die Kollektion document.all enthält alle Elemente. Mit document.all.ID
greifen Sie einfach auf ein Element zu. Alternativ können Sie document.all["ID"]
verwenden. Auch das style-Objekt ist im Internet Explorer 4 schon vorhanden.
Internet Explorer 4 und höher Der Internet Explorer besitzt einige eigene Funktionen, die von keinem anderen Browser genutzt werden und für DHTML eingesetzt werden können. Zum einen sind dies Stylesheet-Befehle für Filter wie beispielsweise
KOMPENDIUM
JavaScript
603
Kapitel 20
DHTML einen Transparenzfilter und zum anderen so genannte Behavior, also standardisierte Verhalten. Diese Funktionen werden in den folgenden Abschnitten beschrieben. Filter Der Internet Explorer ab Version 4 besitzt unter Windows (nicht beim Mac!) so genannte Filter. Vielleicht sind Ihnen Filter aus Grafikprogrammen bekannt. Es handelt sich dabei um kleine Hilfsprogramme, die Effekte auf ein Bild anwenden, deren Erstellung von Hand deutlich zeitaufwändiger wäre. Im Internet Explorer sind die Filter ein Teil der Stylesheet-Implementierung.4 Die Anwendung erfolgt mit filter und dem Filternamen. In runden Klammern folgen mögliche Attribute. Beliebiger Text auch für Internet Explorer 4
Ab Internet Explorer 5.5 hat Microsoft eine neue Syntax für Filter eingeführt. Es muss genau angegeben werden, wo der Filter zu finden ist. Dazu folgt nach filter zunächst progid und anschließend der Name der Komponente, die die Filter enthält: Beliebiger Text Abbildung 20.1: Die Filtereffekte im Browser
4
604
Sie sind jedoch kein Bestandteil des Standards. Die CSS-Arbeitsgruppe des W3C hat die Vorschläge von Microsoft zurückgewiesen und wartet auf die Ergebnisse der SVG-Arbeitsgruppe, die sich mit Filtern in Verbindung mit Stylesheets beschäftigt.
KOMPENDIUM
JavaScript
Grundlagen
Kapitel 20
Damit bestimmte Filter in einem -Block sichtbar werden, benötigen diese Breiten und/oder Höhenangaben im Stylesheet.
Eine Anleitung zu Filtern finden Sie bei Microsoft unter http://msdn. microsoft.com/workshop/filter/filters.asp. Unter http://msdn.microsoft. com/workshop/filter/reference/reference.asp finden Sie eine Auflistung aller zur Verfügung stehenden Filter. Der Skriptzugriff auf einen Filter erfolgt über das Objekt filter. In der filters[]-Kollektion kann entweder der Index oder der Name des Filters angegeben werden: document.all.ie4.filters["dropshadow"]5
Analog können Sie die Eigenschaften eines Filters ändern: document.all.ie4.filters["dropshadow"].offx = "10";
Die neue Syntax ab Internet Explorer 5.5 erfordert etwas mehr Tipparbeit, da der Name mit Komponente angegeben werden muss: document.all.ie55.filters["DXImageTransform.Microsoft.Glow"].color = "blue";
Das folgende Beispiel ändert beim Anklicken der Schaltfläche jeweils eine Eigenschaft eines Filters in der alten und der neuen Syntax: Filter <script language="JScript"> JavaScript-Kompendium
Dieses Buch behandelt alle wichtigen Aspekte von JavaScript und hilft, dynamische Anwendungen für das Web zu realisieren.
Die Teile des Buchs: | Teil I | JavaScript |
Teil II | Webanwendungen |
Teil III | Über den Tellerrand |
Die Grundlagen und fortgeschrittene
Programmierung mit JavaScript.
630
KOMPENDIUM
JavaScript
Navigation
Kapitel 20
JavaScript-Anwendungen
von und für die Praxis. Ein Blick über den Tellerrand. Abbildung 20.11: Der Hilfetext im orangefarbenen Kasten
Browserschwierigkeiten Das Sichtbar- und Unsichtbarmachen von Elementen hat einige Haken. Das erste Problem – das fehlende style-Objekt im Netscape Navigator 4.x – lösen Sie am besten, indem Sie das Objekt direkt in den Zugriff integrieren, wie dies auch in den bisherigen Beispielen erfolgte (siehe Listing 20.8). Ein weiteres Problem entsteht, wenn Sie testen möchten, ob ein Element bereits sichtbar ist. Alle Browser liefern visible für sichtbar und hidden für unsichtbar zurück. Alle Browser? Der Netscape Navigator tanzt wieder aus der Reihe. Hier steht show für sichtbar und hide für unsichtbar. Eine Überprüfung für alle Browser muss also beide Browser überprüfen: if (absatz.visibility == "visible" || absatz.visibility == "show")
KOMPENDIUM
JavaScript
631
Kapitel 20
DHTML Sie finden ein Beispielskript mit dem Namen dhtml.html im Ordner code\kap20 auf der CD-ROM.
zIndex Wenn sich mehrere positionierte Elemente überlappen, entscheidet die Reihenfolge im HTML-Code darüber, welches Element höher liegt. Wollen Sie dagegen die Position selbst festlegen, können Sie in CSS den z-index als ganze Zahl angeben. Das Element mit dem größeren z-index befindet sich oben. Zum z-index bietet JavaScript eine eigene Eigenschaft, die in der JavaScriptSyntax zIndex geschrieben wird.19 Sie ist in den DHTML-fähigen Browsern vorhanden. Tabelle 20.8: zIndex
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel verwendet zIndex, um beim Anklicken des Buttons die Überlagerung der beiden Bilder zu ändern. Die Prüfung und Änderung des zIndex ist fett hervorgehoben. Der Zugriff auf die Bilder, die in -Blöcke eingebaut sind, erfolgt wie gewöhnlich. Listing 20.9: Den zIndex dynamisch verändern (zindex.html)
zIndex <script language="JavaScript">
632
KOMPENDIUM
JavaScript
Navigation
Kapitel 20
} else { bild1.zIndex = 1; bild2.zIndex = 2; }
} //--> Abbildung 20.12: Zuerst ist das eine (links) und dann das andere Buch im Vordergrund (rechts).
Die Positionierung von Formularelementen ist im Netscape Navigator 4.x und in älteren Versionen des Opera noch nicht möglich.
KOMPENDIUM
JavaScript
633
Kapitel 20
DHTML
Elemente permanent sichtbar machen Eine häufige Aufgabe, sowohl in der Navigation als auch in der Werbung besteht darin, dass ein Element der Seite erhalten bleiben soll, auch wenn der Nutzer in der Seite nach unten oder zur Seite scrollt. Die Positionierung mit CSS hat für dieses Problem eine Lösung: Sie können Elemente mit fixed positionieren, sodass sie auch beim Scrollen in ihrer Position relativ zum Browserfenster bleiben.
Das Problem bei dieser Lösung ist, dass weder Netscape Navigator 4.x noch Internet Explorer (in allen Versionen unter Windows20) fixed unterstützen. Tabelle 20.9:
NS4.x NS6
fixed
a.
NS7
IE4 IE5 ()a
IE5.5 IE6
O7
M1
K3
beim Mac
JavaScript bietet hier einen Ausweg. Sie müssen lediglich feststellen, wie weit die Seite gescrollt wurde und dann die Position des Elementes anpassen. Damit die Überprüfung permanent erfolgt, ruft sich die zugehörige Funktion permanent() mit setTimeout() immer wieder selbst auf. Zunächst wird beim Laden der Seite die Funktion start() aufgerufen. In dieser Funktion wird zuerst die Position des Elements ausgelesen, das permanent angezeigt werden soll. Das Skript führt dabei eine einfache Browserunterscheidung mit Browserobjekten durch. function start() { if (document.layers) { x_pos = document.bild1.left; y_pos = document.bild1.top; } else if (document.all) { x_pos = document.all.bild1.style.pixelLeft; y_pos = document.all.bild1.style.pixelTop; } else if (document.getElementById) { document.getElementById("bild1").style.position = "fixed"; return; } permanent(); }
20 Beim Mac wird fixed unterstützt.
634
KOMPENDIUM
JavaScript
Navigation
Kapitel 20
Für Browser, die document.getElementById() unterstützen, wird die Positionierung direkt auf fixed gesetzt. Dieser Weg ist natürlich eine Abkürzung. Sie könnten auch für diese Browser die Position mit JavaScript setzen. Allerdings wird die fixierte Positionierung mit CSS im Browser wesentlich sanfter gerendert und sieht daher einfach flüssiger aus, wenn der Nutzer scrollt. Da auch der Internet Explorer document.getElementById() unterstützt, fixed jedoch nicht, müssen Sie die Überprüfung von document.all unbedingt vor der auf document.getElementById() durchführen. Nachdem die normale Position des Elements festgestellt wurde, dient die Funktion permanent() dazu, die Scroll-Position festzustellen: function permanent() { if(document.layers) { var x_scroll = window.pageXOffset; var y_scroll = window.pageYOffset; } else if (document.all) { var x_scroll = document.body.scrollLeft; var y_scroll = document.body.scrollTop; }
Das Feststellen der Scroll-Position ist – wie in diesem Code-Fragment zu sehen – von Browser zu Browser unterschiedlich. Die folgende Tabelle gibt eine Übersicht darüber, wie welcher Browser auf die Scroll-Position zugreift.21 Netscape 4.x
IE 4+ Opera 7Konqueror/Safari
Navigator 6+, Mozilla
window.pageXOffset
body.scrollLeft
window.scrollX
window.pageYOffset
a
window.scrollY
a.
body.scrollTop
Tabelle 20.10: Scroll-Position in verschiedenen Browsern feststellen
Für die Scroll-Position in einem Frame oder einem anderen Objekt referenzieren Sie einfach auf dieses Objekt. Ab Internet Explorer 5 liefert diese Eigenschaft für nahezu jedes Objekt einen Wert.
Im zweiten Schritt ruft das Skript die Funktion setzen() auf, die das Element anhand der Scroll-Position neu setzen soll. Anschließend wird die Funktion permanent() mit setTimeout() wieder aufgerufen, um die Scroll-Position zu aktualisieren.
21 Der Zugriff für Opera/Konqueror/Safari und Navigator/Mozilla wird in diesem Beispiel nicht benötigt, da in der Funktion start() für diese Browser die Positionierungsmethode auf fixed geändert wurde.
KOMPENDIUM
JavaScript
635
Kapitel 20
DHTML setzen(x_scroll, y_scroll); setTimeout("permanent()", 50); }
Die Funktion setzen() verwendet die Scroll-Position und die Ausgangsposition des Elements und errechnet daraus die neue Position: function setzen(x_scroll, y_scroll) { if (document.layers) { document.bild1.left = parseInt(x_pos) + parseInt(x_scroll); document.bild1.top = parseInt(y_pos) + parseInt(y_scroll); } else if (document.all) { document.all.bild1.style.pixelLeft = x_pos + x_scroll; document.all.bild1.style.pixelTop = y_pos + y_scroll; } }
Nachfolgend sehen Sie den vollständigen Code. Funktionsaufrufe und Namen sind fett hervorgehoben: Listing 20.10: Scrollen mit JavaScript verhindern (logo_permanent_js .html)
Permanent <script language="JavaScript">
} permanent();
} function permanent() { if(document.layers) { var x_scroll = window.pageXOffset; var y_scroll = window.pageYOffset; } else if (document.all) { var x_scroll = document.body.scrollLeft; var y_scroll = document.body.scrollTop; } setzen(x_scroll, y_scroll); setTimeout("permanent()", 50);
636
KOMPENDIUM
JavaScript
Navigation
Kapitel 20
} function setzen(x_scroll, y_scroll) { if (document.layers) { document.bild1.left = parseInt(x_pos) + parseInt(x_scroll); document.bild1.top = parseInt(y_pos) + parseInt(y_scroll); } else if (document.all) { document.all.bild1.style.pixelLeft = x_pos + x_scroll; document.all.bild1.style.pixelTop = y_pos + y_scroll; } } //-->
Abbildung 20.13: Nun scrollt das Logo auch im Internet Explorer mit.
Die Geschwindigkeit, mit der setTimeout() die Funktion wieder aufruft, entscheidet, wie schnell gescrollt wird. Zum Testen sollten Sie diese hochsetzen, später können Sie dann die richtige Geschwindigkeit wählen. Scrollen Das Feststellen der Scroll-Position ist nicht die einzige dynamische Möglichkeit beim Scrollen. Es gibt auch drei Methoden, die ein dynamisches Setzen der Scroll-Position per JavaScript erlauben:
KOMPENDIUM
JavaScript
637
Kapitel 20
DHTML window.scroll(x, y) – scrollt das Dokument absolut von der linken oberen Ecke nach links (x) und unten (y). Folgende Zeile setzt also die
Scroll-Position wieder zurück: window.scroll(0, 0); window.scrollBy(dx, dy) – scrollt das Dokument relativ zur aktuellen Position nach links (dx) und unten (dy). Die folgende Zeile scrollt 20
Pixel nach rechts und 40 Pixel nach oben: window.scrollBy(20, -40); window.scrollTo(x, y) – scrollt das Dokument absolut. Ersetzt die Methode window.scroll() ab den Browsern der vierten Generation. Die folgende Zeile scrollt horizontal auf die Anfangsposition und vertikal auf 100 Pixel: window.scrollTo(0, 100); scroll() existiert als einzige der drei Funktionen bereits im Netscape 3, die anderen beiden Funktionen sind erst ab der vierten Generation enthalten. Tabelle 20.11: Methoden zum Scrollen
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
scroll()
scrollBy()
scrollTo()
20.4
Animation
Eine der spannendsten Anwendungen von DHTML ist die Animation von Elementen. Vielleicht haben Sie schon einmal ein Werbebanner gesehen, das über die Webseite fliegt. Das war vermutlich DHTML. In diesem Abschnitt finden Sie ein umfangreicheres Beispiel mit einer zufallsgesteuerten Animation. Darüber hinaus werden die einzelnen Objekte dynamisch erstellt. Das Beispiel soll fallenden Schnee auf einer Webseite darstellen. Ein solcher Effekt ist normalerweise eine Domäne von Flash, aber auch DHTML kann das. Das Prinzip ist recht einfach: Das Skript gibt dynamisch -Blöcke mit ebenfalls dynamisch vergebenen IDs und per Zufall gewählter Position aus, die ein Bild mit einer Schneeflocke enthalten.
638
KOMPENDIUM
JavaScript
Animation
Kapitel 20
Auf der CD-ROM finden Sie das Bild mit dem Namen flocke.gif im Ordner code\kap20. Wenn Sie andere Farben bevorzugen, finden Sie dort auch die original Photoshop-Datei flocke.psd. Nachdem die Schneeflocken über das gesamte Fenster zufallsgesteuert verteilt sind, wird eine Funktion, die die Flocken bewegen soll, mit setInterval() in regelmäßigen Abständen aufgerufen. Die Funktion zum Bewegen der Flocken erhöht bei jedem Aufruf die y-Koordinate um 5 Pixel, damit die Flocken nach unten fallen. Abbildung 20.14: Schneetreiben im Browser
Vorbereitungen Die Vorbereitungen bestehen – wie meistens – aus Variablendeklarationen.22 Die Variable name soll später die IDs der einzelnen Schneeflocken-Blöcke aufnehmen. Die Variable ele enthält die Ausgabe und wird bereits als leere String-Variable vordefiniert.
22 Wenn Sie ein eigenes Skript programmieren, benötigen Sie häufig währenddessen zusätzliche globale Variablen. Deklarieren Sie diese dann einfach am Anfang und verwenden Sie sie später. So schaffen Sie auch während des kreativen Prozesses Ordnung im Skript. Denn um ehrlich zu sein, wenn sie einmal laufen, ändert ein Programmierer seine Skripten eher nicht mehr ab.
KOMPENDIUM
JavaScript
639
Kapitel 20
DHTML Die beiden Variablen f_hoehe und f_breite enthalten die Höhe und Breite des Browserfensters, wobei eine Fallunterscheidung feststellt, wie die Maße bei verschiedenen Browsern gemessen werden. Von der resultierenden Höhe zieht das Skript noch einmal 30 Pixel ab, da die Schneeflocke selbst ebenfalls eine Höhe hat. var name; var ele = ""; if (window.innerHeight) { var f_hoehe = window.innerHeight - 30; var f_breite = window.innerWidth - 30; } else if (document.body.clientHeight) { var f_hoehe = document.body.clientHeight - 30; var f_breite = document.body.clientWidth - 30; }
Die Messung der Höhe des Browserfensterinhalts ist in den verschiedenen Browsern unterschiedlich: Netscape 4.x, 6 und 7, Mozilla, Konqueror/Safari und Opera verwenden window.innerHeight und window.innerWidth. Der Internet Explorer verwendet stattdessen document.body.clientHeight und document.body.clientWidth. Sollten die Schneeflocken über die Höhe des Browserfensters hinauslaufen, werden in unschöner Abfolge immer wieder die Scroll-Balken eingeblendet. Ein ausreichender Spielraum ist also notwendig.
Dynamische Ausgabe Die dynamische Ausgabe besteht aus einer Schleife, die mittels der Zählervariablen i von 0 bis 20 läuft. i dient dazu, die flexible ID des -Blocks festzulegen. Die Position der 20 auf diese Weise generierten -Blöcke wird mittels einer Zufallszahl und der Höhe des Browserfensters bestimmt.23 for (var i = 0; i KOMPENDIUM
JavaScript
Animation
Kapitel 20
var ele = ""; if (window.innerHeight) { var f_hoehe = window.innerHeight - 30; var f_breite = window.innerWidth - 30; } else if (document.body.clientHeight) { var f_hoehe = document.body.clientHeight - 30; var f_breite = document.body.clientWidth - 30; } for (var i = 0; i
//-->
Diese Überprüfung funktioniert nicht, wenn bereits ein Vorgabewert mit dem value-Attribut angegeben ist. In diesem Fall muss geprüft werden, ob das Feld den Vorgabewert oder einen leeren String enthält, denn beides wäre nicht korrekt.1 Wenn Sie es wünschen, können Sie zusätzlich vorher alle Leerzeichen entfernen, damit der Nutzer Sie nicht mit der Eingabe von Leerzeichen reinlegen kann.
1
648
Es sei denn, der Vorgabewert ist ein möglicher Wert. Dies sollten Sie jedoch im Allgemeinen vermeiden.
KOMPENDIUM
JavaScript
Vollständigkeitsüberprüfung function test() { var ele = document.formular.eingabe.value; return (ele.replace(" ", "") != ""); }
Kapitel 21 Listing 21.2: Vollständigkeitsüberprüfung ohne Leerzeichen (vollst_feld_ ohneleer.html)
Die hier gezeigte Überprüfung gilt für alle Arten von Textfeldern. Checkboxen Für eine Checkbox können Sie mit checked überprüfen, ob sie aktiviert wurde. Folgende Zeile liefert eine Überprüfung, ob eine Checkbox für die AGBs aktiviert wurde: return (document.formular.AGB.checked);
Listing 21.3: Eine Checkbox überprüfen (vollst_checkboxen. html)
Normalerweise ist die Überprüfung einer Checkbox nicht sinnvoll, da sie optionalen Charakter hat. Eine Ausnahme ist eine Checkbox, die eine Bestätigung erfordert: beispielsweise, dass der Nutzer die Lizenzbedingungen akzeptiert oder die AGBs gelesen hat. Wollen Sie überprüfen, ob aus einer Gruppe von Checkboxen2 eine ausgewählt ist, müssen Sie alle Elemente mit einer Schleife durchlaufen: function test() { var ele = document.formular.katalog; for (var i = 0; i < ele.length; i++) { if (ele[i].checked) return (true); } return false; }
Listing 21.4: Vollständigkeitsüberprüfung mit mehreren Checkboxen (vollst_checkboxen _mehrere.html)
Radiobuttons Radiobuttons treten immer in Gruppen auf, haben also dasselbe name-Attribut. Die Überprüfung erfolgt analog zu den Checkboxen:
2
Jede Checkbox einer Gruppe hat das gleiche name-Attribut.
KOMPENDIUM
JavaScript
649
Kapitel 21 Listing 21.5: Vollständigkeitsüberprüfung für eine Gruppe von Radiobuttons (vollst_radiobutton. html)
Vollständigkeitsüberprüfung und reguläre Ausdrücke function test() { var ele = document.formular.geschl; for (var i = 0; i < ele.length; i++) { if (ele[i].checked) return (true); } }
Auswahllisten Bei Auswahllisten unterscheidet sich die Vollständigkeitsüberprüfung für Listen mit nur einer und Listen mit mehreren Auswahlmöglichkeiten. Auswahlliste mit einer Option Wenn der Nutzer keine Option auswählt, ist automatisch die erste Option in einer Auswahlliste ausgewählt. Die Eigenschaft selectedIndex hat also den Wert 0.3 Daher steht häufig als erste Option nur ein Platzhalter wie »Bitte wählen« zur Verfügung. Bei einer Vollständigkeitsüberprüfung kann anschließend getestet werden, ob selectedIndex gleich 0 ist. In diesem Fall hat der Nutzer nichts ausgewählt. return (ele.selectedIndex != 0);
Wollen Sie nicht nur am Anfang, sondern auch zwischen den Optionen leere Optionen einfügen, sollten Sie eine andere Überprüfungsmethode wählen. Die Füllfelder sollten einen leeren String als value haben. Das Überprüfungsskript prüft dann die value-Eigenschaft der ausgewählten Option: Listing 21.6: Die Vollständigkeitsüberprüfung mittels eines leeren value-Attributs (vollst_auswahl_ value.html)
Vollständigkeit überprüfen <script language="JavaScript">
} //--> <select name="auswahl"> Option 1 Option 2 --- Option 3 3
650
siehe Kapitel 16.2 unter »Auswahlliste« im Abschnitt »Zugriff auf Auswahllisten«
KOMPENDIUM
JavaScript
Vollständigkeitsüberprüfung
Kapitel 21
Auswahlliste mit mehreren Optionen Bei einer Auswahlliste mit mehreren Optionen4 kann der Nutzer natürlich auch nur leere Optionen auswählen. Die Auswahl bleibt auch dann korrekt, wenn nur eine Option einen Wert hat. Daher muss die Überprüfungsfunktion alle Optionen durchgehen und überprüfen, ob sie ausgewählt sind und keinen leeren Wert haben. Nur, wenn beides für eine der Optionen zutrifft, wird von der Überprüfung true zurückgeliefert. function test() { var ele = document.formular.auswahl; for (var i = 0; i < ele.length; i++) { if (ele.options[i].value != "" && ele.options[i].selected) return true; } return false; }
Listing 21.7: Vollständigkeitsüberprüfung für eine Auswahlliste mit mehreren Optionen (vollst_auswahl_ mehrere.html)
Datei-Upload Die Überprüfung des Datei-Uploads erfolgt wie die Überprüfung eines Textfelds. Ist es leer, hat der Nutzer keine Datei angegeben. In Kapitel 16.2 im Abschnitt »Datei-Upload« finden Sie ein Beispiel für die Überprüfung des Datei-Uploads.
Automatisieren Die bisherigen Überprüfungen für die einzelnen Formularelemente benötigen eine direkte Referenz auf den Elementnamen. Dies ist bei größeren Formularen natürlich unpraktisch. Hier stellt sich die Frage, ob das ganze Formular – unabhängig davon, welche Elemente enthalten sind – nicht automatisch geprüft werden kann. Ein solcher Automatismus basiert immer auf demselben Aufbau, auch wenn er unterschiedlich realisiert werden kann: Alle Elemente des Formulars werden in einer Schleife durchgeprüft. Eine Fallunterscheidung testet den Typ (type-Eigenschaft) des Elements. Je nach Typ wird eine der Überprüfungsfunktionen aufgerufen.
4
HTML-Attribut multiple
KOMPENDIUM
JavaScript
651
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke Die gesamte Überprüfung wird mit return false abgebrochen, wenn eine der Überprüfungsfunktionen false zurückliefert, ein Element also nicht ausgefüllt ist. Im Folgenden sehen Sie ein vollständiges Skript, das aus diesen Elementen besteht. Hervorgehoben sind die Funktionsaufrufe und die Rückgaben (return).
Listing 21.8: Automatisierte Vollständigkeitsüberprüfung (vollst.html)
Vollständigkeit überprüfen <script language="JavaScript">
} else if (f.elements[i].type=="select-multiple") { if(!multiple(f.elements[i])) return false;
} else if (f.elements[i].type=="checkbox" || f.elements[i].type=="radio") { if(!radio_check(f, f.elements[i].name)) return false;
} } return true;
} function leer(ele) { var inhalt = ele.value; return (inhalt.replace(" ","") != "");
} function multiple(ele) { for (var i = 0; i < ele.length; i++) { if (ele.options[i].value != "" && ele.options[i].selected) return true;
} return false;
} function radio_check(f, ele) { if (f.elements[ele].length == null) { return true;
} else { for (var i = 0; i < f.elements[ele].length; i++) { if (f.elements[ele][i].checked) return true;
} } return false;
652
KOMPENDIUM
JavaScript
Vollständigkeitsüberprüfung
Kapitel 21
} //-->
Wohin soll die Reise gehen?
<select multiple name="auswahl"> Zypern --- Barcelona --- Moskau Reiseziel?
Sonderwunsch?
Weiblich
Männlich
Katalog senden
Die Überprüfungsfunktionen kennen Sie bereits von den einzelnen Formularelementen. Lediglich die Funktion für Checkboxen und Radiobuttons musste angepasst werden: Hier wird als Erstes überprüft, ob mehrere Elemente mit demselben Namen vorhanden sind. function radio_check(f, ele) { if (f.elements[ele].length == null) { return true;
Wenn dies nicht der Fall ist, wird sofort true zurückgeliefert. Das heißt, Checkboxen oder Radiobuttons, die alleine stehen, müssen nicht unbedingt aktiviert sein. Gibt es mehrere Checkboxen oder Radiobuttons mit einem Namen, werden alle Elemente der Gruppe durchlaufen und überprüft, ob eines der Elemente aktiviert ist. } else { for (var i = 0; i < f.elements[ele].length; i++) { if (f.elements[ele][i].checked) return true; } }
KOMPENDIUM
JavaScript
653
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke Sollte dies nicht der Fall sein, wird am Ende der Funktion false zurückgegeben. return false; }
Optionale Felder Der Automatismus vereinfacht das Leben des JavaScript-Programmierers natürlich deutlich, macht allerdings auch ein wenig unflexibel. Was geschieht beispielsweise, wenn ein Formular optionale Felder haben soll? Natürlich könnte jedes Feld einzeln ausgeschlossen werden, allerdings ist dies recht umständlich. Daher können Sie auf einen Trick zurückgreifen: Geben Sie jedem Feld, das optional sein soll, einen eindeutigen Namenszusatz wie beispielsweise "_opt". Überprüfen Sie anschließend mit index Of()innerhalb der Schleife, ob der Namenszusatz enthalten ist.5 Nur, wenn dies nicht der Fall ist, wird das Element weitergeprüft: Listing 21.9: Optionale Elemente nicht testen (Ausschnitt aus: vollst_opt.html)
function test(f) { for (var i=0; i < f.elements.length; i++) { if (f.elements[i].name.indexOf("_opt") == -1) {
if (f.elements[i].type=="text" || f.elements[i].type=="password" || f.elements[i].type=="textarea") { if(!leer(f.elements[i])) return false; } else if (f.elements[i].type=="select-multiple") { if(!multiple(f.elements[i])) return false; } else if (f.elements[i].type=="checkbox" || f.elements[i].type=="radio") { if(!radio_check(f, f.elements[i].name)) return false; } }
} return true; } . . . Sonderwunsch?
Nachfragen Bisher erfolgte die Fehlermeldung ohne sinnvolle Ausgabe. Für eine Ausgabe benötigen Sie eine Fehlervariable, die die Namen der nicht vollständig ausgefüllten Formularfelder aufnimmt. 5
654
Wenn dies nicht der Fall ist, ergibt indexOf() den Wert -1 (siehe Kapitel 7.2 im Abschnitt »Suchen«).
KOMPENDIUM
JavaScript
Vollständigkeitsüberprüfung var fehler = "";
function test(f) { for (var i=0; i < f.elements.length; i++) { if (f.elements[i].type=="text" || f.elements[i].type=="password" || f.elements[i].type=="textarea") { if(!leer(f.elements[i]))
Kapitel 21 Listing 21.10: Vollständigkeitsüberprüfung mit Fehlermeldung (vollst_fehler.html)
fehler += f.elements[i].name + " ";
} else if (f.elements[i].type=="select-multiple") { if(!multiple(f.elements[i])) fehler += f.elements[i].name + " ";
} else if (f.elements[i].type=="checkbox" || f.elements[i].type=="radio") { if(!radio_check(f, f.elements[i].name)) fehler += f.elements[i].name + " ";
} } if (fehler != "") { alert("Folgende Felder fehlen:\n" + fehler); fehler = ""; return false; } else { return true; }
} Abbildung 21.1: Das Skript liefert eine Fehlermeldung.
Allerdings ist noch nicht alles perfekt. Ist die Radiobutton-Gruppe nicht ausgefüllt, erscheint die Fehlermeldung zweimal, weil sie aus zwei Radiobuttons besteht. Hier hilft eine einfache Überprüfung, ob das Feld bereits im fehler-String genannt wurde:
KOMPENDIUM
JavaScript
655
Kapitel 21 Listing 21.11: Für Gruppen von Radiobuttons und Checkboxen erscheint nun lediglich eine Fehlermeldung (vollst_fehler_ mehrere.html)
Vollständigkeitsüberprüfung und reguläre Ausdrücke } else if (f.elements[i].type=="checkbox" || f.elements[i].type=="radio") { if(!radio_check(f, f.elements[i].name)) { if (fehler.indexOf(f.elements[i].name) == -1) fehler += f.elements[i].name + " ";
} }
Wenn Sie etwas längere oder aussagekräftigere Fehlermeldungen verwenden möchten, sollten Sie nicht das name-Attribut heranziehen. Dann scheitert der Automatismus und Sie müssen für jedes Feld eine eigene Fehlermeldung anlegen. Als Erweiterung können Sie die Fehler auch auf einer neuen Seite6 oder mit innerHTML7 oben in der Seite ausgeben.
Ändern In der Regel kann der Nutzer nach der Vollständigkeitsüberprüfung das Formular neu ausfüllen. Wollen Sie etwas aufdringlicher nachfragen, können Sie auch window.prompt() verwenden und direkt nach einem Wert für das Feld nachfragen. Dies ist hauptsächlich bei Textfeldern sinnvoll, nicht aber bei Auswahllisten oder Checkboxen. Im Allgemeinen erscheint die Nachfrage nach einem Formularwert zu aufdringlich. Außerdem bietet sich hier eine Endlosschleife an, wenn der Nutzer das Feld nicht ausfüllen möchte.
Überprüfung bei der Eingabe Die Vollständigkeitsüberprüfung bei der Eingabe erfolgt über das Ereignis onchange. Neben dem Formularfeld muss dann dynamisch eine Fehlermeldung angezeigt werden. Eine Möglichkeit besteht darin, einen bereits vorhandenen <span>-Block einzublenden. Listing 21.12: Vollständigkeitsüberprüfung bei der Eingabe (vollst_eingabe. html)
Vollständigkeit überprüfen <script language="JavaScript">
656
siehe Kapitel 21.2 »Formulardaten übernehmen« siehe Kapitel 20 »DHTML«, insbesondere Kapitel 20.1 unter »Neuere DHTML-Ansätze«.
KOMPENDIUM
JavaScript
Vollständigkeitsüberprüfung
Kapitel 21
}
//--> <span id="eingabe_aus" style="visibility:hidden">Bitte ausfüllen
Das hier verwendete Skript kann für jedes Textfeld in der Seite verwendet werden. Die Referenz auf das aktuelle Textfeld wird mit this übergeben und der Name in der Funktion dynamisch zusammengesetzt: var name = e.name + "_aus";
Dies erfordert, dass die <span>-Blöcke nach einem bestimmten Schema benannt sind. In dem Beispiel heißen Sie immer wie das Textfeld, gefolgt von "_aus". Abbildung 21.2: Der Nutzer hat nur ein Leerzeichen eingetragen.
Das onchange-Ereignis hat den Nachteil, dass es nicht aufgerufen wird, wenn der Nutzer nur in das Feld klickt und nichts ändert. Für diesen Fall könnten Sie zusätzlich onclick verwenden, allerdings erscheint dann sofort eine Fehlermeldung, wenn der Nutzer in das Feld klickt. Um das vorherige Beispiel auch mit der vierten Generation von Netscape Navigator und Internet Explorer abwärtskompatibel zu machen, ist einiger Aufwand nötig. Der Netscape Navigator 4.x benötigt einen absolut positio-
KOMPENDIUM
JavaScript
657
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke nierten -Block für die Beschriftung und in die Funktion test() muss eine Fallunterscheidung für den Zugriff auf den -Block eingefügt werden. Sie finden das abwärtskompatible Beispiel auf der CD-ROM unter vollst_ eingabe_komp.html im Ordner code\kap21. Um auch in Uralt-Browsern die höchste Abwärtskompatibilität zu erreichen, können Sie statt eines -Blocks auch ein image-Objekt verwenden und das Bild von einem transparenten GIF in ein Symbol für fehlerhaftes Ausfüllen abändern.8
Auf dem Server? Gegenüber einer serverseitigen Vollständigkeitsüberprüfung hat die Überprüfung mit JavaScript Vor- und Nachteile. Zunächst die schlechte Nachricht: JavaScript kann deaktiviert werden. Das heißt, entweder entfällt die Vorausfüllung oder der Nutzer kann das Formular überhaupt nicht mehr verschicken. Letzteres sollte natürlich auf keinen Fall eintreten, wenn Sie keine Kunden verlieren möchten. Da aber auch der erste Fall nicht angenehm ist, bleibt zu überlegen, direkt zu überprüfen, ob der Nutzer JavaScript aktiviert hat und ihm nur dann das Formular mit Vollständigkeitsüberprüfung vorzusetzen. Allerdings halten Sie auch hier dem Nutzer ohne JavaScript Informationen vor. Bei diesem Dilemma sollten Sie überlegen, ob eher der Service-Gedanke oder die Filterung von Falscheingaben im Vordergrund steht. Für elektronische Zahlungssysteme – beispielsweise per Kreditkarte – stellen viele Dienstleister zusätzliche Überprüfungen zur Verfügung, sodass Sie den Zahlungsverkehr im Onlineshop gegenchecken können, ohne selbst programmieren zu müssen. Ein Vorteil von JavaScript gegenüber serverseitiger Überprüfung ist die Performance. Die JavaScript-Überprüfung wird direkt im Browser aufgebaut. Es ist keine Anfrage an den Server erforderlich. Bei der serverseitigen Überprüfung müssen die Daten dagegen zunächst an den Server geschickt werden, anschließend wird überprüft und eventuell auftretende Fehlermeldungen werden zurückgeliefert. Dies ist auch der Grund, warum ASP.NET serverseitige Überprüfungen mit Validation Controls für den Internet Explorer9 in JScript-Code umwandelt.
8 9
658
Mehr Informationen zum image-Objekt erhalten Sie in Kapitel 13 »Bilder«. Andere Browser müssen mit serverseitiger Überprüfung vorlieb nehmen.
KOMPENDIUM
JavaScript
Formulardaten übernehmen
21.2
Kapitel 21
Formulardaten übernehmen
Es gibt mehrere Möglichkeiten, um Daten aus einem Formular auf eine andere Seite zu übernehmen. Im Einzelnen erfolgt dies über: ein Cookie (siehe Kapitel 17 »Cookies«) versteckte Formularfelder (siehe Kapitel 16 »Formulare«), eventuell in einem versteckten, also nur 1 Pixel hohen Frame (siehe Kapitel 18 »Frames«). In einem versteckten Frame können Sie natürlich auch die Werte in Variablen ablegen. die Übergabe in der URL mit GET. Diese Methode verwenden wir in diesem Abschnitt, um eine Dankesseite und die Eingaben zu bestätigen. Im Dokument, das die Dankesseite aufruft, muss die URL der Seite unter action eingetragen werden. Als Methode ist GET zu wählen.
Listing 21.13: Aufruf der Dankesseite (vollst_danke.html)
Dieses Skript ist eine leichte Abwandlung von Listing 21.11. Sie finden die vollständige Datei unter vollst_danke.html im Ordner code\kap21 auf der CD-ROM. Die Formulardaten werden hinter einem Fragezeichen an die URL angehängt. Die einzelnen Name/Wert-Paare sind durch kaufmännische Und getrennt: danke.html?Reiseziel=Zypern&Sonderwunsch=Sitzplatz&Geschlecht=m&Katalog=on
Darauf können Sie in der Dankesseite mit dem location-Objekt zugreifen. location.search enthält den Teil des Strings mit dem Fragezeichen. Die Dankesseite ist folgendermaßen aufgebaut: Nach einigen Variablendeklarationen erhält die Variable ur_str den String vom Fragezeichen (inklusive) bis zum Ende. Ist der String nur ein Zeichen order keines, wurden keine Werte übergeben. Wenn jedoch Werte vorhanden sind, erhält der String statt des Fragezeichens am Anfang ein kaufmännisches Und, da so die Überprüfung der Namen/ Wert-Paare einfacher erfolgt. Anschließend wird die Funktion ausgeben() aufgerufen, die den String aus der URL zerlegen soll.
KOMPENDIUM
JavaScript
659
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke var ur_str = location.search; if (ur_str.length > 2) { ur_str = "&" + ur_str.substring(1, ur_str.length); ausgeben(ur_str); } else { document.write("
Keine Werte übertragen
"); }
Diese Funktion geht in einer Schleife den gesamten String durch und schneidet die Namen und Werte heraus. Dazu werden anhand der Trennzeichen & und = jeweils Beginn (beg), Mitte (mit) und Ende (end) eines Name/Wert-Paares herausgefiltert. function ausgeben(ur_str) { for(var pos = 0; ur_str.indexOf("&", pos) != -1; pos=mit+1) { beg = ur_str.indexOf("&", pos)+1; mit = ur_str.indexOf("=", pos); if(ur_str.indexOf("&", mit+1) != -1) end = ur_str.indexOf("&", mit+1); else end = ur_str.length; feld = unescape(ur_str.substring(beg, mit)); wert = unescape(ur_str.substring(mit+1,end)); document.write("
"+feld+": "+wert+"
"); } }
Nachfolgend sehen Sie den vollständigen Code: Listing 21.14: Eine Dankesseite (danke.html)
Vielen Dank Vielen Dank für das Interesse!
Sie haben folgendes ausgewählt:
<script language="JavaScript"> 2) { ur_str = "&" + ur_str.substring(1, ur_str.length); ausgeben(ur_str);
660
KOMPENDIUM
JavaScript
Formulardaten übernehmen
Kapitel 21
} else { document.write("
Keine Werte übertragen
"); } function ausgeben(ur_str) { for(var pos = 0; ur_str.indexOf("&", pos) != -1; pos=mit+1) { beg = ur_str.indexOf("&", pos)+1; mit = ur_str.indexOf("=", pos); if(ur_str.indexOf("&", mit+1) != -1) end = ur_str.indexOf("&", mit+1); else end = ur_str.length; feld = unescape(ur_str.substring(beg, mit)); wert = unescape(ur_str.substring(mit+1,end)); document.write("
"+feld+": "+wert+"
"); } } //--> Abbildung 21.3: Die Angaben werden noch einmal zusammengefasst.
Wenn Sie kein automatisiertes Skript wählen, sondern auf bekannte Formularelemente zurückgreifen, können Sie auch eigene Angaben machen und beispielsweise den Wert m aus dem value-Attribut mit »männlich« ersetzen. Ein weiterer Verbesserungsvorschlag wäre, das Skript zusätzlich mit einer Versandmöglichkeit zu verbinden.
KOMPENDIUM
JavaScript
661
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke
21.3
Reguläre Ausdrücke
Reguläre Ausdrücke sind Muster, die in Strings gesucht werden können oder mit denen Strings verglichen werden. Natürlich können Sie auch mit den String-Methoden wie indexOf() in Strings suchen (siehe Kapitel 7 »Arrays und Strings«). Reguläre Ausdrücke haben allerdings eine eigene Syntax, die es ermöglicht, auch komplexe Überprüfungen sehr einfach durchzuführen. In JavaScript stehen reguläre Ausdrücke als eigenes Regular ExpressionObjekt zur Verfügung. Ein solches Objekt können Sie mit dem Konstruktor (new) erzeugen: var reg = new RegExp("\d{5}");
oder als Literal definieren: var reg = /\d{5}/;
In älteren Browsern – Netscape 2 und 3 und Internet Explorer 3 – stehen reguläre Ausdrücke nicht zur Verfügung. Standardisiert sind sie in ECMAScript v3.10 Der Opera unterstützt sie seit Version 5. Tabelle 21.1: Reguläre Ausdrücke und Regular Expression-Objekt
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Beachten Sie, dass das Literal mit dem regulären Ausdruck immer in Schrägstriche (/) eingeschlossen ist. Der Unterschied zwischen beiden Methoden ist folgender: Per Konstruktor wird der reguläre Ausdruck erst kompiliert, wenn er aufgerufen wird. Dies erlaubt Ihnen, den regulären Ausdruck im Verlauf des Skripts zu ändern. Sie können den Ausdruck allerdings auch mit der Methode compile("Reg. Ausdr.", "Parameter") dazu zwingen, kompiliert zu werden. Diese Methode steht in allen Browsern zur Verfügung, die reguläre Ausdrücke enthalten. Per Literal wird der reguläre Ausdruck sofort kompiliert.
10 JavaScript 1.2 übernimmt einen Teil des Standards, während JavaScript 1.5 den kompletten Standard übernimmt. Die regulären Ausdrücke in ECMAScript v3 entsprechen funktional größtenteils Perl 5.
662
KOMPENDIUM
JavaScript
Reguläre Ausdrücke
Kapitel 21
Das Erstellen eines regulären Ausdrucks ist teilweise recht kompliziert, weil die Syntax sehr kurz und daher auch etwas unübersichtlich ist. Nachfolgend zeigen wir Ihnen eine kurze Übersicht über die wichtigsten grammatikalischen Regeln für reguläre Ausdrücke: Ziffern und Buchstaben des Alphabets entsprechen in regulären Ausdrücken sich selbst. Sonderzeichen werden mit Backslash (\) entwertet. var reg = /\\/
entspricht also einem Backslash. Zeichen mit besonderer Bedeutung – so genannte Metazeichen – sind: \|[]()^$*+-.? Ihre Bedeutung wird nachfolgend erläutert: Zeichenarten können in eckigen Klammern ([]) angegeben werden. Der reguläre Ausdruck /[136]/ prüft, ob eine Ziffer 1, 3 oder 6 ist. Mit dem Bindestrich können Sie Bereiche festlegen: /[a-z]/ steht für alle Kleinbuchstaben und /[a-z0-9]/ für alle Kleinbuchstaben und Ziffern. Für einige Zeichenarten gibt es Kürzel: \w steht für alle ASCII-Zeichen und \d für alle Ziffern. Der Punkt (.) steht für jedes beliebige Zeichen und \s für ein Whitespace. Wollen Sie eine Zeichenart bewusst ausschließen, schreiben Sie ein ^ an den Anfang in die eckigen Klammern: /[^136]/ steht also für »alles« außer 1, 3 und 6. Zum Ausschließen einiger Zeichenarten gibt es ebenfalls Kürzel: \W steht für alles außer ASCII-Zeichen und \D für alles außer Ziffern. \S steht für kein Whitespace. Die Häufigkeit des Auftretens eines Zeichens lässt sich in geschweiften Klammern festlegen: /\d{5}/ steht also für das fünfmalige Auftreten einer Ziffer. Sie können mit Komma getrennt auch Minimal- und Maximalanzahl des Auftretens festlegen: /\d{4,5}/ besagt, dass zwischen vier und fünf Ziffern vorkommen müssen. Wenn Sie die Stelle nach dem Komma freilassen, steht dies für »mindestens«: /\d{5,}/ verlangt also mindestens fünf Ziffern. Neben dieser Syntax gibt es noch einige Kurzformen: – ? steht für einmaliges oder kein Auftreten. Dies entspricht {0,1}. – + steht für einmaliges oder mehrmaliges Auftreten. Dies hat die gleiche Wirkung wie {1,}. – * für steht für mehrmaliges oder kein Auftreten. Dies ist dasselbe wie {0,}.
KOMPENDIUM
JavaScript
663
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke Klammern dienen zur Zusammenfassung von Elementen. Der horizontale Strich (|) trennt Alternativen. /(01|12)|[4-9]/ liefert true, wenn das Zeichen entweder die Ziffer 4 bis 9 enthält oder 0 und 1 oder 1 und 2. Den Inhalt einer Klammer können Sie mit \Nummer wieder aufrufen, wobei die Nummer der Position der Klammer entspricht. Die erste Klammer heißt also \1, die zweite \2 usw. Auf diese Weise können Sie Konstrukte in regulären Ausdrücken wieder verwenden. Ankerzeichen: ^11 steht für den Anfang des Strings oder der Zeile, $ für das Ende. \b (Reguläre Ausdrücke) entspricht einer Wortgrenze. \B ist true, wenn es sich um keine Wortgrenze handelt. Flags regeln das Verhalten des regulären Ausdrucks und werden immer an das Ende geschrieben: /[a-d]/i oder per Konstruktor new RegExp ("[a-d]", "i"). Die für JavaScript wichtigen Flags sind: – g – ist ein Vergleich, der nicht nach der ersten Übereinstimmung abgebrochen wird. – i – ist ein Vergleich, der die Groß- und Kleinschreibung nicht berücksichtigt. – m – berücksichtigt Strings mit Zeilenumbrüchen (mit \n). Dieses Buch kann keine umfassende Einführung in reguläre Ausdrücke bieten. Das Standardwerk auf diesem Gebiet, in dem Sie weiterführende Informationen finden, heißt »Reguläre Ausdrücke« von Jeffrey E.F. Friedl und ist in der deutschen Fassung bei O’Reilly erschienen.
Mit regulären Ausdrücken arbeiten Um mit regulären Ausdrücken effektiv arbeiten zu können, müssen die verschiedenen Erscheinungsformen zunächst von den regulären Ausdrücken unterschieden werden. Dies erfolgt über: Drei String-Methoden – match(RegExp), replace(RegExp, Ersatzstring) und search(RegExp), die auf ein String-Objekt einen regulären Ausdruck anwenden.12 Die folgenden Zeilen ergeben a als Ausgabe, da der Buchstabe »a« in dem String »Mozilla« enthalten ist: var text = "Mozilla"; var reg = /[a-d]/; alert(text.match(reg));
11 Beachten Sie die unterschiedliche Bedeutung der Zeichen in verschiedenen Kontexten. 12 siehe auch Kapitel 7.2 unter»Suchen« im Abschnitt »match(), replace() und search()«
664
KOMPENDIUM
JavaScript
Reguläre Ausdrücke
Kapitel 21
Auch die String-Methode split(Reg. Ausdr.) kann einen regulären Ausdruck verwenden, um einen String zu unterteilen. Die folgenden Zeilen teilen »Mozilla« in »Moz« und »lla«. Das Trennzeichen im regulären Ausdruck verschwindet: var reg = /i/; text.split(reg);
Die Methoden eines Regular Expression-Objekts – Sie erlauben, mit dem per Literal oder Konstruktor geschaffenen Regular Expression-Objekt zu arbeiten. Mehr dazu erfahren Sie im nächsten Abschnitt. Das globale RegExp-Objekt mit seinen Eigenschaften – Dieses Objekt ist immer vorhanden. Es ist nicht gleichzusetzen mit dem Konstruktor RegExp. Dieser Konstruktor erzeugt ein bestimmtes Regular ExpressionObjekt. Das RegExp-Objekt ist dagegen global und enthält in seinen Eigenschaften Informationen über die zuletzt durchgeführten Operationen an einem (dem zuletzt erstellten oder geänderten) Regular Expression-Objekt.13 Die wichtigsten Eigenschaften dieses Objekts finden Sie nachfolgend zusammengefasst. Beachten Sie, dass alle Eigenschaften bis auf input nur lesbar sind: – $1, $2 … $9 – Diese neun Eigenschaften geben die Teile des regulären Ausdrucks an, die in runde Klammern gepackt sind. Sie können zwar im regulären Ausdruck beliebig viele Unterteilungen vornehmen, dieses Objekt speichert allerdings nur neun. – index – gibt die Position im String an, an der der reguläre Ausdruck zum ersten Mal zutraf. – input – enthält den String, auf den eine Suche mit dem regulären Ausdruck durchgeführt wurde und ist als einzige der Eigenschaften auch setzbar. Die Kurzform in Anlehnung an Perl lautet $_. Sie können sie statt des Eigenschaftsnamens einsetzen. – lastIndex – ist eine Position nach der Stelle, an der der reguläre Ausdruck zuletzt zutraf. – lastMatch – sind die zuletzt mit einem regulären Ausdruck gefundenen Zeichen. Die Kurzform lautet $&. – lastParen – liefert den letzten Teil eines regulären Ausdrucks, der zutraf. Da ein Teil in runden Klammern steht, heißt die Methode lastParen. Paren steht also für Parentheses (Klammern). – leftContext – enthält den Teil des Strings links neben einem Teil, der dem regulären Ausdruck entsprochen hat. 13 Diese Unterscheidung wird in vielen Quellen nur unsauber oder überhaupt nicht getroffen. Sie ist jedoch entscheidend, wenn Sie Eigenschaften richtig anwenden möchten.
KOMPENDIUM
JavaScript
665
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke – rightContext – ist das Gegenstück zu leftContext. Die Eigenschaft enthält den rechten Teil neben dem zutreffenden Stück. – multiline – gibt an, ob der reguläre Ausdruck auf einen einzeiligen oder mehrzeiligen String (Flag m) angewendet wurde.
Tabelle 21.2: Methoden des RegExp-Objekts
$1, $2…
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
index input
lastIndex
lastMatch
lastParen
leftContext
rightContext
multiline
Methoden des Regular Expression-Objekts Für ein Regular Expression-Objekt gibt es zwei wichtige Methoden: exec("String") – liefert ein Array mit der ersten übereinstimmenden
Stelle zwischen regulärem Ausdruck und String. Die weiteren Indizes des Arrays liefern eventuell vorhandene Unterergebnisse von ArrayTeilen in runden Klammern. Gibt es keine Übereinstimmung, lautet das Ergebnis null. Die Methode ähnelt in der Wirkung sehr stark der match()-Methode des String-Objekts. Diese speichert jedoch alle Übereinstimmungen in einem Array. var text = "JavaScript"; var reg = /[aeiou]/; var erg = reg.exec(text);
liefert »a«. Der Index 1 (erg[1]) ist nicht vorhanden, da der reguläre Ausdruck keine einzelnen Teile hat. Für das Ergebnis-Array gibt es drei Eigenschaften: input, index und lastIndex. Sie gleichen denen des RegExp-Objekts, denn die jeweils zuletzt ausgeführte Regular Expression-Suche vererbt ihre Werte an die Eigenschaften dieses Objekts. input enthält im vorherigen Beispiel also den String »Java-
666
KOMPENDIUM
JavaScript
Reguläre Ausdrücke
Kapitel 21
Script«, index die Position, an der der reguläre Ausdruck zutraf. Dies ist hier die 1 für das erste »a«. lastIndex ist die Position nach dem ersten Zutreffen, also 2. test("String") – prüft, ob der reguläre Ausdruck im String eine Übereinstimmung findet. Wenn dies der Fall ist, wird true zurückgeliefert, sonst false. Die Zahl der Übereinstimmungen ist irrelevant. Das Ergebnis der folgenden Zeilen ist also true, da in »JavaScript« Vokale vor-
kommen: var text = "JavaScript"; var reg = /[aeiou]/; var erg = reg.test(text); NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
exec()
test()
Tabelle 21.3: exec() und test()
Anwendungen Nachdem Sie nun wissen, wie Sie in JavaScript reguläre Ausdrücke bilden, beschäftigen wir uns im Folgenden mit einigen Mustern, die die Vollständigkeitsüberprüfung wesentlich erleichtern. Zahl und Postleitzahl Das folgende Beispiel überprüft, ob in ein Formularfeld nur Zahlen eingefüllt wurden. Wenn dies nicht der Fall ist, wird das Formular nicht abgeschickt: Reguläre Ausdrücke <script language="JavaScript">
Listing 21.15: Überprüfung, ob nur Zahlen im Feld eingetragen wurden (reg.html)
var reg = /^\d*$/; return reg.test(document.formular.eingabe.value);
} //-->
KOMPENDIUM
JavaScript
667
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke
Aus diesem einfachen Beispiel lässt sich sehr einfach eine Überprüfung für Postleitzahlen erarbeiten. Deutsche Postleitzahlen bestehen immer aus 5 Ziffern. Folgender regulärer Ausdruck prüft dies: var reg = /\d{5}/;
Darüber hinaus werden hier auch Buchstaben vor oder hinter den fünf Zahlen akzeptiert. Um diese auszuschließen, erlauben Sie zwischen Anfang und Ende des Strings nur fünf Zahlen: Listing 21.16: Deutsche Postleitzahlen prüfen (postleitzahl.html)
var reg = /^\d{5}$/;
Natürlich gibt es alternative Wege: Sie können das Feld auf fünf Stellen begrenzen und Anfangs- und Endankerzeichen im regulären Ausdruck weglassen oder Sie verwenden bei einem fünfstelligen Feld den Test mit isNaN(). Dies würde Sie allerdings nicht vor der Eingabe von Fließkommazahlen bewahren. Telefonnummern Telefonnummern sind schwierig zu prüfen. Sie müssen dazu für Ihr Formular ein vorgegebenes Eingabeformat erzwingen. Dies ist allerdings auch nicht ohne Risiko, da beispielsweise Nutzer aus dem Ausland eventuell noch die Auslandskennung mit vorangehendem Plus angeben möchten. Wenn Sie die Eingabe von Telefonnummern ohne sonstige Zeichen verlangen, können Sie sehr einfach überprüfen, ob genügend Ziffern angegeben sind: var reg = /^\d{7,}$/;
Wenn Sie das Format der Telefonnummer vollständig freigeben, können Sie prüfen, ob nur die üblichen Zeichen für Telefonnummern vorhanden sind. Hervorgehoben sind die Steuer- und Entwertungszeichen des regulären Ausdrucks: Listing 21.17: Telefonnummer prüfen (telefonnummer.html)
668
var reg = /^(\d|\+|\-|\.|\,|\/|\(|\))*$/;
KOMPENDIUM
JavaScript
Reguläre Ausdrücke
Kapitel 21
Datum Bei den Daten kommt es meist darauf an, ob es sich um ein gültiges Datum im richtigen Format handelt. Hier ist es besonders wichtig, ein Format vorzugeben. In Deutschland werden Daten beispielsweise in der Form TT.MM.JJ oder TT.MM.JJJJ angegeben, in Amerika dagegen in MM.TT.JJ oder MM.TT.JJJJ. Ein deutsches zwei- oder vierstelliges Datum mit Punkten als Trennzeichen können Sie beispielsweise auf diese Weise prüfen (die Steuerzeichen für reguläre Ausdrücke sind hervorgehoben): var reg = /^(0?[1-9]|[12][0-9]|3[01]).(0?[1-9]|1[0-2]).((19|20)?\d{2})$/;
Bei dieser Prüfung wird jedoch nicht berücksichtigt, dass die Monate unterschiedlich lang sein können.
Listing 21.18: Datum prüfen (datum.html)
E-Mail Die Überprüfung von E-Mail-Adressen mit regulären Ausdrücken gehört zu den schwierigsten Disziplinen. Der folgende reguläre Ausdruck erledigt diese Prüfung bereits relativ zuverlässig: var reg = /^([a-zA-Z0-9_\.\-])+@(\[)?([a-zA-Z0-9_\.\-])*([a-zA-Z09]{2,})\.([a-zA-Z]{2,4}|[0-9]{1,3}\])$/;
Der reguläre Ausdruck besteht aus folgenden Teilen (runde Klammern hervorgehoben):
Listing 21.19: Prüfen einer E-Mail-Adresse (email.html)
Vor dem Klammeraffen dürfen Ziffern, Zahlen, Unterstriche, Punkte und Minuszeichen stehen. Es muss jedoch mindestens ein Zeichen sein (dies gewährleistet das +): ([a-zA-Z0-9_\.\-])+
Dann folgt der Klammeraffe. Beachten Sie, dass dies der einzige Klammeraffe für die E-Mail-Adresse ist. @
Der nächste Abschnitt gibt an, dass an dieser Stelle optional (also keinmal oder einmal mit ?) eine eckige Klammer folgt. Dies fängt alle EMail-Adressen ein, die in dem gültigen Format name@[123.123.123.123] geschrieben sind. (\[)?
KOMPENDIUM
JavaScript
669
Kapitel 21
Vollständigkeitsüberprüfung und reguläre Ausdrücke Nun dürfen beliebig viele Zahlen, Ziffern, Unterstriche, Punkte und Minuszeichen folgen. ([a-zA-Z0-9_\.\-])*
Vor dem nächsten Punkt müssen jedoch mindestens zwei Zahlen oder Ziffern für die Second-Level-Domain stehen: ([a-zA-Z0-9]{2,})
Dann folgt der letzte Punkt: \.
und anschließend zwei bis vier Ziffern für die Top-Level-Domain: ([a-zA-Z]{2,4}
oder drei Ziffern für die letzte Zahl der IP-Adresse und die schließende eckige Klammer: |[0-9]{1,3}\])
Auch dieser bereits recht komplexe Ausdruck ist nicht zu umgehen. Er schließt jedoch zumindest keine gültigen E-Mail-Adressen aus und bietet ein meist ausreichendes Maß an Sicherheit.
21.4
Usability
Viele Probleme mit mandatorischen Feldern und der Vollständigkeitsüberprüfung können Sie vermeiden, wenn Sie beim Anlegen des Formulars auf gute Verwendbarkeit achten. Die wichtigsten Regeln sind: Nur tatsächlich notwendige Felder sollten mandatorisch sein. Trennen Sie Angaben, bei denen es Probleme mit dem Format geben könnte. Geburtsdaten lassen sich beispielsweise einfach auf drei Textfelder aufteilen, sodass es keine Verwechslungen mit englischem und deutschem Format, Punkten und Leerzeichen geben ka18. Wenn es nur einige wenige Optionen gibt, fassen Sie diese in einer Auswahlliste zusammen. Dies ist bei der Jahreszahl des Geburtstags sicherlich nicht sinnvoll, aber bei wenigen Optionen wie der Versandmethode nützlich. Beschriften Sie die Felder ausreichend und geben Sie deutlich an, welche mandatorisch sind. 670
KOMPENDIUM
JavaScript
Usability
Kapitel 21
Trennen Sie die Submit- und die Reset-Schaltfläche optisch und lokal weit genug voneinander, damit ein versehentliches Anklicken der Schaltflächen keine Folgen hat.14 Strukturieren Sie das Formular in logische Teile. Die Adresse sollte beispielsweise deutlich von bestellten Elementen oder angeforderten Katalogen abgehoben sein. Lassen Sie Platz bzw. Felder für eigene Anmerkungen des Nutzers. Manche Kunden möchten Ihnen weitere Mitteilungen zukommen lassen.
14 Sie können auch bei der Reset-Schaltfläche erst nachfragen (siehe Kapitel 16.2 unter »Schaltflächen« im Abschnitt »Reset« und Listing 16.20)
KOMPENDIUM
JavaScript
671
Teil 3 Über den Tellerrand …
Kapitel 22: JavaScript und Sicherheit
675
Kapitel 23: Kommunikation mit der Außenwelt
691
Kapitel 24: JScript .NET
713
22
JavaScript und Sicherheit
Das Thema Sicherheit gehört zu den Top 5 der Computerthemen in den nächsten beiden Jahren, vielleicht steht es sogar an erster Stelle. Das ist gut, sehr gut sogar. Allerdings muss die große Panikmache, die aus manchen Sicherheitsfragen entsteht, insbesondere im Bereich JavaScript relativiert werden. Hier drohen kaum große Sicherheitslecks wie bei Mail-Viren oder dem SQL-Slammer, der die Datenbank MS SQL Server in Massen befallen hat. Für den JavaScript-Programmierer gibt es zwei Bereiche, in denen Sicherheit wichtig ist: Sicherheitslecks in den Browsern und wie der Programmierer mit den Bedenken der Nutzer umgehen sollte. In dieses Themengebiet fallen auch die Zertifikate, denen Nutzer und manche Programmierer nach wie vor kritisch oder unsicher gegenüberstehen. Sicherheit für sein geistiges Eigentum, also für seine Skripten
22.1
Diskussionen und potenzielle Sicherheitslecks
Bei Sicherheitsproblemen muss zunächst geklärt werden, um welche Probleme es sich handelt. Eine einfache Dreiteilung stellt die Probleme im JavaScript- bzw. Browserumfeld bereits sehr gut dar: Das Sicherheitsproblem der Datenspionage, beispielsweise das Feststellen von Surfwegen Wesentlich gefährlicher sind Probleme die den Datenmissbrauch betreffen. Hier werden gewonnene Daten verwendet, beispielsweise Kreditkarteninformationen, um Konten zu plündern. Die gefährlichste Bedrohung ist die Zerstörung von Daten und Dateien auf dem Rechner des Nutzers. Sie ist über den Browser allerdings auch sehr selten anzutreffen.
KOMPENDIUM
JavaScript
675
Kapitel 22
JavaScript und Sicherheit
Lecks? Die dargestellten Sicherheitsprobleme schlagen sich in einigen – häufig diskutierten – potenziellen Sicherheitslecks nieder: Cookies1 – insbesondere Third Party Cookies – können es großen Vermarktern ermöglichen, das Surfverhalten zu verfolgen, ohne allerdings die Informationen personalisieren zu können. Der Nutzer kann jedoch in den meisten Browsern Third Party Cookies sperren. Fremdkontrollierte Fenster; wenn der Nutzer mehrere Websites geöffnet hat, könnte ein Skript einer »bösen« Website auf die Seiten von »guten« Anbietern zugreifen und beispielsweise die dort eingetragenen Informationen auslesen. Dies wird allerdings bereits vom Browser verhindert, da er Websites keinen Zugriff auf fremde Fenster – das heißt nicht von der Domain bzw. dem ersten Unterverzeichnis2 geöffnete Fenster – erlaubt. Dieses Prinzip heißt auch Same Origin (selber Ursprung). Zugriff über Java oder ActiveX-Controls. Dieser Zugriff wird über Zertifikate erlaubt und im folgenden Abschnitt ausführlicher behandelt. Viele Aspekte, die Sicherheitsfragen betreffen – wie der Zugriff auf Dateien auf der Festplatte, das Schließen von beliebigen Browserfenstern und das Ausspionieren der History – sind in JavaScript von Anfang an nicht möglich. Eine Sicherheitsdiskussion ist hier nicht erforderlich.3
22.2
Zertifikate
Das Hauptproblem der Zertifikatslösungen ist die unterschiedliche Umsetzung in verschiedenen Browsern. Das Grundprinzip ist immer gleich: Der Nutzer muss ein Zertifikat, also eine Nachfrage in einem modalen Fenster bestätigen, die dem JavaScript-Code erweiterten Zugriff erlaubt. Dieser Zugriff wird dann je nach Browser und benötigten Befehlen in Verbindung mit Java oder ActiveX realisiert. Das Konzept von Microsoft heißt Authenticode und das von Netscape Object Signing.
1 2
3
676
Eine ausführliche Diskussion der Problematik finden Sie in Kapitel 17.1 im Abschnitt »Sicherheit« Diese Regelung schließt Missbrauch bei Hostern aus, die keine Domainnamen, sondern nur Verzeichnisse vergeben. http://www.hostername.de/kunde1 hat also keinen Zugriff auf Fenster, die http://www.hostername.de/kunde2 geöffnet haben. Die einzige Ausnahme sind die Fähigkeiten, die sich mit Zertifikaten nachrüsten lassen.
KOMPENDIUM
JavaScript
Zertifikate
Kapitel 22
Die Zertifikatslösungen werden nicht nur für JavaScript-Skripten verwendet, sondern auch, um das Herunterladen von ausführbaren Dateien, Plugins und ActiveX-Controls zu gewährleisten.
Grundprinzip Das Grundprinzip der Zertifizierung ist bei beiden Technologien gleich und verläuft aus der Sicht des JavaScript-Programmierers in folgenden Schritten: 1.
Sie beantragen ein Zertifikat bei einer der Gesellschaften, die das Recht zum Zertifizieren haben. Eine solche Gesellschaft heißt Certificate Authority. Abbildung 22.1: VeriSign ist eine der bekanntesten Zertifizierungsfirmen, die für verschiedene Technologien Zertifikate vergibt (http://www.
verisign.com/ products/ signing/ index.html).
Im Netscape Navigator und im Mozilla finden Sie ein eigenes Register AUSSTELLER mit den CA-Unternehmen. Diese Zertifikate werden mit dem Browser mit installiert. Für die deutsche Variante ab Netscape 6 ist dies: BEAREITEN/EINSTELLUNGEN, PRIVATSPHÄRE & SICHERHEIT/ZERTIFIKATE und ein Anklicken der Schaltfläche ZERTIFIKATE VERWALTEN. In den anderen Registerkarten sehen Sie die übrigen Zertifikate.
KOMPENDIUM
JavaScript
677
Kapitel 22
JavaScript und Sicherheit
Abbildung 22.2: Zertifikate der Aussteller im Netscape Navigator 7
Im Internet Explorer 6 heißt die entsprechende Registerkarte VERTRAUENSWÜRDIGE STAMMZERTIFIZIERUNGSSTELLEN. 2.
Daraufhin erhalten Sie vom CA-Unternehmen ein Zertifikat in einem standardisierten Format. Es enthält eine digitale Unterschrift. Um das Zertifikat abzusichern, wird es verschlüsselt.
Zertifikate werden in vier Stufen, so genannten Classes vergeben. Die Stufen reichen von 1 (sehr schwach) bis 4 (extrem geprüft). Je höher die Stufe, desto mehr kostet die Zertifizierung. 3.
Der Zertifizierende, also Sie als Programmierer oder Firma, erhält einen Schlüssel, mit dem er mithilfe eines Werkzeugs sein Skript verschlüsseln ka18. Das Skript lässt sich nun nicht mehr ändern – jede Änderung macht es ungültig. Es ist nun ein signiertes Skript.
4.
Als Nächstes bauen Sie das Zertifikat in Ihre Webseite ein.
5.
Der Nutzer muss das Zertifikat bestätigen. Ob er Ihnen vertraut, lässt sich trotz Zertifizierung nicht vorhersagen.
Insbesondere in Deutschland herrscht nach wie vor eine große Unsicherheit bei den Nutzern. Vielen ist der Zertifizierungsprozess nicht klar und sie werden in den meisten Fällen ein Zertifikat – vor allem einer kleineren Firma – lieber zurückweisen, wenn Sie die Informationen für entbehrlich halten.
678
KOMPENDIUM
JavaScript
Zertifikate
Kapitel 22
Unterschiede gibt es in den folgenden Schritten vor allem dabei, was die Browser mit den Zertifikaten anstellen, welche Technologien zum Zertifizieren verwendet werden und wie die praktische Umsetzung aussieht.
Internet Explorer Der Internet Explorer verwendet für sein Sicherheitskonzept vier Standardsicherheitszonen (siehe EXTRAS/INTERNETOPTIONEN/SICHERHEIT):4 Internet mit höheren Sicherheitsstandards, lokales Internet mit geringeren Standards sowie vertrauenswürdige und eingeschränkte Sites. Kontrolle erhalten Sie über die Option STUFE ANPASSEN. Hier können Sie steuern, ob signierte ActiveX-Controls direkt ausgeführt werden und vieles mehr.5 Das Zertifizierungskonzept von Microsoft – vorhanden seit Internet Explorer 3 und ausgeweitet in Version 46 – dient allerdings nicht dem JavaScriptbzw. JScript-Programmierer, sondern anderen heruntergeladenen Elementen wie beispielsweise Applets oder ActiveX-Objekte. Eine vergleichbare Signierung von externen js-Dateien wie beim Netscape Navigator gibt es nicht. Die Signatur von ActiveX-Controls erfolgt mit dem ActiveX SDK, das unter http://msdn.microsoft.com/code/default.asp?url=/code/sample.asp?url=/msdnfiles/027/000/223/msdncompositedoc.xml erhältlich ist.
Da ActiveX-Objekte Teil der Windows- und nicht der JavaScript-Programmierung sind, verzichten wir hier auf eine Einführung. Der JavaScript-Zugriff auf ActiveX-Objekte funktioniert mit dem ActiveXObject, zu dem Sie unter http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/ html/js56jsobjactivexobject.asp eine Beschreibung finden. Weitere Details zu Authenticode können Sie unter http://msdn.microsoft.com/library/?url=/ workshop/security/authcode/intro_authenticode.asp nachlesen. Die ActiveXControls werden unter http://www.microsoft.com/com/tech/activex.asp und in der MSDN unter http://msdn.microsoft.com/library/default.asp?url=/workshop/ components/activex/intro.asp beschrieben.
4
5 6
Weitere Einstellungen zu Zertifikaten und Sicherheit finden Sie in den Optionen unter ERWEITERT im Bereich SICHERHEIT. Hier können Sie beispielsweise einstellen, das geprüft werden soll, ob Zertifikate ungültig geworden sind. Eine ausführliche Beschreibung der Optionen finden Sie unter http://www.microsoft.com/technet/treeview/default.asp?url=/TechNet/prodtechnol/ie/reskit/ie5/part1/ch06digi.asp. und funktional in weiten Teilen auf Windows beschränkt, da viele der damit gestarteten Funktionalitäten sehr betriebssystemnah sind.
KOMPENDIUM
JavaScript
679
Kapitel 22
JavaScript und Sicherheit
Netscape Navigator und Mozilla Der Netscape Navigator 4.x hat die Technologie des signierten Skripts mit Zertifikat hoffähig gemacht. Nachdem das Zertifikat überprüft und vom Nutzer angenommen wurde, kann der JavaScript-Programmierer hier über Java-Methoden auf zusätzliche Funktionen zugreifen. Sogar die Verwendung von Java-Klassen ist direkt möglich. Warnmeldungen zu Sicherheitsfragen, beispielsweise beim Versenden eines E-Mail-Formulars mit mailto:, fallen weg und auch das Schließen eines Fensters ist nicht mehr an das Skript gebunden, von dem aus es geöffnet wurde. Signieren Signierte Skripten sind für Netscape und Mozilla jar-Archive. Die Umwandlung in die jar-Archive erfolgt mit von Netscape zur Verfügung gestellten Tools. Dazu benötigen Sie die Schlüssel, die Ihnen von der Zertifizierungsstelle zur Verfügung gestellt wurden. Netscape und Mozilla stellen für das Erzeugen von jar-Archiven das Werkzeug SignTool 1.3zur Verfügung.7 Die Verankerung im Quellcode erfolgt je nach Browser unterschiedlich. Der Netscape Navigator 4.x erfordert den Aufruf des Archivs mit dem Attribut archive im <script>-Tag. Der Skriptaufruf benötigt außerdem unbedingt eine ID: <script language="JavaScript" archive="verzeichnis/skript.jar" id="1">
Neuere Netscapes und der Mozilla verwenden dagegen folgende URL, um auf das signierte Skript zuzugreifen. jar:http://www.domain.de/verzeichnis/skript.jar!/index.html
Mehr Informationen erhalten Sie unter http://www.mozilla.org/projects/ security/components/signed-scripts.html.
Unsignierte Skripte testen Wenn Sie mit einer lokalen Datei arbeiten (file:), können Sie sie einfach in den Browser ziehen und dieser fragt dann nach, ob die Datei erweiterte Zugriffsrechte erhalten soll. Netscape 4.x gibt zusätzlich an, dass es sich um ein unsigniertes Skript handelt. Dies funktioniert nur, solange die Datei lokal aufgerufen wird. 7
680
siehe http://developer.netscape.com/software/signedobj/jarpack.html
KOMPENDIUM
JavaScript
Zertifikate
Kapitel 22
Bei einer Datei vom Server – auch einem Testserver (localhost) – funktioniert dies nicht. Hier können Sie mit Codebase principal diese Nachfrage auch für unsignierte Skripten erzwingen. Die Einstellung funktioniert für Netscape 4.x und neuere Versionen leicht unterschiedlich: 1.
Beenden Sie den Browser als Erstes.
2.
Suchen Sie bei Netscape Navigator 4.x nach einer Datei pref.js. Für den Netscape Navigator ab Version 6 heißt die Datei all.js.
3.
Öffnen Sie die Datei in einem Texteditor.
4.
Fügen Sie nun für den Netscape Navigator 4.x folgende Zeile an das Ende der Datei ein: user_pref("signed.applets.codebase_principal_support", true);
5.
Für den Netscape Navigator ab Version 6 suchen Sie nach folgender Zeile: pref("signed.applets.codebase_principal_support", false);
6.
und ändern false in true. Abbildung 22.3: Für den Netscape Navigator 7 Codebase principal ändern.
7.
Starten Sie anschließend den Browser neu. Beachten Sie, dass neuere Versionen des Netscape Navigators gelegentlich mit Quick Launch aktiv bleiben. Sie sollten den Browser zu Beginn komplett beenden, damit die Änderungen wirksam werden.
Mit diesen Einstellungen können Sie testen, ohne eine Signatur zu benötigen.
KOMPENDIUM
JavaScript
681
Kapitel 22
JavaScript und Sicherheit Das folgende Beispiel kennen Sie bereits aus Kapitel 15 »Fenster«. Es öffnet ein neues Fenster in voller Größe des Bildschirms ohne Taskleiste und Rahmen. Das Skript verlangt das Privileg UniversalBrowserWrite, das den Zugriff auf normalerweise unzugängliche Browsereinstellungen erlaubt. netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserWrite");
Diese Anweisungen sind Java-Klassen und Methoden. Dies hat auch einen Grund. Ursprünglich wurde das Sicherheitssystem mit signierten Skripten von Netscape für die Java-Unterstützung ins Leben gerufen, die damit gefährliche Aktionen wie Dateizugriffe problemlos unterstützt hätte. Auch heute noch können Sie mit signierten Skripten auf Java-Klassen und Methoden zugreifen. Damit ist beispielsweise ein Zugriff auf java.io.File für den Dateizugriff möglich. Die Bitte um Privilegien muss, nachdem sie genutzt wurde, wieder beendet werden: netscape.security.PrivilegeManager.disablePrivilege("UniversalBrowserWrite");
Halten Sie den Code-Bereich, für den Sie erweiterte Rechte beanspruchen, möglichst klein. Die Methode revertPrivilege() setzt ein Recht temporär außer Kraft. Hier der vollständige Code: Listing 22.1: Erweiterte Rechte mit signierten Skripten (rechte.html)
open() <script language="JavaScript">
//-->
682
KOMPENDIUM
JavaScript
Zertifikate
Kapitel 22
Hauser und Wenz Abbildung 22.4: Das Skript fordert Rechte an.
Abbildung 22.5: Werden diese verweigert, meldet die Konsole einen Fehler in der JavaMethode enablePrivilege.
Die folgende Tabelle gibt eine Übersicht über wichtige Rechte, die Sie beantragen können. Da für jedes Recht ein neuer Methodenaufruf und eine erneute Bestätigung des Nutzers notwendig ist, gibt es auch übergeordnete Privilegien wie UniversalBrowserAccess, das beispielsweise UniversalBrowserRead und UniversalBrowserWrite enthält. Privileg
Beschreibung
UniversalBrowserRead
Geschützte Browserinformationen auslesen. Risiko: mittel
UniversalBrowserWrite
Geschütze Browserinformationen setzen. Risiko: hoch
UniversalBrowserAccess
Voller Zugriff auf Browserinformationen. Risiko: hoch
UniversalXPConnect
Zugriff auf die Browser-APIs über XPConnect. Risiko: hoch
UniversalPreferencesRead
Auslesen der Voreinstellungen. Risiko: mittel
KOMPENDIUM
JavaScript
Tabelle 22.1: Zugriffsrechte für signierte Skripten
683
Kapitel 22 Tabelle 22.1: Zugriffsrechte für signierte Skripten (Forts.)
JavaScript und Sicherheit
Privileg
Beschreibung
UniversalPreferencesWrite
Setzen von Voreinstellungen. Risiko: hoch
UniversalFileRead
Auslesen von lokalen Dateien. Risiko: hoch
UniversalFileWrite
Schreiben von lokalen Dateien. Risiko: hoch
UniversalFileAccess
Voller Zugriff auf lokale Dateien. Risiko: hoch
UniversalSendMail
Mails frei aus dem Skript und ohne Fehlermeldung versendbar. Risiko: mittel
Andere Browser Opera unterstützt Zertifikate nach dem Standard X509, bietet allerdings keinen darüber hinausgehenden verbesserten Zugriff für JavaScript-Skripten und kein Konzept mit signierten Skripten. Ebenso verhält es sich im Konqueror.
Fazit Für JavaScript-Programmierer bieten signierte Skripten und Zertifikate zwar viele Möglichkeiten, von denen sie schon immer geträumt haben. Dies wird allerdings mit der Annahme erkauft, dass die Nutzer Ihren Sicherheitsbekundungen glauben werden. Dies und der erhebliche Aufwand, der zur Zertifizierung und für die unterschiedlichen Browser betrieben werden muss8, lässt diese Technologien nur für spezielle Anwendungen oder sonstige ausführbare Software, in den seltensten Fällen aber für JavaScriptSkripten sinnvoll erscheinen.
22.3
Skripten absichern
Jeder hat vermutlich schon einmal mit ANSICHT/QUELLCODE, ANZEIGEN/ QUELLTEXT oder der rechten Maustaste einen Blick in den Quellcode einer fremden Seite geworfen, sei es, weil ihm einige Effekte gefallen haben oder er irgendetwas besonders schlimm fand. Dieser Tatbestand an sich ist noch kein Problem, allerdings bekommen viele Programmierer – teils zu Recht – Schweißausbrüche, weil sie Tage in eine Anwendung investiert haben und andere sie in ein paar Minuten klauen.
8
Die Zertifikate selbst lassen sich allerdings relativ einfach »umrüsten« (siehe http://www. thawte.com/html/SUPPORT/devel/multi.html). Allein der Zugriff über signierte Skripten und Java- oder ActiveX-Objekte ist sehr unterschiedlich.
684
KOMPENDIUM
JavaScript
Skripten absichern
Kapitel 22
So einfach mag es zwar nicht sein, dennoch gibt es viele Gründe, die eigenen Skripten zu schützen. Dieser Abschnitt zeigt Ihnen, wie Sie sich schützen und warum es keinen perfekten Schutz gibt. Alle Schutzmethoden, die mit JavaScript funktionieren, lassen sich theoretisch ausschalten, indem JavaScript deaktiviert wird. Seiten ohne JavaScript sollten also theoretisch nicht in den Genuss »geschützter« Seiten kommen.
Rechte Maustaste unterbinden Eine Schutzidee ist, die rechte Maustaste zu unterbinden und stattdessen eine Meldung auszugeben. Dafür gibt es ein eigenes Ereignis onContextmenu. Wenn Sie diesem Ereignis den Wert false zurückliefern, wird das Kontextmenü nicht angezeigt.
Listing 22.2: onContextmenu
(oncontextmenu.html)
NS4.x NS6 a.
NS7
IE4 IE5
a
IE5.5 IE6
O7
M1
K3
Tabelle 22.2: onContextmenu
nicht beim Mac
Leider funktioniert onContextmenu nicht in allen Browsern. Daher müssen Sie für die anderen Browser einen komplizierteren Umweg basteln, der eine Warnmeldung ausgibt. Das Beispiel besteht aus drei Teilen: Die Funktion start() fängt beim Laden der Seite die entsprechenden Mausklickereignisse ab. Die Funktion meldung() gibt eine Meldung aus und liefert false zurück, wenn die Maustaste 2 oder höher gedrückt wurde. Das Ereignis onContextmenu unterstützt die Browser, die es verstehen. Wenn es fehlt, würden diese Browser trotz Warnmeldung ein Kontextmenü anzeigen. Hier der komplette Quellcode: Rechte Maustaste <script language="JavaScript">
KOMPENDIUM
JavaScript
Listing 22.3: Unterdrückung der rechten Maustaste (rechte_maustaste. html)
685
Kapitel 22
JavaScript und Sicherheit window.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP) window.onmousedown=meldung; window.onmouseup=meldung; } else if (document.all) { document.onmouseup=meldung; window.onmouseup=meldung; } } function meldung(e) { if (document.all) { if (event.button >= 2) { alert("Kontext verboten"); return false; } } else if (window.captureEvents){ if (e.which >= 2) { alert("Kontext verboten"); return false; } } else { return true; } }
//-->
Dieses Skript scheitert im Opera 7, da er die linke und die rechte Maustaste beide mit der Nummer 1 versieht. Die Unterdrückung der rechten Maustaste ist leider nicht sehr wirksam. Die Menübefehle können zwar entfernt werden, indem das Fenster ohne Menüleiste geöffnet wird, dennoch bleibt das Skript im Browsercache. Das Tastenkürzel (Strg) + (U) ruft außerdem im Netscape Navigator direkt den Quellcode auf. Auch deaktiviertes JavaScript oder die Eingabe VIEWSOURCE:URL im Internet Explorer hebeln den Schutz aus.
Code in Frames auslagern Die Idee ist bestechend: Sie legen den JavaScript-Code in einen unsichtbaren Frame von einem oder null Pixel Höhe9 und greifen darauf von dem Hauptfenster aus zu (siehe Kapitel 18 »Frames«). Die rechte Maustaste geht nun ins Leere und auch der Aufruf des Seitenquelltextes bringt kein Resultat.
9
686
Nicht in allen Browsern, deswegen besser ein Pixel.
KOMPENDIUM
JavaScript
Skripten absichern
Kapitel 22
Einige Probleme bleiben allerdings bestehen. Jeder, der sich einigermaßen mit HTML auskennt, muss nur den Quelltext des Framesets betrachten und dann den unsichtbaren Frame getrennt öffnen. Aber auch hier fällt dem findigen JavaScript-Programmierer etwas ein. Er erzwingt das Laden einfach immer im Frameset (siehe Kapitel 18.3 »Frames erzwingen und vermeiden«). Dieser Ansatz ist bereits relativ Erfolg versprechend. Er kann allerdings ausgehebelt werden, wenn der Nutzer auf die Dateien im Browsercache zugreift. Der Browsercache befindet sich meist auf der Festplatte. Für den Internet Explorer sollten Sie nach einem Ordner Temporary Internet Files suchen. Der Netscape-Browser und Mozilla erlauben über die Angabe about:cache Zugriff auf die Inhalte des Caches. Dort können Sie auch das lokale Verzeichnis auf der Festplatte nachlesen. about:cache funktioniert außerdem im Opera. Wenn Sie verhindern wollen, dass ein Dokument in den Cache auf der Festplatte gelegt wird, gibt es zwei Wege: Sie setzen mit einer serverseitigen Programmiersprache den HTTP-Header mit folgender Angabe: Pragma: no-cahce
Sie verwenden die entsprechende Anweisung im <meta>-Tag, die jedoch nicht in allen Browsern funktioniert: <meta http-equiv="pragma" content="no-cache">
Dies hilft allerdings nur eingeschränkt, da der Netscape Navigator und der Opera dennoch erlauben, das Dokument aus dem Cache heraus abzuspeichern.
Externe Dateien Das Auslagern von Quellcode in externe Dateien10 macht den Code nicht nur modular auf verschiedenen Systemen verwendbar, sondern hält auch einige Nutzer davon ab, ihn direkt zu klauen. Eine externe JavaScript-Datei hat die Dateiendung .js und wer sie haben möchte, muss in den Quellcode, dort den Verweis auf die externe Datei suchen und den Pfad in die Adressleiste des Browsers eintippen. Der Internet Explorer fragt dann sofort, ob er die Datei speichern oder ausführen soll. Dies macht es dem Besucher sehr einfach. 10 siehe Kapitel 2 »JavaScript in HTML«, Abschnitt 2.1 unter »Externes JavaScript«
KOMPENDIUM
JavaScript
687
Kapitel 22
JavaScript und Sicherheit
Abbildung 22.6: Der Cache des Netscape Navigators 7
Netscape Navigator und Mozilla interpretieren die Datei in den meisten Fällen sofort. Dort finden Sie die Dateien im Browsercache.
Quellcode schwer lesbar machen Nehmen wir an, Sie haben guten und aufwändigen JavaScript-Code geschrieben und wollen nicht, dass er von jedermann geklaut wird. Ihnen ist aber klar, dass gewiefte JavaScript-Programmierer Ihren Quellcode auch bekommen, obwohl Sie Ihnen den Zugang mit den im vorhergehenden Abschnitt beschriebenen Methoden erschwert haben. In diesem Fall ist es nahe liegend, den Code so schwer lesbar wie möglich zu machen. Dazu gibt es einige Tricks, die Sie mit einem guten Texteditor sehr schnell ausführen können: Einrückungen entfernen Unnötige Leerzeichen entfernen Kommentare entfernen, die Sie zur Information und Übersicht im Code haben
688
KOMPENDIUM
JavaScript
Skripten absichern
Kapitel 22
Besonders gemeine Taktiker fügen zusätzlich Dummy-Funktionen ein und benennen Variablen, Funktionen und eigene Objekte sinnlos um. Hier sollten Sie vorsichtig sein und häufig testen, damit das Skript nicht unbrauchbar wird. Fügen Sie charakteristische Elemente oder unsichtbare Zeichenketten in den HTML-Code ein, die Sie dann über eine Suche in einer Suchmaschine wie Google (http://www.google.de) wieder finden können. Sie müssen natürlich die Originalversion des Dokuments behalten, sonst haben Sie sich selbst ausgetrickst.
Quellcode verschlüsseln Die Code-Verschlüsselung muss bei clientseitigem JavaScript natürlich auch clientseitig mit JavaScript erfolgen. Das Prinzip ist immer gleich: Der Code – meist inklusive HTML-Quellcode – wird mit einem bestimmten Algorithmus codiert. Sie fügen den codierten Code in eine Datei ein und decodieren diesen Code mit einer JavaScript-Funktion. Diese Codierung müssen Sie natürlich nicht von Hand vornehmen. Dafür gibt es Freeware und kommerzielle Software, beispielsweise HTML Guard (http:// www.aw-soft.de/htmlguard.html, 15 €), HTML Guardian (http://www.protware. com/, ca. 40 US $) und Webcrypt Pro (http://www.moonlight-software.com/ webcrypt.htm, ca. 30 US $), das beispielsweise auch Grafiken in Einzelteile zerlegt, damit sie nicht zusammen gespeichert werden können. Sogar von Microsoft gibt es eine eigene, kostenfreie Lösung, die allerdings nur mit dem Internet Explorer funktioniert. Es ist der Microsoft Script Encoder, der zur Microsoft Scripting Engine gehört. Die Beschreibung finden Sie unter http://msdn.microsoft.com/library/default.asp?url=/library/ en-us/script56/html/seconscriptencoderoverview.asp, die Engine unter http:// msdn.microsoft.com/downloads/default.asp?URL=/downloads/sample.asp?url=/msdnfiles/027/001/733/msdncompositedoc.xml.
Das Problem dabei ist, dass der Code irgendwie wieder in der Originalfassung in den Browser gelangen muss. Das heißt, es gibt eine zugehörige document.write()- oder eval()-Anweisung, in der der Code decodiert und ausgegeben wird. Wenn ein Programmierer das Skript an dieser Stelle umschreibt und die Ausgabe beispielsweise in ein Textfeld leitet, hat er die Codierung umgangen. Ein zweites Problem besteht darin, dass der Nutzer unbedingt JavaScript benötigt, damit er die Seite sehen kann.
KOMPENDIUM
JavaScript
689
Kapitel 22
JavaScript und Sicherheit
Sichern oder nicht? Lassen Sie sich Ihren Code klauen! Denn für jede Verschlüsselung gibt es eine Entschlüsselung. Und diejenigen, die diese Entschlüsselung nicht kennen, sind Ihnen – als mittlerweile versiertem JavaScript-Programmierer – ohnehin nicht gewachsen und können Ihren Quellcode sicherlich kaum auf die eigene Seite übertragen. Für die meisten JavaScript-Probleme gibt es im Netz hunderte von – mehr oder meist weniger – guten Lösungen. Das Besondere an Ihrer Lösung ist, dass Sie sie auf Ihre Bedürfnisse angepasst haben und das lässt sich nicht klauen. Sie können durchaus auch auf den Open Source-Gedanken in der Webgemeinschaft vertrauen. Wenn Sie ein gutes Skript unter Ihrem Namen zur Verfügung stellen und nur um eine Erwähnung bitten und Ihre Urheberschaft in einen Kommentar in den Quellcode schreiben, werden das die meisten Entwickler zu schätzen wissen und sich daran halten. Ein Copyright-Vermerk macht vielen erst klar, dass sie geistiges Eigentum vor sich haben.11 Von dieser Ansicht mag es Ausnahmen geben. Eine ist vielleicht ein aufwändig per JavaScript gestaltetes Spiel, das Sie exklusiv verwenden möchten. Sollte es sie tatsächlich stören, wenn es irgendwo in den Tiefen des Webs auftaucht, dann verwenden Sie am besten alle erwähnten Methoden, wobei für die Verschlüsselung ein automatisiertes Tool am besten geeignet ist. Sie sollten hier so wenig wie möglich Arbeitsschritte benötigen, Ihren Originalcode umzuwandeln, denn sonst werden Updates am Code zur Qual.
22.4
Passwortschutz mit JavaScript
Der clientseitige Passwortschutz mit JavaScript hat immer ein Problem. Irgendwo steht das Passwort und/oder die URL des geschützten Bereichs im Quellcode. Und wie Sie in Kapitel 22.3 »Skripten absichern« gesehen haben, kann der Code nicht vollständig geschützt werden. Speichert man das Passwort in ein Cookie, kann es auch dort vom Nutzer ausgelesen werden. Was bedeutet dies für eine Passwortüberprüfung in JavaScript? Sie ist immer knackbar. Das macht sie unsinnig. Sie sollten also auf eine serverseitige Passwortüberprüfung zurückgreifen. Serverseitig haben Sie außerdem die Möglichkeit das Sessionmanagement einzusetzen. Eine Session ist eine Sitzung. Der Nutzer kann anhand seiner Session-ID nach einem Login über den Verlauf einer Sitzung als eingeloggt festgestellt werden. Das Passwort kann in einer Datei oder Datenbank auf dem Server liegen. Es kann also vom Nutzer nicht ausgelesen werden. 11 Siehe hierzu auch den durchaus unterhaltsamen Link http://www.templetons.com/brad/ copymyths.html.
690
KOMPENDIUM
JavaScript
23
Kommunikation mit der Außenwelt
Bis jetzt stand JavaScript im Zentrum der Aufmerksamkeit. Das soll zwar auch in diesem Kapitel so bleiben. Dazu gesellt sich allerdings noch ein zweiter wichtiger Kommunikationspartner. Den Anfang macht Java. Java-Applets sind zwar lange nicht mehr so populär wie vor einigen Jahren, es bleibt dennoch interessant zu sehen, wie JavaScript auf Java-Klassen und -Methoden zugreifen und damit die eigenen Möglichkeiten erweitern kann. Die Steuerung von Sound und Multimedia ist immer eine Steuerung von Plugins in den Browsern, die für das Abspielen solcher Dateien notwendig sind. Diese Steuerung erlaubt zwar einiges, unterscheidet sich aber in den Browsern und auf verschiedenen Betriebssystemen stark. Zum Schluss sehen Sie, wie Flash mit JavaScript interagieren kann. Nicht nur dass die Skriptsprache von Flash, ActionScript, ebenfalls an ECMAScript angelehnt ist, es gibt auch Kommunikationsmöglichkeiten zwischen dem Flash-Player, also ActionScript, und JavaScript im Browser.
23.1
Java
Serverseitig, im Großrechnerbereich und bei Firmenkunden gewinnt Java, die Programmiersprache der Firma Sun, immer mehr an Bedeutung. Clientseitig sieht das ein wenig anders aus: Java-Applets benötigen eine Java Virtual Machine. Diese ist zwar bei vielen Plattformen und Betriebssystemen dabei1, allerdings sind die kleinen Applet-Fenster im Browserfenster nicht sehr flexibel und die Performance ist manchmal nicht so gut. Die Performance-Schwäche von gerade älteren Java-Versionen hat einen einfachen technischen Grund: Der Java-Code muss von der Virtual Machine noch zur Laufzeit kompiliert werden. Dieser Vorgang kostet einige Zeit. Dennoch sind Java-Applets für manche besondere Anwendungen durchaus eine Überlegung wert.
1
Eine Ausnahme ist hier beispielsweise Windows XP, da Sun und Microsoft diesbezüglich schon länger in einem Rechtsstreit liegen.
KOMPENDIUM
JavaScript
691
Kapitel 23
Kommunikation mit der Außenwelt Mit JavaScript haben Sie drei Kommunikationsmöglichkeiten mit Java2: Sie können Java-Klassen direkt aus JavaScript aufrufen. Dies funktioniert über die Technologie Liveconnect, die jedoch nur der Netscape Navigator und der Mozilla unterstützen. Sie haben die Möglichkeit, per JavaScript auf Methoden in Java-Applets zuzugreifen. Sie können aus Java auf JavaScript-Objekte, beispielsweise das Browserfenster, zugreifen. Diese drei Möglichkeiten finden Sie in den nächsten Abschnitten.
Liveconnect Liveconnect, vollständig integriert im Netscape Navigator 4.x, erlaubt den Zugriff auf Java-Klassen, die direkt in den Browser integriert sind. Der Zugriff erfolgt immer über die Basisklasse Packages.java, die in Kurzform auch java geschrieben werden kann. Liveconnect ist beschränkt auf den Netscape Navigator und Mozilla. Version 4.6 hat kein Liveconnect integriert, in Version 6 des Browsers gibt es keine Implementierung. Sie wurde mit der Unterversion 6.1 nachgeholt. Das folgende Beispiel zeigt, wie der Konstruktor new ein eigenes Java-Fenster als Objekt erzeugt: Listing 23.1: Auf Java ohne Applet zugreifen (java_ohne_applet. html)
Java ohne Applet <script language="JavaScript">
} //--> Java-Applet-Fenster öffnen
2
692
Ausgenommen ist hier serverseitiges Java, beispielsweise in Form von Enterprise Java Beans.
KOMPENDIUM
JavaScript
Java
Kapitel 23 Abbildung 23.1: Das Java-Fenster
Manche Klassen erlauben nur den Zugriff über signierte Skripte3. Dazu gehört java.io.file, das den Zugriff auf lokale Dateien ermöglicht. Hierzu ist das Privileg UniversalFileAccess notwendig.
Zugriff auf Java-Applets Der zweite Kommunikationsweg zwischen JavaScript und Java ist der Zugriff von JavaScript auf Methoden des Java-Applets. Liveconnect und ActiveX heißen hier die entsprechenden Technologien von Netscape bzw. Internet Explorer. Dankenswerterweise funktionieren beide sehr ähnlich, deswegen ist keine Browserunterscheidung notwendig. Ein Applet wird mit dem -Tag in den Code eingebunden: Kein Java vorhanden
Verwenden Sie ein Mini-Java-Applet mit einer Größe von 1*1 Pixel, wenn Sie Java-Klassen und -Methoden benötigen ohne ein sichtbares Applet auf der Seite. Der Zugriff darauf erfolgt entweder über die applets-Kollektion und den Index: document.applets[0]
oder über die Kollektion und den Namen:
3
Siehe Kapitel 22 »JavaScript und Sicherheit«
KOMPENDIUM
JavaScript
693
Kapitel 23
Kommunikation mit der Außenwelt document.applets["Applet1"]
oder direkt über den Applet-Namen. document.Applet1
Das eigentlich Interessante ist der Zugriff auf Methoden innerhalb des Applets: Mit document.Applet1.Methode();
erhalten Sie Zugriff auf alle Methoden des Applets, die als public definiert wurden. Dies sieht in Java folgendermaßen aus: public class { public void Methode() { Anweisungen; } }
Beim Methoden-Aufruf können durchaus auch Parameter übergeben werden: document.Applet1.Methode(Parameter1, Parameter2);
Bei Parametern erfolgt eine (automatische) Datentyp-Umwandlung, die in der Praxis meist problemlos abläuft: JavaScript-Objekte werden in JSObjectObjekte umgewandelt, Zahlen (Datentyp Number) in Float. Java-Applets steuern Ein Java-Applet muss kompiliert werden. Dazu benötigen Sie das Java SDK, das mittlerweile in der Version 1.4 vorliegt. Da allerdings die meisten Browser mit einer älteren Version (oder gar keiner) vorlieb nehmen müssen, sollten Sie auf Nummer sicher gehen. Am sichersten erscheint dabei das Java Development Kit 1.1.8. Sie finden es auf der CD-ROM im Ordner software/javasdk und unter http://www.sun.com im Download-Archiv. Im Folgenden sehen Sie ein Beispiel aus dem Java Development Kit. Sie finden es im Programmordner (meist jdk1.1.8) unter demo/clock. Die Uhr hat den Namen clock2.class.4 .class ist die Dateiendung für ein kompiliertes 4
694
Die Uhr findet sich auch in den neueren Versionen des Development-Kits im demo-Ordner. Allerdings besitzt sie teilweise unterschiedliche Namen, im SDK 1.4 beispielsweise nur Clock.class.
KOMPENDIUM
JavaScript
Java
Kapitel 23
Java-Applet. Der Quellcode ist ebenfalls vorhanden und hat immer die Endung .java. Natürlich können Sie auch auf ein eigenes Java-Applet zurückgreifen, dessen öffentliche Methoden Sie kennen. Die Uhr besitzt zwei öffentliche Methoden start() und stop(),deren Namen schon ihre Aufgabe verraten: Sie lassen die Uhr laufen und halten sie an. Die Verwendung dieser Methoden mit JavaScript ist also unproblematisch: Java-Applet steuern <script language="JavaScript">
Listing 23.2: Ein Java-Applet steuern (java_applet.html)
document.uhr.start();
} function stop() { document.uhr.stop();
} //-->
Uhr starten
Uhr stoppen Abbildung 23.2: Das Java-Applet wird per JavaScript »ferngesteuert«.
KOMPENDIUM
JavaScript
695
Kapitel 23
Kommunikation mit der Außenwelt Java-Unterstützung Mit dem Zugriff auf Java-Applets gibt es zwei Probleme: Die Frage, ob eine Java Virtual Machine vorhanden ist. Die Java-Unterstützung prüft die Funktion navigator.javaEnabled(). Sie kann also zu einer Fallunterscheidung dienen, liefert allerdings nicht die Versionsnummer, sondern nur einen Boolean. Das zweite Problem ist, dass Methodenaufrufe ins Leere gehen, wenn das Applet noch nicht geladen ist. Auch dies kann über eine Prüfung abgefangen werden, denn das Applet liefert den Wert 0, wenn es noch nicht vollständig geladen ist. Folgende Zeile dient zur Überprüfung: if(document.Appletname != null) document.Appletname.Methode();
Java zu JavaScript Der andere Weg von Java zu JavaScript bedarf ebenfalls einiger vorbereitender Schritte: Java benötigt zusätzliche Pakete, um auf JavaScript zuzugreifen. Diese Pakete müssen Sie in Java importieren: import netscape.javascript.*;
Schwieriger ist es, die Pakete dem Compiler bekannt zu machen. Es gibt hier mehrere Wege, wovon nur einer beschrieben werden soll: 1.
Die zwei benötigten Klassen netscape.javascript.JSObject und netscape.javascript.JSException werden beispielsweise beim Netscape Navigator 4.x mitgeliefert. Sie sind im Paket java40.jar versteckt.
2.
Dieses Paket muss dem Compiler beim Kompiliervorgang angegeben werden. Am einfachsten erfolgt das mit dem classpath.
3.
Nehmen Sie beispielsweise an, Sie hätten das Paket in das Unterverzeichnis lib der JDK (jdk1.1.8) gelegt und die Datei befände sich im bin-Verzeichnis5: javac –classpath ..\lib\java40.jar ausgabe.java
5
696
Dies dient der Vereinfachung, normalerweise haben Sie längere Pfadangaben.
KOMPENDIUM
JavaScript
Java
Kapitel 23
Sollten Sie einen anderen Compiler oder eine andere Konfiguration verwenden, unterscheiden sich natürlich die Pfade. Egal, wo Sie die Bibliotheken für classpath abgelegt haben, der Browser findet sie beim Anwenden des Applets, wenn sie beim Browser mitgeliefert werden. Das Java-Applet benötigt die Erlaubnis für den Skript-Zugriff. Dieser wird über das Attribut mayscript des -Tags gesteuert. Kein Java vorhanden
Applet und Einbau Ein einfaches Beispiel verdeutlicht die Java-zu-JavaScript-Kommunikation. Das Herzstück ist die JSObject-Klasse in Java. Sie erlaubt den Zugriff auf alle JavaScript-Objekte. Der erste Schritt dazu ist immer die Methode getWindow(Applet), die das übergeordnete window-Objekt des Java-Applets liefert. Mit der Methode eval("String") kann dann JavaScript-Code ausgeführt werden. Im Beispiel wird sie verwendet, um eine einfache Ausgabe mit alert() zu starten. Mit der Funktion getMember(Eigenschaft) haben Sie die Möglichkeit, auf Eigenschaften von Objekten zuzugreifen. Folgende zwei Zeilen realisieren in Java den Zugriff auf ein Eingabefeld im HTML-Formular: JSOject feld = fenster.eval("document.formular.eingabe"); String inhalt = (String) feld.getMember("value");
Hier der vollständige Code des Applets: import java.awt.*; import java.lang.*; import java.applet.Applet; import netscape.javascript.*;
Listing 23.3: Ausgabe mit JSObject (ausgabe.java)
public class ausgabe extends java.applet.Applet { public void init() { JSObject fenster = JSObject.getWindow(this); fenster.eval("alert('Hallo von Java!')");
} }
Das Applet müssen Sie nun kompilieren. Sollte dies nach der Anleitung im letzten Abschnitt nicht klappen, finden Sie die kompilierte Datei mit dem Namen ausgabe.class auf der CD-ROM im Ordner code\kap23.
KOMPENDIUM
JavaScript
697
Kapitel 23
Kommunikation mit der Außenwelt Im nächsten Schritt bauen Sie das Applet in die Seite ein. Vergessen Sie dabei nicht das Attribut mayscript im -Tag:
Listing 23.4: Von Java zu JavaScript (java_javascript.html)
Java zu JavaScript
Abbildung 23.3: Das Java-Applet meldet sich in JavaScript.
Die Datentyp-Umwandlung von Java in JavaScript ist unter Umständen schwieriger als der umgekehrte Weg. Beispielsweise steht der Java-Datentyp long für einen 64 Bit-Integer, der sich in JavaScript aber nur mit 32 Bit abspeichern lässt. Auch die Rückumwandlung von Arrays und Objekten kann im Einzelfall Probleme bereiten.
23.2
Sound und Multimedia
Die Sound- und Video-Steuerung mit JavaScript ist vor allem eines: eine Plugin-Kontrolle. Skripten haben nur direkten Zugriff auf die in Browsern integrierten Plugins. Hier gibt es, wie Sie wohl schon vermutet haben, mehrere Ansätze:
698
KOMPENDIUM
JavaScript
Sound und Multimedia
Kapitel 23
Netscape LiveAudio. Ein Netscape-Plugin, das skriptfähig ist. Leider wird es bei vielen Browser-Versionen nicht mehr mitinstalliert. Microsoft Windows Media Player. Beim Media Player finden Sie leichte Unterschiede zwischen Version 6.4 und höheren Versionen. Für Windows 95 gibt es zusätzlich die ActiveX-Komponente ActiveMovie. Apples QuickTime ab Version 4.1 bietet ebenfalls JavaScript-Unterstützung, allerdings nur eingeschränkt. RealPlayer G2 und höher. Er bietet – als erster RealPlayer – volle Steuerbarkeit über JavaScript, die sogar Eingriffe in das Aussehen der Oberfläche des Players erlaubt. Die Aufgaben des JavaScript-Programmierers sind nun vielfältig: Er muss die Einbindung beherrschen und erkennen, ob das richtig Plugin vorhanden ist, um dann das Plugin über JavaScript zu steuern. Auf Grund der vier verschiedenen Ansätze haben wir folgende Lösung gewählt: Netscape LiveAudio und der Windows Media Player werden zusammen in einem Skript ausgewertet und jeweils verwendet. Apple QuickTime und RealPlayer stehen als Plugin für beide Browser zur Verfügung und werden deswegen einzeln abgehandelt.
In die Website einbinden Der erste Schritt beim Einbinden von Multimedia-Dateien ist die Einbindung in HTML. Zu diesem Zweck besaß der Netscape Navigator lange Zeit das <embed>-Tag, das es aber nie in den W3C-Standard geschafft hat. Microsoft hat stattdessen das -Tag vorgeschlagen und neben <embed> seit dem Internet Explorer 4 implementiert.
<embed>
NS4x
NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 23.1: <embed> und
Um Netscape 4.x-Nutzer nicht auszuschließen, hat sich die Verschachtelung von und <embed> etabliert. Netscape 4.x ignoriert das ihm unbekannte -Tag und die zugehörigen <param>-Tags: <param name="src" value="video.asf"> <embed src="video.asf" name="player1" mastersound>
KOMPENDIUM
JavaScript
Listing 23.5: Multimedia-Dateien einbinden (einbinden.html)
699
Kapitel 23
Kommunikation mit der Außenwelt Beachten Sie die dazugehörigen Attribute für das <embed>-Tag: Wichtig ist das Attribut mastersound, ohne das der Navigator 4.x stumm bleibt. Das Attribut autostart legt fest, ob der Sound oder das Video sofort loslegt (true) oder nicht (false). hidden versteckt den Player (true). Standardeinstellung ist false.
Das -Tag kennt ebenfalls ein wichtiges Attribut: Das Attribut classid im -Tag gibt eine Art Plugin-Identifikation an. Die folgende Tabelle zeigt eine Übersicht. Tabelle 23.2: Die IDs einiger wichtiger Technologien
Technologie
classid (Component Identifier)
Apple QuickTime
02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
Macromedia Flash Player
D27CDB6E-AE6D-11cf-96B8-444553540000
Macromedia Shockwave Player
166B1CA-3F9C-11CF-8075-444553540000
RealPlayer
CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA
Windows Media Player 6.4
22D6f312-B0F6-11D0-94AB-0080C74C7E95
Windows Media Player 7/8
6BF52-394A-11D3-B153-00C04F79FAA6
Neben diesen Attributen können Sie für beide Tags die Höhe (height) und Breite (width) festlegen.
Plugin-Erkennung Das navigator-Objekt besitzt die Methode plugins() zum Auslesen der Plugins im Browser. Zurückgeliefert wird ein Array mit allen Plugins. Ein einzelnes Plugin können Sie mit seinem Index oder seinem Namen ansprechen. Ein Plugin-Objekt besitzt dann vier Eigenschaften: description – eine Beschreibung. filename – lokaler Dateiname des Plugins. length – die Anzahl der unterstützten MIME-Typen. name – der Name des Plugins.
700
KOMPENDIUM
JavaScript
Sound und Multimedia
Kapitel 23
Das folgende Skript liest die Eigenschaften aus: plugins() <script language="JavaScript">
Listing 23.6: Plugins ausgeben (plugins.html)
(var i= 0; i
Sie können für eine Übersicht der Plugins im Netscape Navigator auch direkt about:plugins in die Adressleiste eingeben. Neben diesen Methoden besitzt plugins() noch die Methode refresh(Aktivieren). Sie kann als Parameter true übernehmen, um die Liste mit Plugins zu aktualisieren.
a.
NS4x
NS6
NS7
IE4 IE5 a
()
IE5.5 IE6
O7
M1
K3
Tabelle 23.3: navigator.plugins()
Nur Mac.
Das Problem mit der Methode plugins() ist, dass der Internet Explorer sie nicht unterstützt. Er liefert bei Aufruf dieser Methode allerdings true zurück, wenn ein soundfähiges ActiveX-Control, also der Windows Media Player oder Active Movie, vorliegt. Der Internet Explorer ab Version 5 für Mac unterstützt navigator.plugins() vollständig. Er besitzt jedoch keine skriptfähige Erweiterung und kein ActiveX-Control, das heißt die Steuerungsbemühungen scheitern.
KOMPENDIUM
JavaScript
701
Kapitel 23
Kommunikation mit der Außenwelt Wollen Sie feststellen, ob ein ActiveX-Control vorhanden ist, können Sie eine andere Methode verwenden:
Listing 23.7: Überprüfung, ob der Windows Media Player vorhanden ist (activex.html)
var control = new ActiveXObject("MediaPlayer.MediaPlayer.1"); alert(control); if(control) { alert("Media Player vorhanden"); }
Abbildung 23.4: Der Windows Media Player ist vorhanden.
MIME-Typen Der MIME-Type (Multipurpose Internet Mail Extension)6 lässt sich ebenfalls aus der plugins-Kollektion gewinnen. Der Zugriff darauf ist mit einem weiteren Array möglich: navigator.plugins["Name"]["Name"]
Alternativ können Sie auch bei beiden den Index nehmen oder mischen. Eine weitere Möglichkeit besteht darin, die mimeTypes-Kollektion zu verwenden. Sie speichert in der Eigenschaft type den Namen des MIME-Types und in enabledPlugin einen Boolean, der angibt, ob dafür ein Plugin vorhanden ist. Mit diesem Wissen lässt sich die Überprüfung aus Listing 23.6 noch ein wenig ausweiten: Listing 23.8: Unterstützte MIMETypen werden mit ausgegeben (mime.html).
for (var j = 0; j < navigator.plugins[i].length; j++) { t += ""+navigator.plugins[i][j].type + "
"; }
6
702
Ursprünglich eine Standardisierung für E-Mail-Anhänge, dann zur Erkennung von DateiArten verwendet.
KOMPENDIUM
JavaScript
Sound und Multimedia
Kapitel 23 Abbildung 23.5: Einige Plugins mit MIME-Typen
Steuerungsmöglichkeiten Die Steuerungsmöglichkeiten besitzen je nach verwendeter Technologie deutliche Unterschiede. Die folgende Tabelle zeigt die wichtigsten Steuerungsmöglichkeiten der bekanntesten Abspieltechnologien:
KOMPENDIUM
JavaScript
703
Kapitel 23
Kommunikation mit der Außenwelt
Netscape LiveAudio
Internet Explorer ActiveMovie
Internet Explorer WMP 6.4
Internet Explorer WMP 7+
Apple Quick- RealPlayer Time Ab 4.1
Wiedergabe
play(Schleife)
play()
play()
play()
play()
DoPlay()
Pause
pause()
pause()
pause()
pause()
pause()
DoPause()
Stopp
stop()
stop()
stop()
stop()
stop()
DoStop()
Abspielstatus
IsPaused() IsPlaying() IsReady() – komplett geladen
CurrentState 0: Stopp 2: Pause 3: Abspielen
PlayState 0: Stopp 2: Pause 3: Abspielen
PlayState 1: Stopp 2: Pause 3: Abspielen
-
GetPlayerState() 0: Stopp 3: Abspielen 4: Pause
Lautstärke
GetVolume() SetVol()
volume
volume
volume
getVolume() SetVolume()
GetVolume() SetVolume()
Position / Start / Ende
- / start_time(Sekunde) / end_time(Sekunde)
current Position / selectionStart / selectionEnd
currentPosition / selectionStart / selectionEnd
current Position / selectionStart / selectionEnd
getTime() / setTime() mit play() / setStartTime() / setEndTime()
GetPosition() / SetPosition()
Tabelle 23.4: Steuerungsmöglichkeiten für verschiedene Player
Diese Tabelle kann nur eine grobe Übersicht über die wichtigsten Multimedia-Plugins geben. Weiterführende Informationen zu QuickTime und RealPlayer finden Sie in den nächsten beiden Abschnitten. Das Objektmodell des neuen Windows Media Player 9-ActiveX-Controls finden Sie unter http://msdn.microsoft.com/library/default.asp?url=/library/ en-us/wmplay/mmp_sdk/windowsmediaplayeractivexcontrol.asp. Die Variante für den Player 6.4 steht unter http://msdn.microsoft.com/ library/default.asp?url=/library/en-us/wmp6sdk/htm/microsoftwindowsmediaplayer controlversion64sdk.asp.7
Apple QuickTime Ab Version 4.1 von QuickTime hat Apple eine JavaScript-Unterstützung eingebaut. Sie müssen dazu enablejavascript im <embed>-Tag auf true setzen. Die bekannten Steuerungsbefehle sind: Play() zum Abspielen und Stop() zum Anhalten (nicht auf den Anfang zurück). 7
704
Da es den Windows Media Player auch als Netscape-fähiges Plugin gibt, lässt er sich dort skriptfähig ansprechen. Die Methoden sind weitgehend gleich.
KOMPENDIUM
JavaScript
Sound und Multimedia
Kapitel 23
Leider funktioniert die JavaScript-Unterstützung nur in QuickTime ab 4.1 und 5 nur in Netscape 4.x. Mit QuickTime 6 gibt es Skript-Fähigkeiten auch für Netscape 6, 7, Mozilla und für die ActiveX-Komponente des Internet Explorers unter Windows. Ausgesperrt wird der Internet Explorer für Macintosh, der mit ActiveX nichts anfangen kann. Mehr Informationen über die Skript-Fähigkeiten von QuickTime erhalten Sie unter http://developer.apple.com/techpubs/quicktime/qtdevdocs/REF/QT41_ HTML/QT41WhatsNew-72.html und für QuickTime 6 unter http://developer. apple.com/techpubs/quicktime/qtdevdocs/PDF/whats_new_qt6.pdf.
RealPlayer Die Steuerung des RealPlayers ab Version G2 ist im Prinzip sehr einfach: Sie binden die Real-Datei ein und haben dann über den Namen (<embed>) bzw. die ID (object) Zugriff. Das folgende Beispiel verwendet die Steuerungsbefehle: RealPlayer <script language="JavaScript"> <param name="src" value="datei.rm"> <embed src="datei.rm" name="real">
KOMPENDIUM
JavaScript
705
Kapitel 23
Kommunikation mit der Außenwelt Beispieldateien erhalten Sie auf der Real-Homepage http://www.real.com oder auch bei http://www.amazon.de. Weitere Informationen zur RealPlayer API mit vielen Steuerungsmöglichkeiten finden Sie unter http://service.real.com/ help/library/guides/realonescripting/ScriptingGuide.pdf.
Fazit Insgesamt bleiben die JavaScript-Steuerungsmöglichkeiten mehr oder weniger nur auf einen Player beschränkt. Auf unterschiedliche Player und Plattformen zu reagieren, erfordert eigentlich je zwei selbstständige Skripte. Die Ähnlichkeiten zwischen LiveAudio und dem Windows Media Player zu nutzen, macht heute kaum noch Sinn, da LiveAudio in den aktuellen Netscape Browsern nicht mehr integriert ist. Als Standards in Bezug auf SkriptZugriff kristallisieren sich immer mehr der Windows Media Player, der RealPlayer und mit Einschränkungen der QuickTime heraus. Wer selbst ein Netscape-kompatibles Plugin schreibt, findet interessante Informationen zur neuen Mozilla API für Scripting-Schnittstellen unter http://www.mozilla.org/projects/plugins/scripting-plugins.html.
23.3
Flash
Flash ist ein Quasi-Standard für Vektoranimationen im Internet. Die Entwicklungsumgebung Flash und das Format SWF (Shockwave Flash)8 stammen von der Firma Macromedia.9 Flash besitzt eine eigene Skriptsprache namens ActionScript; die seit Flash 5 wie JavaScript auf ECMAScript basiert. Das heißt für alle, die JavaScript können, ist ActionScript sehr leicht zu erlernen (und umgekehrt). Die Ähnlichkeit der beiden Sprachen ist allerdings nicht das einzige Bemerkenswerte. Macromedia hat in den Flash-Player auch Austauschmöglichkeiten zwischen JavaScript und Flash eingebaut. Beide Kommunikationsrichtungen sind möglich, wie die nächsten beiden Abschnitte zeigen werden.
8
9
706
Nicht zu verwechseln mit dem Macromedia Shockwave-Format, das ein Exportformat von Macromedia Director ist. Director wird hauptsächlich für CD-ROM-Produktion und Lernanwendungen verwendet. Der Flash-Player wird bei fast jedem Browser mitgeliefert, das Plugin ist sehr klein und das Format weit verbreitet. Dennoch ist SWF nur ein halboffener Standard. Weiterentwicklungen und damit ein Zeitvorsprung liegen in den Händen von Macromedia. Ein standardisiertes, XML-basiertes Konkurrenzformat ist SVG (Scaleable Vector Graphics) (http:// www.w3.org/Graphics/SVG).
KOMPENDIUM
JavaScript
Flash
Kapitel 23
Die Einbindung eines Flash-Films erfolgt mit und <embed>. Flash erledigt dies beim Veröffentlichen des Films in der Entwicklungsumgebung auch selbst. Hier der produzierte Code: <EMBED src="wuerfel.swf" quality=high bgcolor=#FFFFFF WIDTH="550" HEIGHT="400" NAME="wuerfel" ALIGN="" TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/ go/getflashplayer">
Die classid stellt Flash dankenswerterweise selbst ein. Ansonsten können Sie die Einstellungen natürlich auch anpassen.
JavaScript zu Flash Der Zugriff auf den Flash-Film erfolgt ähnlich wie bei Musikstücken über den Namen (<embed>) bzw. die ID (). Name und ID sollten natürlich gleich sein. Den swf-Film wuerfel.swf und die Flash-Datei finden Sie beide auf der beiliegenden CD-ROM im Ordner code\kap23. Der Film zeigt einen fliegenden Würfel und ist wirklich einfach zu realisieren. Die zugehörige HTML-Seite, die Flash generiert hat, heißt wuerfel.html. Zuerst müssen Sie in der Seite wuerfel.html das Attribut swLiveConnect="true" setzen, damit auch Netscape 4.x auf den Flash-Film zugreifen kann. Fügen Sie in die HTML-Seite drei Schaltflächen für Start, Pause und Stopp hinzu. Die dazugehörigen Funktionen sehen so aus: function play() { document.wuerfel.Play(); } function pause() { document.wuerfel.StopPlay(); } function stop() { document.wuerfel.Rewind(); }
Listing 23.10: Flash-FilmSteuerung aus JavaScript (wuerfel_modifiziert.html)10
10 Dieses Skript versagt – obwohl offensichtlich korrekt – in manchen Mozilla- und Netscape-Versionen. Entsprechende Bug-Reports liegen beispielsweise in Bugzilla vor.
KOMPENDIUM
JavaScript
707
Kapitel 23
Kommunikation mit der Außenwelt
Abbildung 23.6: Den Flash-Film anhalten
Der Internet Explorer verwendet standardmäßig den Zugriff mit window.Filmname, kennt allerdings document.Filmname ebenfalls. Wollen Sie auf Nummer sicher gehen, können Sie eine Fallunterscheidung einfügen. Eine solche Datei finden Sie auf CD-ROM unter dem Namen wuerfel_ sicher.html im Verzeichnis code\kap23. Methoden Die im letzten Beispiel eingesetzten Methoden waren natürlich nicht die einzigen für den Zugriff auf Flash. Die folgende Tabelle gibt eine Übersicht: Tabelle 23.5: Methoden zur Flash-Steuerung aus JavaScript
708
Methode
Beschreibung
GetVariable(Name)
Liefert den Wert einer ActionScript-Variablen Name.
GotoFrame(Nummer)
Springt zu einer Frame-Nummer im Film. Der Film läuft nicht weiter.
IsPlaying()
Prüft, ob der Film abgespielt (true) oder angehalten wird (false).
KOMPENDIUM
JavaScript
Flash
Kapitel 23
Methode
Beschreibung
LoadMovie(Position, Datei)
Lädt einen Film auf das angegebene Level. Entspricht weitgehend der LoadMovie-Methode in ActionScript.
Pan(x, y, Modus)
Schwenkt einen gezoomten Bereich. x und y stehen für die x- und y-Koordinate, wenn der Modus den Wert 0 hat. Ansonsten stehen sie für Prozentwerte.
PercentLoaded()
Liefert, wie viel Prozent von 0 bis 100 eines Films geladen wurden.
Play()
Spielt den Film ab.
Rewind()
Setzt den Film auf den ersten Frame und stoppt ihn.
SetVariable(Name, Wert)
Setzt eine ActionScript-Variable Name auf den Wert.
SetZoomRect (l, o, r, u)
Zoomt einen rechteckigen Bereich aus dem Film. Die Koordinaten für links (l), oben (o), rechts (r) und unten (u) werden in twips angegeben. Auf ein Inch kommen 1140 twips.
StopPlay()
Hält den Film an.
TotalFrames()
Anzahl der Frames im Film.
Zoom(Faktor)
Verkleinert oder vergrößert den Film relativ zu einer Basis von 100.
Tabelle 23.5: Methoden zur Flash-Steuerung aus JavaScript (Forts.)
Alle hier vorgestellten Methoden funktionieren seit dem Flash Player 4, viele sogar noch länger. Proprietäre Erweiterungen des ActiveX-Controls und undokumentierte Methoden berücksichtigt die Tabelle nicht und Sie sollten im Praxiseinsatz darauf verzichten. Neben den hier genannten allgemeinen Methoden gibt es noch Tell-Target-Methoden für die Arbeit mit einzelnen Movieclips (vormals Filmsequenzen).
Flash zu JavaScript In ActionScript, der Skriptsprache von Flash, gibt es zwei Wege, mit JavaScript zu kommunizieren: Die Methode fscommand(Befehl, Parameter), mit der Sie ein Kommando übertragen und als optionale Angabe eigene Parameter übergeben können. Die Kommandos waren ursprünglich dafür vorgesehen, dem Flash-Player Befehle zukommen zu lassen, was auch heute noch möglich ist. Alternativ erlauben sie aber auch die Kommunikation mit JavaScript.
KOMPENDIUM
JavaScript
709
Kapitel 23
Kommunikation mit der Außenwelt Die zweite Alternative ist getURL(), mit der Sie einen Link angeben können. Verwenden Sie dort einen JavaScript-Link, haben Sie schon einen Aufruf einer JavaScript-Funktion: fscommand() Der Einsatz von fscommand() ist ein wenig aufwendig, da Sie wie erwähnt nicht direkt mit JavaScript-Befehlen arbeiten können. Ein Beispiel zeigt dies: Ausgangspunkt ist eine Flash-Datei mit einem Eingabefeld und einer Schaltfläche. Klickt der Nutzer auf die Schaltfläche, wird fscommand() ausgeführt: on (release) { fscommand("Ausgabe", text); }
Der Code gibt als Befehl »Ausgabe« und übergibt als Parameter den Wert des Textfeldes, der vorher in Form einer Variablen im Eigenschafteninspektor angegeben wurde. Sie finden die Datei unter dem Namen fscommand.fla auf der CD-ROM im Ordner code\kap23. Nachdem die Flash-Datei fertig ist, sind folgende Schritte notwendig: 1.
Sie müssen die Flash-Datei veröffentlichen. Hierzu gibt es in den Einstellungen für das Veröffentlichen (DATEI/EINSTELLUNGEN FÜR VERÖFFENTLICHUNGEN) im Register HTML die Option Flash mit FSCOMMAND. Sie erzeugt automatisch eine Seite, die fscommand()-Anweisungen aufnimmt.
2.
Die von Flash produzierte HTML-Seite sollten Sie im Texteditor näher betrachten. Sie enthält eine Browserunterscheidung. Der Netscape Navigator mit LiveConnect11 wird per JavaScript angesprochen. Da die ActiveX-Komponente des Flash Players nicht JavaScript-fähig ist, verwendet Flash hier ein per JavaScript erzeugtes VBScript.12 In der Seite ist der wichtigste Teil die JavaScript-Funktion function fscommand_DoFSCommand(command, args). Ihr Name wird aus dem Namen des Flash-Films, hier also fscommand und _DoFSCommand zusammengesetzt. Der Befehl und die Parameter erscheinen beide als Parameter.
11 Dies funktioniert in einigen Versionen des Netscape Navigators nicht, da die LiveConnectUnterstützung dort fehlt oder fehlerhaft ist. Bekannt sind Probleme bei Navigator 6.0 bis 6.1 und 4.76. 12 Dies funktioniert nicht im Internet Explorer für Mac, da dort kein ActiveX vorhanden ist.
710
KOMPENDIUM
JavaScript
Flash
Kapitel 23 Abbildung 23.7: Wählen Sie FLASH MIT FSCOMMAND.
Da der Dateiname des Flash-Films Bestandteil einer JavaScript-Funktionsbezeichnung ist, sollten Sie darin keine Sonderzeichen verwenden! 3.
Fügen Sie nun folgenden Code in die Funktion ein, um den Text aus dem Formularfeld auszugeben:
if (command == "Ausgabe" && args != "") alert(args);
Fertig ist das Beispiel. Der zusätzliche Schritt, bei dem der eigentliche Code in JavaScript steht, ist leider notwendig. Alternativ können Sie auch eine komplette JavaScript-Anweisung in das Kommando schreiben und diese dann mit
Listing 23.11: fscommand() in JavaScript (fscommand.html)
eval(command);
ausführen. getURL() Der Einsatz von getURL() ist sehr einfach. Sie übergeben den JavaScriptBefehl als JavaScript-Link. getURL("javascript:alert(\'Hallo von Flash!\')\;");
Sie können damit auf alle Elemente der HTML-Seite zugreifen und in Flash den Link auch bei verschiedensten Ereignissen, beispielsweise beim Klicken auf eine Schaltfläche ausführen.
KOMPENDIUM
JavaScript
711
Kapitel 23
Kommunikation mit der Außenwelt
Abbildung 23.8: Der Text aus dem Flash-Eingabefeld landet in einer JavaScript-Warnmeldung.
Kommunikationssorgen Wie sinnvoll die Kommunikation über fscommand() ist und wann Sie besser auf getURL() zurückgreifen, hängt vom Einzelfall ab. Die bei fscommand() ausgeschlossenen Browser sollten Sie unter Umständen durch Überprüfung vorher herausfiltern. Vor allem beim Internet Explorer für Mac ist das sinnvoll, da diese Nutzer einen anderen Browser verwenden müssen. Ebenso achten Sie bitte auf die nicht berücksichtigten Browser wie Opera, Konqueror und Safari. Neben der Überprüfung des Browsers macht es durchaus Sinn, auch das Flash-Plugin zu testen. Die Überprüfung für den Navigator und Mozilla erfolgt über: navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin
Die Versionsnummer lässt sich in der description-Eigenschaft auslesen: navigator.mimeTypes["application/x-shockwave-flash"].description
Die Erkennung im Internet Explorer erfolgt über VBScript und ist um einiges komplizierter. Flash liefert entsprechende Vorlagen im Register HTML der Einstellungen zum Veröffentlichen (DATEI/EINSTELLUNGEN FÜR VERÖFFENTLICHUNGEN). 712
KOMPENDIUM
JavaScript
24
JScript .NET
Dieses Kapitel gibt Ihnen einen kurzen Einblick in die serverseitige Programmierung und es zeigt, wozu die Sprache JavaScript – oder in der MicrosoftTerminologie JScript – fähig ist. Die .NET-Strategie von Microsoft wird viel diskutiert und ist heftig umstritten. Bisher hat sie – ähnlich wie die XBox, Microsofts Spielekonsole – noch nicht richtig eingeschlagen. Dies liegt zum Teil auch daran, dass vielen nicht klar ist, worum es sich dabei handelt. Der Ansatz für Entwickler ist ansonsten als durchaus positiv und insbesondere für Webentwickler als überfällig zu bezeichnen. Und da zum Zeitpunkt der Drucklegung dieses Buchs die XBox gerade bei den Verkaufszahlen zulegt, ist das doch wohl auch von .NET zu erwarten .
24.1
.NET-Basics
Das .NET-Konzept (gesprochen Dotnet) basiert auf dem .NET Framework1. Dieses Framework enthält eine Vielzahl an Klassen, in denen die Funktionalität für die Anwendungsentwicklung unter Windows und die serverseitige Internetprogrammierung mit ASP.NET gepackt ist. Der Entwickler greift auf diese Klassen zu und setzt sie in seiner Programmierung ein. Das zweite wichtige Konzept von .NET ist die Sprachunabhängigkeit. Sie können mit jeder beliebigen Sprache, für die eine Schnittstelle zu .NET zur Verfügung steht, in .NET entwickeln. Dies wird durch die Common Language Runtime (CLR) realisiert. Code in .NET wird nicht sofort kompiliert wie beispielsweise Code in C oder C++. Stattdessen wird er in die Microsoft Intermediate Language (MSIL) umgewandelt. Diese Zwischensprache benötigt das .NET Framework auf dem jeweiligen Rechner, um ausgeführt zu werden. Für Webentwickler ist dies im Gegensatz zur Anwendungsentwicklung2 kein großes Problem, da das .NET Framework nur auf einem Rechner – dem Webserver –vorhanden sein muss. Der Nutzer erhält im Browser viel HTML und JavaScript. Ja, Sie haben richtig gelesen, JavaScript. Einige Funktionalitäten werden – zumindest für den Internet Explorer – aus 1 2
Rahmenwerk oder Rahmen Hier benötigt jeder Nutzer das .NET Framework.
KOMPENDIUM
JavaScript
713
Kapitel 24
JScript .NET ASP.NET in JavaScript (korrekt eigentlich JScript) umgewandelt. Dies bringt teilweise deutliche Performance-Vorteile, insbesondere bei den Validation Controls (siehe Kapitel 24.2 im Abschnitt »Validation Controls«).
Abbildung 24.1: Die Architektur von .NET – stark vereinfacht
Server Webserver
Common Language Runtime
Browser:
Client
HTML + JavaScript
Von ASP zu ASP.NET Die »alte« serverseitige Technologie von Microsoft heißt ASP (Active Server Pages). Mit ASP können Sie Formulare überprüfen und verschicken, auf Datenbanken zugreifen und mit Sessions arbeiten; also alles Aufgaben, die eine serverseitige Programmiertechnologie können muss. Leider hinkte ASP in einigen Bereichen den direkten Konkurrenten und insbesondere PHP deutlich hinterher. Daher hat Microsoft für ASP.NET deutlich nachgelegt. Endlich ist beispielsweise Sessionmanagement, also die Verwaltung von Benutzersitzungen, ohne Cookies möglich. Wenn Ihr Betriebssystem und Ihr Webserver bzw. Hoster die im folgenden Abschnitt behandelten Voraussetzungen erfüllen, ist ASP.NET ASP vorzuziehen. ASP hat bisher die zwei Programmiersprachen VBScript – ein Visual BasicDerivat – und JScript unterstützt. ASP.NET ist natürlich entsprechend den Grundprinzipien des .NET Frameworks sprachunabhängig. Die beiden Standardsprachen sind allerdings VB.NET und C#. JScript kommt als JScript .NET zum Einsatz. 714
KOMPENDIUM
JavaScript
.NET-Basics
Kapitel 24
Welche Betriebssysteme und Webserver? Um mit .NET arbeiten zu können, benötigen Sie das .NET Framework. Microsoft bietet es in zwei Varianten an: ein Redestributable und ein SDK (Software Development Kit). Das SDK ist mit knapp 130 MB wesentlich größer, enthält allerdings für den Entwickler nützliche Dokumentation und Beispiele. Des Weiteren wird die MSDE (Microsoft SQL Desktop Engine) mitgeliefert, eine kleinere Ausgabe der Datenbank MS SQL Server. Sie ist insbesondere zu Testzwecken sehr gut geeignet. In letzter Zeit hat ein Virus namens SQL-Slammer auf sich aufmerksam gemacht. Er verschickt sich in einem einzigen UDP-Paket und sorgt beim MS SQL Server für einen Buffer overflow. Ansonsten harmlos, belegt der Virus dennoch ganze Netzwerke mit dem Verbindungsaufkommen, das er produziert. Leider befällt dieser Virus auch die beim .NET SDK mitgelieferte MSDE. Ein Patch steht unter http://www.microsoft.com/downloads/ details.aspx?displaylang=de&FamilyID=1C4195CE-4007-476A-AA71-F9782DFD0818 zur Verfügung. Bevor Sie sich das .NET Framework von http://msdn.microsoft.com/ netframework/downloads/howtoget.asp herunterladen oder das von der BuchCD verwenden, muss geklärt werden, ob Ihr Betriebssystem damit zurecht kommt: Das .NET Redistributable steht für alle Microsoft-Betriebssysteme ab Windows 98 zur Verfügung. Das SDK ist laut Microsoft-Angaben auf Windows NT 4 (SP 6), 2000 in allen Versionen und XP Professional beschränkt. Sie können das Framework durchaus auch unter XP Home installieren. Das Problem hierbei ist, dass der Webserver fehlt. Für ASP.NET benötigen Sie – da es sich um eine serverseitige Technologie handelt – einen Webserver. ASP.NET unterstützt hier nur den IIS (Internet Information Service, vorher Internet Information Server), der unter NT 4, 2000 in allen Versionen und XP Professional vorhanden ist. Der PWS – eine kleine Serverlösung für Windows 98 und mit Tricks auch für Windows ME – wird nicht unterstützt. Unter Windows 98 und ME können Sie also nicht für ASP.NET testen. XP Home-Käufer ärgern sich besonders, dass Microsoft den Privatkunden keinen Webserver spendiert hat. Hier hilft allerdings Web Matrix, der ASP.NET-Editor von Microsoft aus. Er besitzt einen eigenen kleinen Webserver, der unter XP Home funktioniert.
KOMPENDIUM
JavaScript
715
Kapitel 24
JScript .NET Web Matrix finden Sie auf der CD-ROM im Ordnern software\dotnet.
Unter http://www.go-mono.com gibt es einen Portierungsversuch des .NET Frameworks auf Linux. Er trägt den Namen Mono und ist ein ausgesprochen spannender Feldversuch, auf den man achten sollte. Die Installation für ASP.NET erfolgt in drei einfachen Schritten: 1.
Installieren Sie den Webserver IIS, wenn er noch nicht installiert ist. Dies funktioniert über SOFTWARE in der Systemsteuerung und WINDOWS-KOMPONENTEN HINZUFÜGEN. Sie müssen dazu die CD-ROM des Betriebssystems bereithalten.
2.
Installieren Sie das .NET SDK Framework. Sie finden es auf der CDROM zum Buch.
3.
Installieren Sie Updates und Patches für den Server und das Framework.
Das aktuelle ServicePack zum .NET SDK Frame finden Sie auf der CDROM. Aktuelle Updates erhalten Sie auch unter Windows-Update (START/ PROGRAMME/WINDOWS-UPDATE).
ASP.NET-Seiten anlegen Die ASP.NET-Seiten müssen in einem Webverzeichnis des Webservers liegen. Beim IIS ist das Hauptwebverzeichnis inetpub/wwwroot. Aufgerufen werden die Seiten bei einer lokalen Testumgebung auf einem Rechner über http://localhost für den Webserver. Da ASP.NET-Seiten die Dateiendung .aspx besitzen, wird eine Seite test.aspx, die direkt in inetpub/wwwroot liegt (also im Browser) wie folgt aufgerufen: http://localhost/test.aspx
Wenn sie im Verzeichnis inetpub/wwwroot/test/ liegt, lautet der Aufruf: http://localhost/test/test.aspx
716
KOMPENDIUM
JavaScript
.NET-Basics
Kapitel 24
Editoren Theoretisch können Sie ASP.NET-Seiten in einem Texteditor schreiben, was für den Anfang durchaus ausreichend ist. Irgendwann soll es allerdings ein wenig mehr sein. Hier gibt es bisher zwei Alternativen von Microsoft:3 Visual Studio .NET ist die große Entwicklungsumgebung von Microsoft. Sie ist sehr mächtig und erlaubt komfortables Entwickeln, ist jedoch auch relativ teuer. ASP.NET Web Matrix ist ein kostenloses Tool von Microsoft, das nicht nur ein ASP.NET-Editor ist, sondern auch in .NET geschrieben wurde. Sie finden es unter http://www.asp.net/webmatrix/.4 Leider unterstützt Web Matrix bisher nur VB.NET und C#, nicht aber JScript .NET. Für Visual Studio .NET steht dagegen eine Erweiterung für JScript .NET zur Verfügung.
JScript .NET im Vergleich mit VB.NET und C# Dieser Abschnitt soll kein Sprachvergleich werden. Dies ist eher uninteressant, da die Funktionalität aus den .NET-Klassen stammt, die alle gleich sind. Vielmehr sollen die Zukunftschancen von JScript .NET im Vergleich zu den beiden übermächtigen Konkurrenten beleuchtet werden. Web Matrix als kostenfreier ASP.NET-Editor unterstützt JScript nicht, Visual Studio .NET nur mit einer Erweiterung. In den Dokumentationen sind die meisten Beispiele nur in VB.NET und C#. Die meisten Bücher setzen auf VB.NET oder C#. Es spricht aber auch einiges für einen Einsatz von JScript .NET: Sie können es bereits. Die Möglichkeiten sind dieselben wie bei den anderen Sprachen. Die Funktionalität steckt in den Klassen, deren Dokumentation auch mit JScript .NET genutzt werden kann. Letztlich wird die Entscheidung darin begründet sein, wie tief Sie in ASP.NET einsteigen möchten. Sollen es nur ein paar einfache serverseitige Aufgaben sein, wäre es unsinnig, eine neue Sprache zu lernen. Für einen tie3
4
Die Beschränkung auf diese zwei Alternativen ist keine überbordende Microsoft-Verehrung, sondern liegt daran, dass es für ASP.NET noch keine vergleichbaren Editoren gibt. Der Open Source-Editor SharpDevelop ist nur für die Anwendungsentwicklung geeignet. Wenn Sie mehr über Web Matrix erfahren wollen, empfehlen wir Ihnen das Buch »ASP.NET Web Matrix« von Christian Wenz, erschienen bei Markt+Technik.
KOMPENDIUM
JavaScript
717
Kapitel 24
JScript .NET fer gehenden Einstieg sind Sie dagegen auf weiterführende Dokumentationen, Editoren und Beispiele in der Sprache angewiesen, in der Sie arbeiten. Hier kann sich der Aufwand des Neulernens lohnen.
24.2
Web Forms
Das Herzstück der ASP.NET-Programmierung sind die so genannten Web Forms (Webformulare). Web Forms bestehen aus Formularelementen, die ASP.NET unterstützt und steuern kann. Diese Formularelemente müssen alle mit runat="server" versehen sein, damit ASP.NET erkennen kann, dass es sich um seine Formularelemente handelt. Die Funktionalität kommt dann aus den Klassen des .NET Frameworks. Für diese Klassen bietet das .NET SDK (und auch Web Matrix) einen Class Browser, der Ihnen erlaubt, die Klassen durchzugehen. Sie finden ihn unter Start/Programme/Microsoft .NET Framework SDK/Samples and Quick Start Tutorials. Auf der Seite klicken Sie auf den Link ASP.NET QuickStarts. Auf der folgenden Seite finden Sie unten bei den Beispielen A Class Browser Application. Starten Sie das Beispiel. Abbildung 24.2: Der Class Browser – hier mit der Klasse, die Informationen über die Browserfähigkeiten enthält.
Ein Namespace oder Namensraum enthält Klassen. Bei ASP.NET müssen Sie zunächst viele Namespaces importieren, bevor Sie die Klassen verwenden können.
718
KOMPENDIUM
JavaScript
Web Forms
Kapitel 24
Diese Zeile importiert den Namespace, der beispielsweise Klassen für das Auslesen und Schreiben von Dateien enthält.
HTML Controls Das einfachste Element für Web Forms sind die so genannten HTML Controls. Dies sind normale HTML-Formularelemente, die mit einem runat= "server" versehen sind. Beachten Sie, dass das -Tag ebenfalls ein runat="server" benötigt Sie können in ASP.NET direkt mit ihrer ID angesprochen werden. Das folgende Beispiel überträgt Text von einem Textfeld in ein anderes. Eine ASP.NET-Seite beginnt immer mit der Angabe der Sprache. In unserem Fall ist das jscript. Da der zugehörige Compiler bereits im .NET Framework enthalten ist, müssen Sie nichts weiter tun.
Die Textfelder des Beispiels sind HTML Controls, ebenso die Schaltfläche. Sie arbeitet mit dem OnServerClick-Ereignis5. Dieses Ereignis ist das Gegenstück zu onclick und dient zum serverseitigen Abfangen des Klickereignisses: <script runat="server"> function ausgeben(o : Object, e : EventArgs) { ausgabe.Value = eingabe.Value; }
Listing 24.1: HTML Controls im Einsatz (htmlcontrols.aspx)
HTML Controls
5
Die Schreibweise mit großen Anfangsbuchstaben nennt sich Camel-Case (von den Höckern der Kamele) und ist der Standard für alle Klassen, Methoden und Eigenschaften in .NET.
KOMPENDIUM
JavaScript
719
Kapitel 24
JScript .NET
Abbildung 24.3: Sie geben Text ein …
Abbildung 24.4: … und er wird in das untere Feld übertragen.
Web Controls Web Controls sind etwas fortschrittlicher als HTML Controls. Dafür übernimmt allerdings auch ASP.NET die Kontrolle. Ein Web Control beginnt immer mit function ausgeben(o : Object, e : EventArgs) { ausgabe.Text = eingabe.Text; }
720
KOMPENDIUM
JavaScript
Web Forms
Kapitel 24
Web Controls
Abbildung 24.5: Der Nutzer klickt auf Testen …
Abbildung 24.6: … und der Text aus dem Feld landet im Label-Web Control.
Wenn Sie einen Blick auf den Code werfen, der für das Geschehen in Abbildung 24.6 verantwortlich ist, sehen Sie, dass es sich hier um ein HTML-Formular handelt, das über einen Mausklick die aspnetcontrol.aspx-Seite erneut aufruft. Die Web Controls wurden in die entsprechenden HTMLElemente umgewandelt. Ein verstecktes Textfeld enthält weitere Infos. Web Controls
KOMPENDIUM
JavaScript
721
Kapitel 24
JScript .NET <span id="ausgabe">Testen
Im Allgemeinen müssen Sie sich um das Ergebnis Ihres Quellcodes nicht kümmern. Da die Ausgabe serverseitig erfolgt und die Browser geprüft werden, kann sogar Netscape 3 etwas mit dem Beispiel anfangen. Allerdings erfordert das serverseitige Lösen dieser Aufgabe auch, dass die Seite an den Server zurückgeschickt wird und dieser ein Resultat liefert. Dies kann zu Performance-Verlusten gegenüber clientseitigem JavaScript führen. Abbildung 24.7: Die Seite in Netscape 3
Komplexere Web Controls Das Konzept der Web Controls erlaubt eine wesentlich größere Flexibilität. Daher sind durchaus auch deutlich komplexere Web Controls denkbar, die die Arbeit vereinfachen. Ein bereits implementiertes Beispiel ist das Calendar-Control. Es erzeugt einen Kalender und besitzt viele Eigenschaften, um die Ausgabe zu steuern. Diese Eigenschaften können Sie der Dokumentation entnehmen. Der folgende einfache Code ist jedoch ausreichend, um ein gutes Resultat zu erzielen (siehe Abbildung 24.8). Listing 24.3: Das Web Control Calendar
(kalender.aspx)
722
Kalender
KOMPENDIUM
JavaScript
Web Forms
Kapitel 24
Abbildung 24.8: Den Kalender von Hand zu erstellen, wäre wohl zu aufwändig gewesen.
Validation Controls Eine dritte Art Controls nimmt Ihnen als Entwickler ebenfalls einiges an Arbeit ab. Die Validation Controls dienen der Überprüfung von Formulareingaben. Im folgenden Code überprüft ein RequiredFieldValidator, ob das Textfeld eingabe (ControllToValidate="eingabe") ausgefüllt ist. Ist dies nicht der Fall, wird eine Fehlermeldung (Eigenschaft ErrorMessage) ausgegeben: Validation Controls
Listing 24.4: Validation Controls im Einsatz (validationcontrol.aspx)
KOMPENDIUM
JavaScript
723
Kapitel 24
JScript .NET
Abbildung 24.9: Die Fehlermeldung erscheint, wenn das Formular leer abgeschickt werden soll.
Wenn Sie das Beispiel im Internet Explorer ausführen, wird sofort die Fehlermeldung daneben geschrieben. Dies erfolgt so schnell, dass es eigentlich nur clientseitig erfolgen kann. Und so ist es auch: ASP.NET wandelt das Validation Control, das keinen JScript .NET-Code erfordert hat, in clientseitigen JScript-Code mit Überprüfungen um. Eine externe JavaScript-Datei, die im .NET Framework auf dem Webserver integriert ist, enthält die Überprüfungsfunktionen: <script language="javascript" src="/aspnet_client/system_web/1_0_3705_288/ WebUIValidation.js">
Im übrigen Quellcode befindet sich ebenfalls viel JScript-Code. Für andere Browser funktioniert dies leider nicht so gut. Hier erfolgt die Überprüfung serverseitig und der Server muss zunächst eine neue Seite zurückschicken. Das heißt, hier kann – wie auch bei komplexen Überprüfungen – eine clientseitige JavaScript-Lösung durchaus Vorteile bringen.
24.3
Sessionmanagement
Da es sich hier nicht um ein ASP.NET-Buch handelt, muss die kurze Tour durch die serverseitige Programmierung leider mit diesem Abschnitt enden. Die Möglichkeiten des Sessionmanagements sollen jedoch kurz dargestellt werden. Eine Session ist eine Nutzersitzung. In dieser Sitzung erhält der Nutzer eine einheitliche ID über alle Seiten hinweg. Mit dieser ID kann der Nutzer auf der ganzen Website verfolgt werden. Das Sessionmanagement kann entweder mit Cookies erfolgen – die ID wird also in einem Cookie gespeichert – oder ohne Cookies. In diesem Fall wird die ID an die URL angehängt. Bei der Standardeinstellung werden Cookies eingesetzt, da dies etwas schneller geht. Das Erstellen von Sessions in ASP.NET ist sehr einfach. Die folgende Zeile erzeugt eine Session-Variable mit dem Wert »Wert1«. Session["Variable1"] = "Wert1"; 724
KOMPENDIUM
JavaScript
Sessionmanagement
Kapitel 24 Abbildung 24.10: Die Session-ID im Cookie
Hier der vollständige Code: <script runat="server"> function Page_Load() { Session["Variable1"] = "Wert1"; Session["Variable2"] = "Wert2"; }
Listing 24.5: Eine Session mit zwei Variablen wird angelegt. (session_starten. aspx)
Session starten Session auslesen
Auf der folgenden Seite kann nun der Wert der Variablen wieder aufgerufen und wie in diesem Beispiel ausgegeben werden. <script runat="server"> function Page_Load() { var variable = Session["Variable2"].ToString(); ausgabe.Text = variable; }
KOMPENDIUM
JavaScript
Listing 24.6: In der folgenden Seite haben Sie Zugriff auf die Session-Variable (session_auslesen. aspx).
725
Kapitel 24
JScript .NET Session ausgeben
Abbildung 24.11: Der Wert der Session-Variable kann einfach ausgelesen werden.
Natürlich können Sie über Sessions auch weitere Aktionen durchführen. Einen Login realisieren Sie beispielsweise, indem Sie den Nutzer einmal einloggen lassen und anschließend als Session-Variable Login=true oder eine ähnliche Information mitschicken. Die Session-Variable wird nur auf dem Server gespeichert und dort der ID zugeordnet. Daher ist sie vor unerlaubtem Zugriff sicher. ASP.NET beherrscht wie erwähnt auch ein Sessionmanagement ohne Cookies über die URL. Dazu müssen Sie eine Textdatei mit dem Namen web.config in Ihren Projektordner legen und dort mit einem Texteditor die folgenden Zeilen einfügen: <system.web> <sessionState cookieless="true" />
24.4
Ausblick
Beherrschen Sie nun ASP.NET und JScript .NET? Sicherlich nicht, denn viele interessante Themen wie Datenbanken und Webservices wurden nicht behandelt. Allerdings haben Sie nun (hoffentlich) einen Eindruck, wie serverseitige Programmierung mit JavaScript funktionieren kann. Dies könnte doch eine Anregung für das nächste Thema sein, mit dem Sie sich beschäftigen?! Mehr Informationen zu ASP.NET erhalten Sie im Verlagsprogramm von Markt+Technik. Eine (sehr eigennützige) Empfehlung ist das Buch »ASP.NET Kompendium« von Wenz/Hauser/Kordwig und Trennhaus.
726
KOMPENDIUM
JavaScript
Teil 4 Anhänge
Anhang A: Browser
729
Anhang B: Tools
739
Anhang C: JavaScript 2.0 und die Zukunft
741
Anhang D: Quellen
743
Anhang E: CD-ROM
745
A
Browser
Das wichtigste Handwerkszeug eines JavaScript-Entwicklers ist der Browser. Daher lohnt hier eine Betrachtung der verschiedenen Alternativen. Natürlich ist der Internet Explorer mit einem Marktanteil, der in verschiedenen Studien bis zu 90% beträgt, der Platzhirsch. Dennoch surft eine relevante Anzahl an Nutzer auch mit anderen Browsern. Vielleicht hat gerade Ihre Website einen besonders hohen Anteil an Nutzern mit anderen Browsern. Da wäre es fahrlässig, diese Nutzer auszugrenzen. Der Webprogrammierer benötigt also eine umfassende Testumgebung mit so vielen Browsern wie möglich. Sie haben in diesem Buch sicherlich bereits die Kompatibilitätstabellen entdeckt, die die wichtigsten Browser enthalten. In diesem Kapitel finden Sie dazu eine kurze Beschreibung der Browser, ihrer Geschichte und eine Bewertung ihrer Bedeutung.
A.1
Internet Explorer
Als Marktführer gehört der Internet Explorer natürlich auf jeden Testrechner. Ein Problem dabei ist, dass sich mehrere Internet Explorer unter einem Windows nicht (oder nur extrem schwer) zum Laufen bringen lassen. Einen Ausweg bieten meist mehrere Betriebssysteme – unter Umständen sogar auf mehreren Rechnern. Wer dies nicht leisten kann, sollte sehr genau auf die Kompatibilitätsangaben in diesem Buch und in anderen Quellen achten. Vielleicht finden Sie im Bekanntenkreis noch jemanden, der einen älteren Rechner hat, beispielsweise mit dem Internet Explorer 4. Einen relevanten Marktanteil besitzen heute nur noch die Internet Explorer ab Version 4. Die dritte Generation können Sie getrost nicht mehr unterstützen. Ein Problem für den ambitionierten Entwickler stellen auch die Internet Explorer-Versionen für den Mac dar. Aktuell sind dort die Versionsnummern 5.x, wobei es eine Version für Mac OS X und eine für ältere Betriebssysteme gibt. Da die Entwicklung der Macintosh-Variante von einem anderen Entwicklerteam durchgeführt wird, als dem der WindowsVariante, gibt es hier teilweise deutliche Unterschiede.
KOMPENDIUM
JavaScript
729
Anhang A
Browser
Abbildung A.1: Internet Explorer 6 unter Windows XP
Eine grobe Faustregel ist, dass die Mac-Variante sich wesentlich enger an die Standards hält und auch vieles aus den Standards unterstützt (beispielsweise die Positionierung mit fixed1). Viele der Inkompatibilitäten finden Sie bei den jeweiligen Funktionen oder Objekten in diesem Buch. Allerdings sollten Sie umfangreichere Anwendungen auch immer am Mac testen.2
A.1.1
Geschichte: Der Browserkrieg
Von Marc Andreessen und Jim Clark 1994 gegründet, jagte Netscape (vormals Mosaic) Microsoft mit seinem Browser, dem Netscape Navigator, einen gehörigen Schrecken ein.3 Zuerst nahm Bill Gates – der MicrosoftGründer – das Internet nicht wahr, dann folgte die völlige Kehrtwendung. Der Internet Explorer 3 war die erste ernst zu nehmende, das heißt einigermaßen funktionierende, Version eines Microsoft-Browsers, die sich Netscape entgegenstellte.
1 2
3
730
siehe Kapitel 19 »CSS und JavaScript« Hierzu eine Anekdote aus der Geschichte: Die Firma boo.com wollte 1998 über eine internationale E-Commerce-Site im großen Stil Mode verkaufen. Leider funktionierte das ausgeklügelte Shopsystem nicht beim Mac. Dabei saß insbesondere in Werbe- und PR-Agenturen ein Großteil der Zielgruppe für Trendmode … Die Pleite kam 13 Monate später. Netscapes Börsengang gilt für viele als die Geburtsstunde des New Economy Booms.
KOMPENDIUM
JavaScript
Netscape Navigator
Anhang A Abbildung A.2: Der Internet Explorer am Mac
Mit Version 4 schuf Netscape sich eine Menge Probleme, da einige Standards noch nicht feststanden und viele proprietäre Erweiterungen wie Layers nie von den Konkurrenten adaptiert wurden. Der Internet Explorer wurde dagegen in Version 4 deutlich besser und unterstützte damals bereits die meisten JavaScript-Möglichkeiten, die heute zum Einsatz kommen. Als Netscape an AOL verkauft wurde, war der Kampf entschieden: Microsoft hatte sich durchgesetzt und konnte die Versionen 5, 5.5 und 6 über ihre Betriebssysteme an die Nutzer verteilen.
A.2
Netscape Navigator
Der Problemkandidat unter den Netscape-Browsern ist der Navigator 4.x. Er hat eine Vielzahl an Unterversionen mit teilweise unterschiedlicher JavaScript-Unterstützung hinter sich und dies führte – neben der Marktmacht von Microsoft – zum Niedergang von Netscape. Dennoch kommt ein Webentwickler heute – das heißt im Jahr 2003 und eventuell auch 2004 – nicht um diesen Browser herum, denn er hat mit seinen verschiedenen Versionen und Plattformen (Windows, Linux und Mac) immer noch einen vergleichbaren Marktanteil wie seine Nachfolger Netscape 6, 7 und Mozilla. Netscape – bereits von AOL aufgekauft – gab den Quellcode des Navigator frei. Daraus entstand das Projekt Gecko4. Die Gecko-Engine kehrte den proprietären Konzepten des Netscapes 4.x komplett den Rücken und setzt
KOMPENDIUM
JavaScript
731
Anhang A
Browser mittlerweile vollständig auf die W3C- und sonstigen Standards. Entsprechend machte Netscape aus der Gecko-Engine den Netscape Navigator 6, und – nachdem dieser ziemlich fehlerhaft war – kurz darauf den aktuellen Netscape Navigator 7. Dieser Browser ist ein Hoffnungsschimmer für alle alten Netscape-Anhänger, da seine Standardunterstützung gut ist. Ob er diese Hoffnungen auf Dauer erfüllt, sei allerdings dahingestellt. Als JavaScript-Programmierer müssen Sie die beiden Netscape-Browser auf jeden Fall berücksichtigen. Glücklicherweise sind die Unterschiede nicht sehr groß, da Netscape 7 vor allem Bugs beseitigt hat.
Abbildung A.3: Die Browserzentrale von Netscape. Insbesondere der Developer´s Corner ist ergiebig.
Sie finden die aktuellen Netscape-Browser unter http://www.netscape.com und natürlich auf der Buch-CD-ROM.
4
732
Dies ist auch die Bezeichnung der Engine des Browsers – also dem, was unter der Haube steckt.
KOMPENDIUM
JavaScript
Mozilla
A.3
Anhang A
Mozilla
Da Gecko bereits Open Source war, lag es nahe, einen eigenen Open Source-Browser daraus zu entwickeln. Das Ergebnis ist der Mozilla. Unter http://www.mozilla.org fand nicht nur dieser Browser mit dem netten Feuer speienden Drachen eine Heimat, sondern auch viele andere interessante Open Source-Projekte rund um die Webentwicklung. Der Mozilla ist für alle wichtigen Betriebssysteme verfügbar und seine Homepage ist eine Fundgrube für interessante Entwicklungsprojekte und Informationen, beispielsweise auch über die Zukunft von JavaScript. Abbildung A.4: Die Heimat des roten Drachen
Als ambitionierter JavaScript-Entwickler sollten Sie den Mozilla auf jeden Fall berücksichtigen. Die Testumgebung ist einfach realisierbar, da die beiden Netscape-Versionen und Mozilla problemlos parallel installiert werden können. Steht Ihnen wenig Festplattenplatz zur Verfügung, ist es jedoch ausreichend, im Netscape 7 oder Mozilla zu testen.
A.3.1
Gecko und Konsorten
Aus der Gecko-Engine entstanden weitere Browserprojekte wie beispielsweise Galeon (http://sourceforge.net/projects/galeon), Phoenix (http:// www.mozilla.org/projects/phoenix/) und K-Melon 0.7 (http://sourceforge.net/ projects/kmeleon).
KOMPENDIUM
JavaScript
733
Anhang A
Browser
A.4
Opera
Der Opera stammt aus Norwegen und ist seit langer Zeit die Nummer 3 im Browsermarkt hinter Netscape und Internet Explorer. Das besondere an Opera ist zum einen, dass er sehr leichtgewichtig daherkommt. Der Download der aktuellen Version umfasst – ohne Java Virtual Machine – nur 3,2 MB. Zum anderen integriert Opera interessante und teilweise neue Bedienkonzepte, indem er beispielsweise geöffnete Seiten in Registern darstellt. Abbildung A.5: Den Opera finden Sie unter http:// www.opera.com.
Den Opera gibt es in einer kostenfreien Variante mit Werbebannern und in einer Variante ohne Werbung, die allerdings 39 US $ kostet. Die kostenfreie Variante ist jedoch für Entwickler, die nicht ständig damit surfen, ausreichend. Die aktuelle Version des Opera ist 7. In dieser Version wurden insbesondere die DHTML-Unterstützung und einige JavaScript-Funktionen verstärkt an die Standards angelehnt. In den Vorgängerversionen ähnelte Opera häufig dem Internet Explorer sehr stark. Er unterstützt beispielsweise auch document.all. Als JavaScript-Programmierer sollten Sie auf jeden Fall mit der aktuellen Version testen. Opera 6 scheint zum Testen allerdings auch noch geeignet zu sein. Da beide problemlos nebeneinander installiert werden können, bedeutet dies auch keinen größeren Aufwand.
734
KOMPENDIUM
JavaScript
Konqueror
Anhang A
Viele Webseiten verwenden – leider – Browserunterscheidungen mit dem navigator-Objekt, die den Opera nicht berücksichtigen. Daher können Sie den Opera in den Voreinstellungen (DATEI/VOREINSTELLUNGEN) als Internet Explorer oder Netscape Navigator ausgeben (siehe Kapitel 12 »Browserunterscheidung«). Von den neuen Versionen des Opera gibt es häufig mehrere Beta-Versionen. Von diesen bis zu den endgültigen Programmversionen ändert sich oftmals recht viel, was die JavaScript-Unterstützung betrifft. Achten Sie also beim Testen genau darauf, welche Unterversion Sie besitzen.
A.5
Konqueror
Die meisten Linuxdistributionen bieten – häufig als eine unter mehreren – die KDE (K Desktop Environment)5 als Desktop-Oberfläche. Integriert ist ein Dateimanager, der gleichzeitig ein Webbrowser ist. Dieser Webbrowser mit dem Namen Konqueror6 basiert auf der Rendering-Engine KHTML. Abbildung A.6: Der Konqueror kommt auch mit DHTML zurecht.
5 6
http://www.kde.org http://www.konqueror.org
KOMPENDIUM
JavaScript
735
Anhang A
Browser Der Konqueror in der Version 3 hat hervorragende JavaScript-Fähigkeiten und unterstützt die gängigen Webstandards. HTML-Seiten rendert er sehr schnell, da die Engine wenig Code umfasst und entsprechend fix ist. Die integrierte JavaScript-Engine ist offensichtlich etwas weniger performant, was aber durch die gute Ausführungsqualität und erfreulich wenige Bugs ausgeglichen wird. Der Konqueror ist insbesondere im universitären Umfeld und in der LinuxGemeinde recht verbreitet und sollte von einem guten JavaScript-Programmierer getestet werden.7 Dies ergibt auch erfreuliche Synergie-Effekte, da der neue Mac OS X-Browser Safari von Apple auf derselben RenderingEngine KHTML basiert. Beide Browser können sich auch als Internet Explorer oder Netscape ausgeben, um schlechten Browserunterscheidungen vorzubeugen.
A.6
Safari
Als Apple angekündigt hat, einen eigenen Webbrowser für Mac OS X (erst Jaguar) zu entwickeln, war die Spannung groß. Er sollte über ein gutes Design verfügen, einfach zu bedienen und schnell sein. Die bisherigen Betas des Safari (http://www.apple.com/de/safari) konnten diese Erwartungen auch gut erfüllen. Nachdem Apple nicht auf der grünen Wiese beginnen wollte, hat man sich für die KHTML-Rendering-Engine als Grundlage des Browsers entschieden, da sie – nach Aussagen der Apple-Verantwortlichen – wesentlich weniger Code umfasst und schneller arbeitet. Der Safari ist zwar nur auf das neueste Mac OS X namens Jaguar beschränkt, aber dank seiner engen Integration in das System und seiner sonstigen Vorzüge wird er beim Mac sicherlich bald einen größeren Marktanteil gewinnen können. In der Beta-Version besitzt der Safari noch ein verstecktes Menü, in dem er sich beispielsweise als anderer Browser ausgeben kann. Sie blenden das Menü ein, indem Sie in der XML-Konfigurationsdatei von Safari (~/Library/ Preferences/com.apple.Safari/plist) den neuen Eintrag IncludeDebugMenu mit dem Wert true hinzufügen: IncludeDebugMenu <true/>
Dazu ist ein normaler Texteditor ausreichend. 7
736
Ein Linux-Testsystem gehört ebenfalls zu den Pflichten. Eine Ausnahme ist ein Intranet, das komplett auf Windows-Rechnern basiert.
KOMPENDIUM
JavaScript
HotJava
Anhang A Abbildung A.7: Apple geht auf Safari
A.7
HotJava
Der HotJava-Browser von Sun (http://java.sun.com/products/hotjava/3.0/) ist vollständig in Java geschrieben und benötigt daher ein Java Development Kit (JDKTM) 1.1.x. Die JavaScript-Unterstützung ist recht ordentlich, kann jedoch nicht mit den anderen neueren Browsern verglichen werden. Auch bei der HTML 4.0-Unterstützung hapert es ein wenig. Die Eigeneinschätzung von Sun lautet HTML 3.2++. Da der Marktanteil des HotJava-Browsers heute sehr gering ausfällt, muss ein JavaScript-Entwickler nicht unbedingt auf ihm testen. Die Ausnahme sind Zielgruppen, die aufgrund der einfachen Verfügbarkeit insbesondere auf einen Java-Browser setzen.
KOMPENDIUM
JavaScript
737
Anhang A
Browser
Abbildung A.8: HotJava und seine Heimat
A.8
Browser ohne JavaScript
Browser ohne JavaScript? Warum werden diese Browser in diesem Buch überhaupt erwähnt. Hauptsächlich, um das Bewusstsein zu fördern, dass es sie gibt. Sie sollten immer – auch wenn Sie eine sehr moderne Zielgruppe und mit JavaScript überfrachtete Seiten haben – einen Ausweg und einfachen Informationszugriff für diejenigen bieten, die entweder mit einem Browser ohne oder mit deaktiviertem JavaScript surfen. Die Liste der Browser ohne oder mit sehr wenig JavaScript-Unterstützung ist lang. Daher folgen hier nur einige Beispiele: Amaya (http://www.w3.org/Amaya) vom W3C – ist ein Test-Browser für neue Standards und Implementierungen des W3C. Arachne (http://arachne.browser.org) – ist ein grafischer Browser für DOS-kompatible Betriebssysteme. Lynx (http://lynx.browser.org) – ist ein einfacher und früher recht populärer Textbrowser, der für verschiedene Plattformen erhältlich ist. NCSA Mosaic (http://archive.ncsa.uiuc.edu/SDG/Software/mosaic-w) – ist ein Nachfolger des Urbrowsers Mosaic. Mnemonic (http://www.mnemonic.org//mnemonic/documentation/doc/www/ index.html) – ist ein grafischer Browser für Unix. 738
KOMPENDIUM
JavaScript
B
Tools
Neben den Browsern gehören noch einige andere Programme zum Handwerkszeug eines JavaScript-Entwicklers. Als Erstes ist da natürlich der Editor zu nennen, in dem programmiert wird.
B.1
Editoren
Die Editoren für JavaScript lassen sich grob in zwei Gruppen einteilen: Texteditoren – Hier reicht die Palette von einfachen Editoren – wie dem bei Windows mitgelieferten – bis hin zu komplexen Programmen mit Syntax-Highlighting. Eine Empfehlung fällt hier schwer, da jeder Programmierer andere Gewohnheiten und Wünsche hat. WYSIWYG-Editoren (What You See Is What You Get) – Editoren, in denen HTML-Seiten erstellt und ein wenig JavaScript zusammengeklickt werden kann. Die JavaScript-Möglichkeiten von bekannten Editoren wie Macromedia Dreamweaver und Adobe GoLive sind recht gut und da man in diesen Programmen auch den Quellcode bearbeiten kann, können JavaScript-Programmierer auch dort arbeiten.
B.2
JavaScript-Engines
Wenn Sie selbst Software entwickeln und für diese Software gerne JavaScript als Skriptsprache verwenden möchten, benötigen Sie eine JavaScriptEngine zum Interpretieren des Codes. Eine solche Engine selbst zu programmieren, ist nicht nur ein immenser Aufwand, sondern auch unnötig, da die JavaScript-Engine einiger Browserprojekte zur Weiterverwendung zur Verfügung steht. Beachten Sie auf den Websites zu den Projekten, unter welcher Open Source-Lizenz die Engine vorliegt oder welche Lizenzbedingungen an eine Weiterverwendung geknüpft werden.
KOMPENDIUM
JavaScript
739
Anhang B
Tools
Abbildung B.1: UltraEdit – ein guter Texteditor
Folgende Engines sind verfügbar: Rhino (http://www.mozilla.org/rhino/) – ist die JavaScript-Engine aus dem Mozilla-Projekt – geschrieben in Java. Informationen zur Implementierung erhalten Sie ebenfalls auf der Homepage des Projekts. Eine erste Anlaufstelle dort ist http://www.mozilla.org/rhino/tutorial. html. Spidermonkey (http://www.mozilla.org/js/spidermonkey/) – ist die JavaScript-Engine des Mozilla-Projekts in C. Erste Anlaufstelle zur Implementierung ist hier http://www.mozilla.org/js/spidermonkey/apidoc/ jsguide.html. FESI (Free ECMAScript Interpreter; http://home.worldcom.ch/~jmlugrin/ fesi/) – ist eine freie ECMAScript-Engine. Sie wird jedoch bereits länger nicht mehr aktualisiert und befindet sich daher auf dem Stand von JavaScript 1.1. Microsoft Windows Scripting-Engine mit JScript-5.6-Unterstützung (http://msdn.microsoft.com/downloads/default.asp?URL=/downloads/sample. asp?url=/msdn-files/027/001/733/msdncompositedoc.xml)
740
KOMPENDIUM
JavaScript
C
JavaScript 2.0 und die Zukunft
Die erste Frage im Zusammenhang mit JavaScript lautet meist: »Hat JavaScript überhaupt eine Zukunft?« Das diese Frage mit »Ja« zu beantworten ist, wissen Sie als Leser dieses Buches bereits. Der Boom von serverseitigen Programmiersprachen wie PHP kann nicht darüber hinwegtäuschen, dass es ohne clientseitige Programmierung in vielen Bereichen nicht geht. Und vieles, was heute HTML-Editoren als tolle Effekte verkaufen, ist meist einfaches JavaScript oder DHTML. Der Code, der dabei herauskommt, ist von sehr unterschiedlicher Qualität. Allein, um diesen Code zu verstehen, zu verändern und auf alle Browser anzupassen, benötigen Sie JavaScript. Und der übergeordnete Standard ECMAScript wird auch in Zukunft nicht nur bei Flashs Programmiersprache ActionScript eingesetzt werden. Wer JavaScript beherrscht, ist eindeutig im Vorteil. Zu guter Letzt gibt es immer neuere Technologien – wie beispielsweise SVG (Scalable Vector Graphics) für Webvektoranimationen – die geradezu nach guten Scripting-Möglichkeiten verlangen. Aus dieser Perspektive ist JavaScript ein unverzichtbarer Bestandteil in der Zukunft des Webs.
C.1
JavaScript 2.0
Zum Zeitpunkt der Drucklegung dieses Buches sind revolutionäre Änderungen im Bereich JavaScript nicht in Sicht, zumindest, wenn unter »Sicht« ein Zeitraum von ein bis zwei Jahren verstanden wird. Dies soll aber nicht heißen, dass in dieser Zeit nichts geschehen wird. Neue Browserversionen und -Updates halten den JavaScript-Programmierer auf jeden Fall auf Trab. Und auf kleinere Bugs und Probleme werden Sie auch in dieser Zeit stoßen. Der nächste große Schritt wird dann die JavaScript-Version 2.0 bzw. ECMAScript 4 sein.1 Unter http://www.mozilla.org/js/language/js20.html bzw. http://www.mozilla.org/js/language/es4.html liegt die bekannteste Vorschlagliste für diesen neuen Standard. Sollten die dort genannten Änderun1
Eine Gleichsetzung der beiden Arbeiten wäre nicht ganz exakt. Allerdings verläuft die Entwicklung von ECMAScript 4 Hand in Hand mit der von JavaScript 2.0, das auf ECMAScript 4 aufsetzen soll.
KOMPENDIUM
JavaScript
741
Anhang C
JavaScript 2.0 und die Zukunft gen und einige andere Schritte tatsächlich vollzogen werden, müssen die JavaScript-Interpreter in den Browsern, die Spezifikationen und dieses Buch vollständig überarbeitet werden. Diese Vorschläge sind jedoch auch mit Vorsicht zu genießen. Sie beinhalten nahezu nur Eingaben von Netscape oder der Mozilla-Gemeinde, aber nicht von Microsoft. Darüber hinaus geben auch die Verantwortlichen selbst offen zu, dass sich die Überlegungen noch in einem »Experimentierstadium« befinden. Die wichtigsten geplanten Änderungen sind: Wesentlich mehr Objektorientierung. Objektorientierte Programmierung mit Klassen und klassenorientierter Vererbung Kompilieren von JavaScript-Code als zusätzliche Möglichkeit neben dem Interpretieren Strenge Typisierung von Daten wie in Java Diese Änderungen bedeuten allerdings nicht, dass Sie alles neu lernen müssen. Ihre Kenntnisse in JavaScript werden Ihnen dabei helfen, auch mit dem nächsten JavaScript-Standard erfolgreich zu arbeiten.
742
KOMPENDIUM
JavaScript
D
Quellen
Das Internet ist – wie bei vielen Gelegenheiten – auch bei JavaScript eine der wichtigsten Quellen für den Programmierer (neben diesem Buch ). Im Folgenden finden Sie hier einige wichtige Quellen.1
D.1
Skripten und Tutorials
Auf den folgenden Websites finden Sie viele Informationen zu JavaScript, Tutorials und vorgefertigte Skripten: http://www.webreference.com/js/ – enthält viele Tutorials und Skripten. Eng angebunden ist http://www.javascript.com. http://www.jsworld.com – ist ein bekanntes englischsprachiges Angebot. http://hotwired.lycos.com/webmonkey/reference/javascript_code_library/ –
ist eine Seite mit vielen vorgefertigten Skripten. http://www.javascriptcorral.com – viele Skripte. http://drweb.de/javascript/ – ist ein deutschsprachiges Angebot zu Java-
Script. http://www.scriptsearch.com/ – Anlaufstelle für die Suche nach Skripten.
Viele Quellen und Tutorials sind ähnlich. Darüber hinaus bestehen Partnerschaften zwischen den Seiten. Testen Sie Skripten, die Sie übernehmen, gut. Schauen Sie sich auch den Code an und testen Sie kritisch.
1
Quellen zu den Browsern finden Sie in Anhang A, Quellen zu Editoren in Anhang B, Quellen zu JavaScript 2.0 in Anhang C.
KOMPENDIUM
JavaScript
743
Anhang D
Quellen
D.2
Newsboards, Newsgroups und Maillisten
In Newsgroups finden Sie interessante Informationen und können – bei reger und den Regeln der Netiquette angepasster Beteiligung – eigene Fragen stellen. comp.lang.javascript – ist die englischsprachige JavaScript-Newsgroup. comp.de.lang.javascript – ist die deutschsprachige JavaScript-News-
group. Die zugehörige Website mit Mailarchiv usw. finden Sie unter http://www.dcljs.de. http://groups.google.de – ermöglicht eine webbasierte Suche und Zugriff auf Newsgroups. Für andere Newsgroups benötigen Sie einen Newsreader (z.B. das Netscape Navigator Mail-Programm Messenger oder Outlook Express des Internet Explorers). http://www.experts-exchange.com/javascript/ – Newsboard, in dem Sie für Punkte Fragen stellen können. Wenn Sie selbst Fragen beantworten, erhalten Sie Punkte.
Mailinglisten helfen dabei, sich täglich ein wenig mit JavaScript zu beschäftigen. Wenn Sie nicht ständig Mails erhalten wollen, können Sie auch Zusammenfassungen – so genannte Digests – bestellen. http://mountaindragon.com/javascript/ – ist die bekannteste JavaScript-
Liste.
744
KOMPENDIUM
JavaScript
E
CD-ROM
Sie haben eine schnelle Internet-Verbindung und Sie halten Buch-CD-ROMs sowieso für Unsinn, weil nie etwas Vernünftiges drauf ist? Dass diese Meinung sich nicht bewahrheiten muss, beweist (hoffentlich) die beiliegende CD-ROM. Sie finden hier alle Beispiele aus dem Buch. Außerdem ist der Ordner software vollgepackt mit nützlicher Software: von Browsern über die Java SDK bis zum .NET Framework. Ihnen fehlt etwas auf der CD-ROM, was Sie in der nächsten Auflage gerne hätten? Schreiben Sie mir eine E-Mail an
[email protected]. Sicherlich lassen sich nicht alle Wünsche erfüllen (Visual Studio gibt es leider nicht auf nur einer CD), aber einen Wunsch äußern kostet (fast) nichts.
E.1
Beispiele
Die Beispiele sind im Unterordner code abgelegt und nach Kapiteln sortiert. In den Kapiteln finden Sie den Namen der Beispiele immer in der Listingunterschrift in runden Klammern.
Listing E.1: Beispiellisting (listingname.html)
Gibt es weitere Beispiele oder Bilder, die nicht abgedruckt sind, wird mít dem CD-ROM-Icon darauf aufmerksam gemacht.
Die Beispiele wurden mehrfach getestet. Sollten dennoch Fehler vorhanden sein, werfen Sie bitte einen Blick auf http://www.hauser-wenz.de/support/ für aktuelle Updates. Finden Sie dort keine Abhilfe, schreiben Sie mir:
[email protected].
E.2
Browser
Die CD-ROM enthält die wichtigsten Browser im Verzeichnis software/ browser: Internet Explorer 6 für Windows
KOMPENDIUM
JavaScript
745
Anhang E
CD-ROM Ältere Microsoft-Browser stehen nicht mehr zur Verfügung. Sie benötigen also zu Testzwecken extra ältere Betriebssysteme mit den Browsern. Netscape Navigator 7.02 für Windows Netscape Navigator 6.23 für Windows und Linux Netscape Navigator 4.78 für Windows Mozilla 1.2.1 für Windows und Linux Opera 7.01 für Windows Der Konqueror wird bei den gängigen Linux-Distributionen mit KDE mitgeliefert. Dort finden Sie auch die aktuellsten Installationspakete. Die Quellen sind unter http://www.konqueror.org zu beziehen. Der Safari liegt bisher nur als Beta vor, was sich vermutlich sehr schnell ändern wird. Sie finden die aktuellste Version unter http://www.apple.com/de/safari/.
E.3
Java SDK
Die Java SDK befindet sich im Ordner software/javasdk. Java 2 SDK 1.4 für Windows und Linux. Java Development Kit 1.1.8 für Windows und 1.2.2 für Linux.
E.4
.NET
Alles, was Sie für .NET benötigen, ist natürlich auch auf der CD-ROM im Ordner software/dotnet. Das .NET SDK Framework Das .NET Redistributable Service Packs und Hot Fixes für das Framework Microsoft Data Access Components (MDAC). Sie enthalten aktuelle Treiber zur Datenbank-Anbindung für das .NET Framework. ASP.NET Web Matrix
746
KOMPENDIUM
JavaScript
Stichwortverzeichnis
, type-Attribut ändern 525 64 - 83 -- 84 != 87 !== 88
! " 63f., 70 "Reguläre Ausdrücke" 663f. # 48 $1,$2… (Eigenschaften), RegExp-Objekt 665 % 83 % (Prozent) 583 %= 85 & 98 && 94 ' 62, 64 * 83 *= 85 + 83, 85 ++ 83 += 85 , 117 .aspx 716 .htc 606 .NET 713 Architektur 714 .NET Framework 713 .NET Framework SDK (Software Development Kit) 715 / 83 /= 85 < 87 699, 707 531 528 557 Zugriff 558 553 Zugriff 558 <iframe> 577 424 454 <meta> 687 <noscript> 40, 363 699, 707 507 <script defer> 53 <script for> 53 <script> 38, 680 im Kopf 41 Kurzform 43 Version 49 <select> 506 <span> 657 <style> 582, 585 -= 85 = 68 == 87 === 88 > 87 >= 87 >> 99 >>> 99 ? 109
747
Stichwortverzeichnis @import 582 \ 62f. \b 63, 664 \f 63 \t 63 ^ 98 _ 71 _blank 440, 467 _media 468 _parent 440, 467 _search 468 _self 440, 467 _top 440, 468 | 98 || 94 ~ 98 ” 64
A a:hover 582 about:cache 687 about:plugins 701 abs() 168 acos() 168 action-Attribut 528 ActionScript 35, 706 ActiveMovie 699 ActiveXObject 205, 679 ActiveX-Objekte 205 add() 516 addBehavior() 607 addEventListener() 348 addImport() 593 addRule() 593, 598 alert() 133, 459 align (Eigenschaft) und 531 iFrame-Objekt 577 image-Objekt 424 allowTransparency (Eigenschaft) Frame-Objekt 562 iFrame-Objekt 577 alt (Eigenschaft), image-Objekt 426 altKey (Eigenschaft) event-Objekt IE 347 event-Objekt W3C 350 alwaysLowered (Fenstereinstellung) 471 alwaysRaised (Fenstereinstellung) 471 Amaya 738 anchor() 238
748
Animation DHTML 638 endlos 413 Größenänderung 420 mehrmals ablaufend 415 mit Bildern 410 mit Bildertausch 411 mit Zufall 416 Anker 440 appendChild() 319, 323, 325 Apple QuickTime 699 Safari 736 apply() 278 appName (Eigenschaft) 365 appVersion (Eigenschaft) 365 Arachne 738 archive-Attribut 680 arguments.callee (Eigenschaft) 276 arguments.caller (Eigenschaft) 277 arguments.length (Eigenschaft) 277 Arithmetische Operatoren 83 Kurzform 84 arity (Eigenschaft) 277 Array 207 assoziativ 216 Datentypen mischen 209 Elemente ändern 212 Elemente löschen 215 for-in-Schleife 213 füllen 208 Konstruktor 207 Kurzformen 209 Länge 212 length 209 mehrdimensionales 210 mit Schleifen 213 Multidimensional 211 verschachteln 210 Array-Objekt 166, 207 Methoden 217 ASCII 76, 91 asin() 168 ASP (Active Server Pages) 35, 714 ASP.NET 35, 713f. Browser-Eigenschaften 390 HTML Controls 719 runat= 719 Sessionmanagement 714, 724 Validation Controls 723
KOMPENDIUM
JavaScript
Stichwortverzeichnis Voraussetzungen 715 Web Controls 720 Web Forms 718 assign() 434 Assoziative Arrays 216 atan() 168 atan2() 168 Attribute action 528 archive 680 autostart 700 class 582, 588 classid 700 cols 553 disabled 455 enablejavascript 704 Event-Handler 48 for 531 height 420 hidden 700 href 427 language 38, 362 lowsrc 405 mastersound 700 mayscript 697 method 528 multiple 506 name 492 noresize 562 src 44 style 582 swLiveConnect 707 target 440 type 45, 525 value 494 width 420 attributes (Eigenschaft), W3C DOM 320 Auswahllisten 505 als Navigationselemente 517 bearbeiten 511 Eigenschaften 507 mehrere Optionen auswählen 509 prüfen 650 Zugriff 506 autostart-Attribut 700 availHeight (Eigenschaft) 422
B back() 335, 431 Backspace 63 Basis für toString() 149
KOMPENDIUM
JavaScript
Behavior 604, 606 Bestätigungsdialogfeld 461 Bezeichner 71 Regeln 71 big() 162, 238 Bilder 395 als Formularelemente 406 Animation 410 Dateiformate 410 Größenänderung 420 Imagemaps 427 Interpolation 420 Vorladen 402 Binäre Schreibweise 97 Bitoperatoren 96 Bitweise Operatoren 96 blink() 238 blur() 455, 476, 499 Bogenmaß 171 bold() 238 Boolean 65, 87, 93 Boolean-Objekt 166, 202 Methoden 202 border (Eigenschaft) Frameset-Objekt 559 image-Objekt 424 borderColor (Eigenschaft) Frame-Objekt 562 Frameset-Objekt 559 break 116, 119 break-Anweisung 110 Browser 729 Cookies 540 DOM 328 Fenstergröße 640 HotJava 737 Identifikation 366f. Internet Explorer 729 Konqueror 735 Mauskoordinaten 623 Mozilla 733 Netscape Navigator 731 ohne JavaScript 38, 738 Opera 734 Safari 736 Browser Sniffer 378 Browserkrieg 32, 730 browserLanguage (Eigenschaft) 379 Browsermarkt 33 Browserobjekte 34, 165, 306, 332 Browserunterscheidung 385 749
Stichwortverzeichnis Browser-spezifische Objekte 166, 204 Browserunterscheidung 361 Browserobjekte 385 Cookietest 550 deaktiviertes JavaScript 363 DHTML 602 Konqueror 368 mit language-Attribut 362 Mozilla 373 navigator-Objekt 364 Opera 367 serverseitig 390 Sprache 379 Versionen 51 Versionsnummer 370 bubbles (Eigenschaft), event-Objekt W3C 349 Bug 283 button (Eigenschaft) event-Objekt IE 346 event-Objekt W3C 349
C call() 278 cancelBubble (Eigenschaft) event-Objekt IE 346 event-Objekt W3C 349 captureEvents() 330, 341, 617, 621 Besonderheit Konqueror 342 case-sensitive 71 catch-Block 294 ceil() 168 cellIndex (Eigenschaft), td-Objekt 613 Certificate Authority (CA) 677 channelmode (Fenstereinstellung) 471 charAt() 246 charCode (Eigenschaft), event-Objekt W3C 350 charCodeAt() 246 Checkboxen 502 prüfen 649 checked (Eigenschaft) 503 Child (Knoten) 314 childNodes (Eigenschaft) 314 class-Attribut 582, 588 Classes 678 classid-Attribut 700 className-Objekt 588 clearInterval() 194, 418 clearTimeout() 418 Client 31 clientInformation-Objekt (nur IE) 364
750
clientseitig 31 Client-Server-Architektur 31 clientX (Eigenschaft) event-Objekt IE 347 Maus 618 clientY (Eigenschaft) event-Objekt IE 347 Maus 618 cloneNode() 318, 323 close() document-Objekt 478 window-Objekt 480 closed (Eigenschaft) 482 cm (Zentimeter) 583 Code schützen 684 Externe Dateien 687 in Frame auslagern 686 Kontextmenü verhindern 685 Notwendigkeit 690 unlesbar machen 688 verschlüsseln 689 Code strukturieren 132 Codebase principal 681 cols (Eigenschaft) Frameset-Objekt 559 Mehrzeiliges Textfeld 501 cols-Attribut 553 colspan (Eigenschaft), td-Objekt 613 Common Language Runtime (CLR) 713 compile() 662 complete (Eigenschaft), image-Objekt 404 concat() Array-Objekt 221 String-Objekt 242 confirm() 461 const 79 continue 120 Cookie-Manager 548 cookie-Objekt 547 Cookies 537 ändern 549 auslesen 542 Beschränkungen 538 Domain 548 Geschichte 538 löschen 549 Mehrere 545 persistent 547 Pfad 548 serverseitig 537
KOMPENDIUM
JavaScript
Stichwortverzeichnis setzen 542 Sicherheit 539 Sicherheitseinstellungen 548 temporär 547 Test 550 cos() 168 Countdown 195 createElement() 323, 325 Auswahllisten 517 createPopup() 464 createRange() 499 createStyleSheet() 593 createTextNode() 323, 325 CSS (Cascading Style Sheets) 581 Versionen 581 cssText (Eigenschaft), styleSheet-Objekt 596 ctrlKey (Eigenschaft) event-Objekt IE 347 event-Objekt W3C 350 current (Eigenschaft), history-Objekt 433 currentTarget (Eigenschaft), event-Objekt W3C 350 cursor (Eigenschaft) style-Objekt 614 Werte 616
D Data Binding 558 Tabellen 614 dataTransfer-Objekt 627 Datei, Änderungsdatum 201 Datei-Upload 521 prüfen 651 Datenmissbrauch 675 Datenspeicherung, eval() 234 Datenspionage 675 Datentyp 57 Array 66 Boolean 65 Funktion 66 in Arrays 209 Infinity 67 Integer 58 NaN 67 Object 66 String 57 undefined 66 Zahl 57 Date-Objekt 166, 177 erweitern 271 Methoden 179 neue Methoden 198
KOMPENDIUM
JavaScript
Datum 177 Änderungsdatum einer Datei 201 eigene 185 formatieren 196 prüfen 669 Wochentag feststellen 111 Debugging 283 Browser 283 Editoren 291 Error 298 Error-Objekt 206 EvalError 298 Fehler 292 Fehler abfangen 294 Fehlerart feststellen 297 Fehler-Handling 294 RangeError 298 ReferenceError 298 RegExpError 298 SyntaxError 298 throw 301 TypeError 298 URIError 298 decodeURI() 155 decodeURIComponent() 155 default-Anweisung 113 defaultChecked (Eigenschaft) 503 defaultValue (Eigenschaft), Schaltflächen 526 Deklarieren 67 Dekrement 84 Reihenfolge 84 delete-Anweisung 215 deleteCell() 613 deleteRow() 613 deleteRule() 598 dependent (Fenstereinstellung) 471 description (Eigenschaft) ErrorObject 299 Plugin-Objekt 700 DHTML 361, 601 Animation 638 Browserunterscheidung 386 der Maus folgen 616 Grundlagen 602 Hilfetext 628 Maus 614 Navigation 628 neuere Ansätze 608 permanent platzieren 634 Positionierung 618 sichtbar und unsichtbar 628 751
Stichwortverzeichnis Tabellen 611 W3C DOM 327 Dialogfelder 459 Internet Explorer 463 schließen 480 Dictionary-Objekt 205 Direct Animation 607 directories (Fenstereinstellung) 471 disabled (Eigenschaft), styleSheet-Objekt 591 do while-Schleife 128 document 395 Änderungsdatum des Dokuments 201 document.write() 38 document.writeln() 38 document.all 386, 603 document.close() 478 document.cookie 542 document.layers 386 document.write() 38, 478 document.writeln() 38 document-Objekt 309, 333, 335 close() 478 cookie 542 form-Objekt 335 DOM (Document Object Model) 165, 305 DOM-Baum 306 Eigenschaften W3C 320 in den Browsern 328 Knoten 309 Level 308 Methoden W3C 323 W3C 308 Domain, Cookies 548 Drag&Drop 620 dropEffect (Eigenschaft), dataTransfer-Objekt 627 Drucken 456 DSO (Data Source Objects) 558 Dynamic HTML 601
E E (Konstante) 167 ECMAScript 34 ActionScript 35, 706 Schlüsselwörter 73 v4 741 Editoren 739 effectAllowed (Eigenschaft), dataTransfer-Objekt 628 Eigenschaften 161 Auswahllisten 507 eigene 254
752
Error-Objekt 296 Frame-Objekt 561 Frameset-Objekt 559 Function-Objekt 276 iFrame-Objekt 577 image-Objekt 424 location-Objekt 436 mathematisch 167 Number-Objekt 202 Object 267 else if-Anweisung 105 Entstehung 107 else-Anweisung 105 E-Mail, prüfen 669 enabledPlugin ( (Eigenschaft), mimeType-Objekt 702 enablejavascript-Attribut 704 encodeURI() 155 encodeURIComponent() 155 Encoding 153 Endlosschleife 115, 293 Engines 739 FESI 740 Microsoft Windows Scripting-Engine 740 Rhino 740 Spidermonkey 740 Enumeration-Objekt 205 Ereignis-Modell 339 Internet Explorer 344 Netscape Navigator 340 W3C 347 Ereignisse 47, 339 <script for> 53 Browserübergreifend 353 Frames 557 in der Praxis 351 Internet Explorer 356 Tastatur 357 Übersicht 354 Error-Objekt 206, 296 Eigenschaften 296 Fehlerarten 298 escape() 153, 533, 542 Escape-Sequenz 63 eval() 151, 234, 697 Datenspeicherung mit 234 Event-Bubbling 345 Event-Capturing 341 Event-Handler 47, 131, 339 onchange 49 onclick 48f.
KOMPENDIUM
JavaScript
Stichwortverzeichnis onerror 303 onload 49 onmouseout 49 onmouseover 49 onunload 49 Event-Listener 348 event-Objekt Internet Explorer 345 Netscape Navigtor 4.x 342 W3C 349 exec() 666 exp() 168 Exponential-Schreibweise 61 extRange-Objekt 499
F Fallunterscheidung 103 false 65 Fehlerbehandlung 283 Fehler-Handling 294 Fenster 459 Bestätigung 461 bewegen 487 Eingabe 462 Einstellungen 469 Größe 640 mit signiertem Skript 474 schließen 480 skalieren 487 unterdrücken 476 FESI 740 fileCreatedDate() 201 fileModifiedDate() 201 fileName (Eigenschaft) 299 filename (Eigenschaft), Plugin-Objekt 700 FileSystemObject 205 File-Upload 521 Filter (Internet Explorer) 604 filter (Stil-Befehl) 604 filter-Objekt 605 finally-Block 295 firstChild (Eigenschaft) 314, 321 fixed (Eigenschaft) 635 fixed (Stil-Befehl) 634 fixed() 238 Flags (Reguläre Ausdrücke) 664 Flash 706 ActionScript 35 Browserprobleme 712 Flash-Player 706
KOMPENDIUM
JavaScript
Tell-Target-Methoden 709 Veröffentlichungen 710 von JavaScript zugreifen 707 zu JavaScript 709 Zugriff 708 Float 60 Floating Frames 573 floor() 168 focus() 476 Fokus 475 fontcolor() 238 for-Attribut 531 for-in-Schleife 123, 213, 260 form-Objekt 335, 531 submit() 535 Formulare 491 Checkboxen 502 Cookies 659 Datei-Upload 521 Daten übernehmen 659 Elemente 494 Elemente prüfen 648 Falscheingaben 647 mit Bildern 406 Passwortfelder 494 Schaltflächen 523 Textfelder 494 Übergabe mit URL 659 versenden 527, 532 versteckte Felder 495 verstecktes Formularfeld 407 Vollständigkeitsüberprüfung 647 Werte in Cookie speichern 532 Zugriff 491 for-Schleife 116 forward() 431 frameBorder (Eigenschaft) Frame-Objekt 562 Frameset-Objekt 559 iFrame-Objekt 577 Frame-Objekt 334 Eigenschaften 561 Frames 553 Ereignisse 557 erzwingen 573 formatieren 558 Hierarchie 556 JavaScript-Link 568 mehrere Seiten ändern 568 mit JavaScript füllen 571
753
Stichwortverzeichnis Tricks 568 und History 572 unsichtbar 570 vermeiden 573 Zugriff 554 frames[], iFrames 575 Frameset 553 verschachtelt 564 Frameset-Objekt, Eigenschaften 559 frameSpacing (Eigenschaft), Frameset-Objekt 559 fromCharCode() 246, 357 fscommand() (ActionScript) 709 fullscreen (Fenstereinstellung) 471 function 131 Objekte 253 Function-Objekt 166, 275 Eigenschaften 276 Methoden 278 Funktionen 131 abbrechen 136 als Objekt 275 als Operator 144 Aufrufe verschachteln 137 decodeURI() 155 decodeURIComponent() 155 eigene 131 encodeURI() 155 encodeURIComponent() 155 escape() 153 eval() 151 Funktionsreferenz 229 globale 145 isFinite() 58, 146 isNaN() 146 Number() 77, 149 Parameter 133 parseFloat() 77, 150 parseInt() 77, 150 Rekursion 142 Rückgabe 134 toString() 77, 148 Typkonvertierung 77 unescape() 154 unwatch() 156 verschachteln 138 watch() 156 Funktionsliteral 144
754
G Galeon 733 Garbage Collection 77 Gecko 732 GET 533, 659 getAttributeNode() 323 getDate() 178f. getDay() 179 getElementById() 310, 386, 558 in der Praxis 310 getElementsByTagName() 310, 312 getFullYear() 179, 188 getHours() 179, 192 getMember() (Java) 697 getMilliseconds() 179 getMinutes() 179 getMonth() 180, 196 getSeconds() 180 getSelection() 499 getTime() 180, 191 getTimezoneOffset() 180, 182 getURL() (ActionScript) 710 getUTCDate() 180 getUTCDay() 180 getUTCFullYear() 180 getUTCHours() 180 getUTCMilliseconds() 180 getUTCMinutes() 180 getUTCMonth() 180 getUTCSeconds() 180 getVarDate() 199 GetVariable() (Flash-Zugriff) 708 getWindow() (Java) 697 getYear() 180, 187 GIF (Compuserve Graphics Interchange Format) 410 Global 140 Funktionen 145 Global-Objekt 206 go() 431 GotoFrame() (Flash-Zugriff) 708 Gültigkeitsbereich, Variablen 140
H handleEvent() 342 hasAttributes() 323 hasChildNodes() 323 hash (Eigenschaft) 436 hasOwnProperty() 268
KOMPENDIUM
JavaScript
Stichwortverzeichnis height (Eigenschaft) Frame-Objekt 562 image-Objekt 421 td-Objekt 614 height (Fenstereinstellung) 471 height-Attribut, Plugins 700 Hexadezimal 58 hidden (verstecktes Textfeld) 499 hidden-Attribut, Plugin 700 History 431 und Frames 572 history-Objekt 335, 431 host (Eigenschaft) 436 hostname (Eigenschaft) 436 HotJava 737 hotkeys (Fenstereinstellung) 471 Hover-Effekt 582 href (Eigenschaft) link-Objekt 438 location-Objekt 336, 434 styleSheet-Objekt 593 hspace (Eigenschaft) iFrame-Objekt 577 image-Objekt 424 HTML Event-Handler 48 JavaScript einbauen 37 Kommentare 39 htmlFor (Eigenschaft), 531 HTTP (HyperText Transfer Protocol) 533 statuslos 537 HTTP-Header 533
I Identifier (ID) 589 Identitätsoperator 88 IETF (Internet Engineering Task Force) 46, 538 if-Anweisung 103 Kurzformen 108 verschachteln 109 iFrame-Objekt 577 Eigenschaften 577 iFrames 573 einsetzen 578 IIS (Internet Information Service) 715 Imagemaps 427 image-Objekt 395 Eigenschaften 424 Vorladen 402
KOMPENDIUM
JavaScript
imports (Eigenschaft), styleSheet-Objekt 593 in (Inch) 583 index (Eigenschaft) Auswahllisten 508 RegExp-Objekt 665 indexOf() 248, 380, 654 Infinity 60, 67, 292 Initialisierung 68 Inkrement 83 Reihenfolge 84 innerHeight (Eigenschaft) 422 innerHeight (Fenstereinstellung) 471 innerHTML (Eigenschaft) 608 Fehlermeldung 656 innerText (Eigenschaft) 608 innerWidth (Fenstereinstellung) 471 in-Operator 124 input (Eigenschaft), RegExp-Objekt 665 insertAdjacentHTML() 609 insertAdjacentText() 609 insertBefore() 323 insertCell() 611 insertRow() 611 insertRule() 598 Instanz 254 Instanziieren 161 Integer 58 größte speicherbare Zahl 58 Internet Explorer 729 ActiveX-Objekte 205 Behavior 606 Debugging 284 Dialogfelder 463 DOM der Version 4 330 Drag&Drop 627 DSO (Data Source Objects) 558 Ereignis-Modell 344 Mac 729 Sicherheitseinstellungen 541 Sicherheitskonzept 679 Internet Explorer 4, DHTML 603 Interpolation 420 isFinite() 58, 146 isNaN() 93, 146, 668 IsPlaying() (Flash-Zugriff) 708 isPrototypeOf() 269 italics() 238
755
Stichwortverzeichnis
J Jahr-2000-Problem 187 jar-Archiv 680 Java 691 classpath 696 Datentyp-Umwandlung 698 JSException 696 JSObject 696 zu JavaScript 696 Zugriff auf Java-Applets 693 Java Virtual Machine (JVM) 691 Java-Applets 692 Ladestand prüfen 696 mit JavaScript steuern 694 javaEnabled() 696 JavaScript Anweisung 70 case-sensitive 71 Code ausführen 151 deaktiviert 38, 363 Drucken 456 Editoren 739 Einsatzgebiete 35 Einschränkungen 36 Engines 739 externe Datei 43 In HTML einbauen 37 Java 691 JScript 50 nicht typisiert 67 Objekte 159 – Übersicht 165 Passwortschutz 690 Short-circuit 95 Sicherheit 675 Standardobjekte 166 Syntax 57 Typkonvertierung 77 Version 2.0 741 Versionsunterscheidung 49 zu Flash 707 javascript 46, 571 JavaScript1.2, Netscape Navigator 4.x 51 JavaScript-Debugger 288 JavaScript-Konsole 287 Opera 290 JavaScript-Links 46 JavaScript-Stylesheets (JSSS) 587 join() 222
756
JPEG (Joint Photographic Experts Group) 411 JScript 32 JavaScript 50 Reservierte Schlüsselwörter 74 JScript .NET 35, 713 Browser-Eigenschaften 390 js-Datei 43 JSObject-Objekt 694
K KDE (K Desktop Environment) 735 keyCode (Eigenschaft) event-Objekt IE 347 event-Objekt W3C 350 KHTML 33, 736 Klasse 160 Stylesheets 582 K-Melon 733 Knoten 309 Child 314 Hierarchie 314 Parent 314 Siblings 314 Zugriff 309 Komma-Operator 117 Kommentare 78 einzeilig 78 mehrzeilig 78 Kompatibilität Ereignisse 353 Flash 712 Mauskoordinaten 623 Scroll-Position feststellen 635 Konditionaler Operator 109 Konkatenation 85 Konqueror 735 Cookies 542 Probleme bei Browserunterscheidung 368 Konstanten 79 mathematisch 167 Konstruktor 161, 253, 662 RegExp 665 Kontextmenü verhindern 685 Kontrollstrukturen 103 default-Anweisung 113 do while-Schleife 128 else if-Anweisung 105 else-Anweisung 105 for-in-Schleife 260
KOMPENDIUM
JavaScript
Stichwortverzeichnis for-Schleife 116 if-Anweisung 103 Kurzformen 108 Schleifen 115 switch case-Anweisung 110
L label 531 language 362 Version 49 language (Eigenschaft) 379 lastChild (Eigenschaft) 321 lastIndex (Eigenschaft), RegExp-Objekt 665 lastIndexOf() 248 lastMatch (Eigenschaft), RegExp-Objekt 665 lastModified() 201 lastParen (Eigenschaft), RegExp-Objekt 665 Latin-1 64 Laufschrift 453 im Textfeld 453 komplex 448 schützen 455 Statusleiste 445 umkehren 448 Laufzeitfehler 292 Layer 361, 603 layerX (Eigenschaft) event-Objekt NN4x 344 event-Objekt W3C 349 layerY (Eigenschaft) event-Objekt NN4x 344 event-Objekt W3C 349 left (Fenstereinstellung) 471 leftContext (Eigenschaft), RegExp-Objekt 665 length, history-Objekt 432 length (Eigenschaft) 277 Array-Objekt 209 Plugin-Objekt 700 String-Objekt 236 lineNumber (Eigenschaft) 299 link() 238 Links 438 JavaScript 46 Linux 735 Literal 57 Array-Literal 209 Funktionsliteral 144 Reguläre Ausdrücke 662 LiveAudio 699 Liveconnect 692
KOMPENDIUM
JavaScript
LiveScript 32 LN10 (Konstante) 167 LN2 (Konstante) 167 LoadMovie() (Flash-Zugriff) 709 localeCompare() 91, 249 localName (Eigenschaft), für XML-Namespaces 325 location (Fenstereinstellung) 471 location-Objekt 336, 434 Eigenschaften 436 log() 168 LOG10E (Konstante) 167 LOG2E (Konstante) 167 Logikfehler 293 Logische Operatoren 93 Mischen 96 Lokal 140 lowsrc 405 lowsrc-Attribut 405 Lynx 738
M Mac, Internet Explorer 729 MagicCookie 537 mailto 46, 533 marginHeight (Eigenschaft) Frame-Objekt 562 iFrame-Objekt 578 marginWidth (Eigenschaft) Frame-Objekt 562 iFrame-Objekt 578 Mark-and-Sweep-Algorithmus 77 mastersound-Attribut 700 match() 250, 664 Reguläre Ausdrücke 666 Math-Objekt 166 Eigenschaften/Konstanten 167 erweitern 273 Methoden 168f. Maus 614 Drag&Drop 620 Koordinaten 617, 623 Mauszeiger 614 Spuren 616 max() 168, 175 MAX_VALUE 202 maxLength (Eigenschaft), Textfeld 500 mayscript-Attribut 697 media (Eigenschaft) styleSheet-Objekt 596 Stylesheets 585
757
Stichwortverzeichnis Mehrdimensionale Arrays 210 Mehrzeilige Textfelder 501 menubar (Fenstereinstellung) 471 message (Eigenschaft) 299 Metazeichen 663 method-Attribut 528 Methoden 162 Array-Objekt 217 big() 162 Boolean-Objekt 202 Date-Objekt 179 eigene 255 Function-Objekt 278 mathematisch 168f. Number-Objekt 203 Object 267 Parameter 163, 256 Regular Expression-Objekt 666 String-Formatierungsmethoden 237 String-Objekt 239 Microsoft 32 Windows Media Player 699 Microsoft Debugger 285 Microsoft Intermediate Language (MSIL) 713 Microsoft Windows Scripting-Engine 740 Millisekunden 186 MIME (Multipurpose Internet Mail Extension) 45, 702 mimeType-Objekt 702 min() 168, 175 MIN_VALUE 202 mm (Millimeter) 583 Mnemonic 738 Mono 716 Mosaic 32 moveBy() 487 moveTo() 487 Mozilla 733 Cookies 541 Debugging 288 Sicherheitskonzept 680 MSDE (Microsoft SQL Desktop Engine) 715 MSHTML-Control 558 Multidimensionale Arrays 211 multiline (Eigenschaft), RegExp-Objekt 666 Multimedia 698 multiple (Eigenschaft) 509 multiple-Attribut 506, 509
758
N name (Eigenschaft) 296 Anker 440 Checkbox 503 Error-Objekt 299 Plugin-Objekt 700 Radiobuttons 504 Schaltflächen 526 name-Attribut 492 Frames 555 namespaceURI (Eigenschaft), für XML-Namespaces 325 NaN 67, 202, 293 Navigation, Mitscrollen verhindern 634 navigator-Objekt 334, 364 Cookies 550 Eigenschaften 365 javaEnabled() 696 plugins() 700 NCSA Mosaic 738 Negation 93 NEGATIVE_INFINITY 203 Netscape 32 Netscape Navigator 731 Cookie-Manager 548 Cookies 541 Debugging 286 Ereignis-Modell 340 JavaScript-Konsole 287 LiveAudio 699 Liveconnect 692 Popups unterdrücken 476 Reservierte Schlüsselwörter 73 Sicherheitskonzept 680 Netscape Navigator 4.x DHTML 603 DHTML-Probleme 631 DOM 329 JavaScript1.2 51 Stylesheets 587 Stylesheet-Zugriff 585 new 161, 207 next (Eigenschaft), history-Objekt 433 nextSibling (Eigenschaft) 314, 321 Node 309 nodeName (Eigenschaft) 322 nodeType (Eigenschaft) 322 nodeValue (Eigenschaft) 322 noResize (Eigenschaft), Frame-Objekt 562 noresize-Attribut 562 noWrap (Eigenschaft), td-Objekt 614
KOMPENDIUM
JavaScript
Stichwortverzeichnis NUL 63 null 66, 215 Number 57, 60 Exponential 61 Float 60 Gleitkommazahlen 60 Hexadezimal 58 Oktal 59 number (Eigenschaft) 299 Number() 77, 149 Number-Objekt 166, 202 Eigenschaften 202 Methoden 203
O Object 166 Datentyp 66 Eigenschaften 267 Methoden 267 Vererbung 265 Objekte 159 an Funktionen übergeben 281 className-Objekt 588 dataTransfer-Objekt 627 eigene 253 eigene Einsatzgebiete 259 erweitern 271 filter-Objekt 605 for-in-Schleife 260 JSObject-Objekt 694 mimeType-Objekt 702 Plugin-Objekt 700 RegExp-Objekt 665 Regular Expression-Objekt 662 selection-Objekt 499 style-Objekt 585 styleSheet-Objekt 590 td-Objekt 613 TextRange-Objekt 499 Übersicht 165 with-Anweisung 261 Objektidentität 161 Objektorientierung 159, 253 Eigenschaften 160, 254 Grundlagen 160 Instanziieren 161 Klasse 160 Methoden 160, 255 Objektidentität 161
KOMPENDIUM
JavaScript
Polymorphismus 165 Unterklasse 164 Vererbung 164 offsetX (Eigenschaft), event-Objekt IE 347 offsetY (Eigenschaft), event-Objekt IE 347 Oktal 59 onabort 356 image-Objekt 406 onafterprint 458 Frames 558 onafterupdate, Frames 558 onbeforeprint 458 Frames 558 onbeforeupdate, Frames 558 onblur 356 onchange 49, 355 Auswahlliste 506 Textfelder 497 Vollständigkeitsüberprüfung 647, 656 onclick 48f., 355 524 525 Checkboxen 503 Probleme beim Scrollen 485 onContextmenu 685 ondblclick 355 onDrag 627 onDragOver 627 onDragStart 627 onerror 303, 356 imageObjekt 406 onerrorupdate, Frames 558 onfocus 356, 455 onkeydown 355 Konqueror 357 onkeypress 355 Konqueror 357 onkeyup 355 Konqueror 357 onload 49, 356 Bild 404 Frames 557 onmousedown 355 Drag&Drop 621 onmousemove 355 Drag&Drop 621 onmouseout 49, 355 <area> 427 Rollover 396
759
Stichwortverzeichnis onmouseover 48, 355 <area> 427 525 Rollover 396 Statusleiste 446 onmouseup 355 Drag&Drop 621 onmove 356 onreset 355, 529 onresize 356 onscroll 356, 486 onselect 356 Textauswahl 498 onsubmit 355, 528 Vollständigkeitsüberprüfung 647 onunload 49, 356 Frames 558 OOP 159 open() 467 Einstellungen 469 Parameter 467 opener (Eigenschaft) 482 Opera 734 Cookies 541 Debugging 290 Popups unterdrücken 477 Probleme bei Browserunterscheidung 367 Operanden 82 Operatoren 81, 93 Addition 83 Arithmetisch 83 Arithmetische Operatoren 84 Bitweise 96 Dekrement 84 Division 83 Funktionen als 144 Genau ungleich 88 Gleichheit 87 Größer als 87 in 124 Inkrement 83 Kleiner als 87 Kleiner gleich 87 Komma 117 Konditionaler Operator 109 Logisches ODER 94 Logisches UND 94 Modulo 83 Negation 83, 93 Präferenz 102 Strings vergleichen 90 760
Subtraktion 83 Ungleichheit 87 Vergleichsoperatoren 87 Optionen 502 Option-Objekt 512 outerHeight (Fenstereinstellung) 472 outerHTML (Eigenschaft) 608 outerText (Eigenschaft) 608 outerWidth (Fenstereinstellung) 472 ownerDocument (Eigenschaft) 322 ownerNode (Eigenschaft), styleSheet-Objekt 597 owningElement (Eigenschaft), styleSheet-Objekt 597 owningNode (Eigenschaft), styleSheet-Objekt 597
P pageX (Eigenschaft) event-Objekt NN4x 344 event-Objekt W3C 349 Maus 618 pageY (Eigenschaft) event-Objekt NN4x 344 event-Objekt W3C 349 Pan() (Flash-Zugriff) 709 Parameter 133, 163 Methoden 256 open() 467 Standardwerte 258 parent (Eigenschaft), Frames 555, 566 Parent (Knoten) 314 parentNode (Eigenschaft) 314, 322 parentStyleSheet (Eigenschaft), styleSheet-Objekt 597 parse(Datum) 180 parseFloat() 77, 150 parseInt() 77, 150 password (Passwortfeld) 499 Passwortfelder 494 Passwortschutz 690 pathname (Eigenschaft) 436 PercentLoaded() (Flash-Zugriff) 709 Persistente Cookies 547 Pfad, Cookies 548 Phoenix 733 PHP 35, 491 PI (Konstante) 167 Play() (Flash-Zugriff) 709 Plugin-Objekt 700 Plugins erkennen 700 steuern 698 Steuerungsmöglichkeiten 703
KOMPENDIUM
JavaScript
Stichwortverzeichnis plugins() 700 PNG (Portable Network Graphics) 411 Polymorphismus 165 pop() 228 Popups 459 erzeugen 467 füllen 478 schließen 480 unterdrücken 476 port (Eigenschaft) 436 POSITIVE_INFINITY 203 POST 533 Postleitzahl prüfen 667 pow() 168 Präferenz, Operatoren 102 Precaching 402 prefix (Eigenschaft), für XML-Namespaces 325 Preloading 402 preventDefault() 351 previous (Eigenschaft), history-Objekt 433 previousSibling (Eigenschaft) 322 print() 456 Privileg UniversalBrowserAccess 683 UniversalBrowserRead 683 UniversalBrowserWrite 682f. UniversalFileAccess 684 UniversalFileRead 684 UniversalFileWrite 684 UniversalPreferencesRead 683 UniversalPreferencesWrite 684 UniversalSendMail 684 UniversalXPConnect 683 Programmierfehler 292 prompt() 462, 656 propertyIsEnumerable() 269 protocol (Eigenschaft) 436 prototype, Objekte erweitern 271 prototype-Vererbung 262 Vererbungskette 265 Prozedurales Programmieren 159 Pseudo-Klassen 582 pt (Punkt) 583 push() 228 px (Pixel) 583
Q QuickTime 699 Scripting 704
KOMPENDIUM
JavaScript
R Radiobuttons 504 prüfen 649 Rahmen 553 random() 168 readOnly (Eigenschaft) styleSheet-Objekt 597 Textfeld 500 RealPlayer 699 Scripting 705 Rechnen 169 RegExp-Objekt 166, 665 Reguläre Ausdrücke 662 Anwendungen 667 Flags 664 Metazeichen 663 String-Objekt 250 Syntax 663 Regular Expression-Objekt 662 Methoden 665f. Reguläre Ausdrücke 663 Rekursion 142 releaseEvents() 341 reload() 436 remove() 516 removeAttributeNode() 323 removeBehavior() 607 removeChild() 324 removeEventListener() 349 removeRule() 598 repeat (Eigenschaft), event-Objekt IE 347 replace() 250, 437, 664 replaceChild() 324 Reservierte Schlüsselwörter 72 Reset 529 reset() 531 resizable (Fenstereinstellung) 472 resizeBy() 487 resizeTo() 487 return 134, 652 reverse() 223 Rewind() (Flash-Zugriff) 709 RGB-Farbwerte 583 Rhino 740 rightContext (Eigenschaft), RegExp-Objekt 666 Rollover 395 ältere Browser 398 Automatisieren 397 mit Stylesheet 586 round() 169
761
Stichwortverzeichnis routeEvent() 342 rows (Eigenschaft) Frameset-Objekt 559 mehrzeiliges Textfeld 501 rowspan (Eigenschaft), td-Objekt 613 Runden 173 Nachkommastellen 173
S Safari 736 Schaltflächen 523 im Formular 525 mit Grafik 529 Reset 529 Schleifen 115 beschriften 122 do while-Schleife 128 Endlosschleife 115 for 116 for-in 123 verschachteln 121 while 125 Schlüsselwörter 72 screen-Objekt 422 Fensterinformationen nutzen 488 screenX (Eigenschaft) event-Objekt IE 347 event-Objekt NN4x 344 event-Objekt W3C 349 screenX (Fenstereinstellung) 472 screenY (Eigenschaft) event-Objekt IE 347 event-Objekt NN4x 344 event-Objekt W3C 349 screenY (Fenstereinstellung) 472 scroll() 484, 638 scrollbars (Fenstereinstellung) 472 scrollBy() 485, 638 scrollByLines() 485 scrollByPages() 485 Scrollen 484 Objekt fixieren 634 Scroll-Position feststellen 635 verhindern 486 scrolling (Eigenschaft) Frame-Objekt 562 iFrame-Objekt 578 scrollTo() 485, 638 SDK (Software Development Kit) 715 search (Eigenschaft), location-Objekt 436, 659
762
search() 250, 664 Seitenvorschub 63 select() 498 selectedIndex (Eigenschaft) 507 Auswahllisten 650 selection-Objekt 499 Select-Objekt 516 self (Eigenschaft), Frames 555 serverseitig JScript .NET 713 programmieren 713 Vollständigkeitsüberprüfung 658 Sessionmanagement 724 setAttribute() 324 setAttributeNode() 324 setDate() 179 setDay() 179 setFullYear() 179 setHours(Wert) 179 setInterval() 194, 414, 435, 445, 639 setMilliseconds() 179 setMinutes() 179 setMonth() 180 setSeconds() 180 setTime() 180 setTimeout() 411, 435, 445 setUTCDate() 180 setUTCDay() 180 setUTCFullYear() 180 setUTCHours() 180 setUTCMilliseconds() 180 setUTCMinutes() 180 setUTCMonth() 180 setUTCSeconds() 180 SetVariable() (Flash-Zugriff) 709 setYear() 180, 187 SetZoomRect() (Flash-Zugriff) 709 shift() 231 shiftKey (Eigenschaft), event-Objekt W3C 350 Short-circuit 95 show() 464 showModalDialog() 463 showModelessDialog() 464 Siblings (Knoten) 314 Sicherheit 675 ActiveX-Controls 676 Cookies 539, 676 Lecks 675 Same Origin-Prinzip 676 Schutz für Eigentum 675 Zertifikate 676
KOMPENDIUM
JavaScript
Stichwortverzeichnis Signed Scripts 433 Signierte Skripte 678, 680 Fenster 474 Privileg 682 sin() 169 Sitemap 483 size (Eigenschaft) Auswahllisten 508 Schaltflächen 526 Textfeld 500 Skript absichern 684 Auslagern 43 slice() Array-Objekt 224 String-Objekt 243 small() 238 sort(), Array-Objekt 218 Sound 698 Spidermonkey 740 splice(), Array-Objekt 226 split() Reguläre Ausdrücke 665 String-Objekt 244, 495 Sprache feststellen 379 ältere Browser 382 Sprachversionen 383 sqrt() 169 SQRT1_2 (Konstante) 167 SQRT2 (Konstante) 167 src (Eigenschaft) Frame-Objekt 562 iFrame-Objekt 578 image-Objekt 395 srcElement (Eigenschaft), event-Objekt IE 347 srcFilter (Eigenschaft), event-Objekt IE 347 status (Eigenschaft) 442 status (Fenstereinstellung) 472 Statusleiste 442 ändern 442 Laufschrift 445 Linkanzeige automatisieren 443 StopPlay() (Flash-Zugriff) 709 stopPropagation() 351 strike() 238 String 57, 236 Escape-Sequenz 63 formatieren 237 Konkatenation 85 Länge 62, 236
KOMPENDIUM
JavaScript
localeCompare() 91 Vergleichen 90 String-Objekt 166, 236 Formatierungsmethoden 237 Methoden 239 style-Attribut 582 style-Objekt 313, 584f. vom CSS-Befehl zur Eigenschaft 586 styleSheet-Objekt 585, 590 Eigenschaften und Methoden 595 Methoden und Eigenschaften 593 Stylesheets 581 Einheiten 583 Elemente überlappen 632 externe einbinden 582 Farben 583 fixed 634 ID wechseln 589 in der Praxis 598 Positionierung 618 Regeln 593 Stil-Befehle 582 Syntax 583 wechseln 590 Zugriff 584 sub() 238 Submit 527 submit() 535 substr() 245 substring() 245, 445, 543 sup() 238 supports() 324 SVG (Scaleable Vector Graphics) 35, 706 swapNode() 324 switch case-Anweisung 110 swLiveConnect-Attribut 707 systemLanguage (Eigenschaft) 381
T Tabellen, dynamisch 611 Tabular Data Control (TDC) 558 Tabulator 64 tan() 169 target (Eigenschaft) event-Objekt NN4x 344 event-Objekt W3C 350 link-Objekt 438 Tastaturereignisse 357 td-Objekt 613 Telefonnummern prüfen 668
763
Stichwortverzeichnis Temporäre Cookies 547 test() 667 text (Eigenscahft), 507 Textfelder 494 mehrzeilig 501 prüfen 648 Third Party Cookies 539 this 143, 254f., 476, 505, 586 throw 301 Thumbnails, Zoomen 423 timeStamp (Eigenschaft), event-Objekt W3C 350 title (Eigenschaft), styleSheet-Objekt 597 titlebar (Fenstereinstellung) 472 toDateString() 199 toElement (Eigenschaft), event-Objekt IE (Eigenschaft) 346 toExponential() 203 toFixed() 203 toGMTString() 180, 547 Token 75 toLocaleDateString() 199 toLocaleLowerCase() 241 toLocaleString() 199 Array-Objekt 232 Number-Objekt 203 Object 270 toLocaleTimeString() 199 toLocaleUpperCase() 241 toLowerCase() 239 toolbar (Fenstereinstellung) 472 top (Eigenschaft), Frames 555 top (Fenstereinstellung) 472 toPrecision() 204 toSource() 278 toString() 77, 148, 279 Array-Objekt 232 Boolean-Objekt 202 Date-Objekt 181 Number-Objekt 204 Object 270 String-Objekt 251 TotalFrames() (Flash-Zugriff) 709 toTimeString() 199 toUpperCase() 239 toUTCString() 181 Transitions 606 Trigonometrie 171 true 65 try-catch-Anweisung 294 type 45
764
type (Eigenschaft) Checkbox 503 event-Objekt IE 347 event-Objekt NN4x 344 event-Objekt W3C 350 Formularelemente 651 Schaltflächen 527 Stylesheets 585 Textfelder 499 Typisierung 67 Typkonvertierung 77, 147 Funktionen 77 Vergleichsoperatoren 88
U Uhrzeit 177 Auf Tageszeit reagieren 192 Counter 195 GMT 181 UTC 182 Zeitverschiebung 182 undefined 66 Unendlichkeit 146 unescape() 154, 533, 542 Unicode 64, 75 UniversalBrowserAccess 683 UniversalBrowserRead 683 UniversalBrowserWrite 682f. UniversalFileAccess 684 UniversalFileRead 684 UniversalFileWrite 684 UniversalPreferencesRead 683 UniversalPreferencesWrite 684 UniversalSendMail 684 UniversalXPConnect 683 Unix-Zeitstempel 186 unshift() 231 Unsignierte Skripte, testen 680 unwatch() 156 URI-Codierung 153 URL (Uniform Resource Locator) 153 GET 659 Usability 407 useMap (Eigenschaft), image-Objekt 427 userAgent (Eigenschaft) 365 userLanguage (Eigenschaft) 381 UTC (Universal Time Coordinated) 182 UTC() 181
KOMPENDIUM
JavaScript
Stichwortverzeichnis
V value (Eigenschaft) Auswahllisten 508 Checkbox 503 Radiobuttons 504 Schaltflächen 525, 527 value-Attribut 494 valueOf() 279 Boolean-Objekt 202 Date-Objekt 181 Number-Objekt 204 Object 270 String-Objekt 251 var 67 Variablen 57 Bezeichner 71 deklarieren 67 global 140 Gültigkeitsbereich 140 Initialisierung 68 lokal 140 mehrere 70 Namen 71 reservierte Schlüsselwörter 72 Werte ändern 69 Werte zuweisen 68 VBArray-Objekt 205 VBScript 31 Venkman (Codename f. Mozilla) 288 Vererbung 164 prototype 262 Vererbungskette 265 Vergleichsoperatoren 87 Strings 90 Typkonvertierung 88 Verhalten 604 Verlauf 431 Versionen 49 Internet Explorer 50 JavaScript1.2 51 Konqueror 51 Mozilla 51 Netscape Navigator 50 Opera 51 Versteckte Felder 495 view (Eigenschaft), event-Objekt W3C 350 viewsource:url 686 visibility (Eigenschaft), Netscape Navigator 4.x 585 Visual Studio .NET 717 VML (Vector Markup Language) 607
KOMPENDIUM
JavaScript
Vollständigkeitsüberprüfung 647 Automatisieren 651 nachfragen 654 optionale Felder 654 serverseitig 658 Vorladen 402 Mehrere 403 vspace (Eigenschaft) iFrame-Objekt 577 image-Objekt 424
W W3C DOM 308 Ereignis-Modell 347 W3C (World Wide Web Consortium) 33, 45, 581 Wagenrücklauf 63 Warnmeldung 459 watch() 156 Web Matrix 717 Webanwendungen 360 Webseite, neu laden 436 Webserver, für ASP.NET 715 Weiterleitung mit Browserunterscheidung 375 nach Sprache 380 wheelDelta (Eigenschaft), event-Objekt IE 347 which (Eigenschaft), event-Objekt NN4x 344 while-Schleife 125 width (Eigenschaft) Frame-Objekt 562 image-Objekt 421 td-Objekt 614 width (Fenstereinstellung) 472 width-Attribut, Plugins 700 window, clearInterval() 418 window-Objekt 332, 459 alert() 459 blur() 476 clearTimeout() 418 close() 480 closed 482 confirm() 461 createPopup() 464 document-Objekt 333 event-Objekt 345 focus() 476 frame-Objekt 334 history-Objekt 431 moveBy() 487
765
Stichwortverzeichnis moveTo() 487 open() 467 opener 482 print() 456 prompt() 462 resizeBy() 487 resizeTo() 487 screen-Objekt 422 scroll() 484 scrollBy() 485 scrollTo() 485 setInterval() 414 setTimeout() 411 showModelessDialog() 464 status 442 window.Event 617 Windows Media Player (WMP) 699 with-Anweisung 261 World Wide Web (WWW) 31
X X (Eigenschaft), event-Objekt IE 347 X509 684 XHTML 37 XML DSO 558
766
Y Y (Eigenschaft), event-Objekt IE 347 Y2K 187
Z Zeichenkette 61 Zeichensatz 64, 75 Zeilenumbruch 63 Zeit 177 Zeitverschiebung 182 von Hand 182 Zerstörung von Daten 675 Zertifikat 433, 676 Grundprinzip 677 X509 684 zIndex (Eigenschaft) 632 z-lock (Fenstereinstellung) 472 Zoom() (Flash-Zugriff) 709 Zufallszahlen 176 beliebige 176 Rollover mit 400 Zuweisungsoperator 81 Kurzformen 84
KOMPENDIUM
JavaScript
Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen eBook-Zusatzdaten sind urheberrechtlich geschützt. Dieses eBook stellen wir lediglich als Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses eBooks und zugehöriger Materialien und Informationen, einschliesslich der Reproduktion, der Weitergabe, des Weitervertriebs, der Plazierung auf anderen Websites, der Veränderung und der Veröffentlichung bedarf der schriftlichen Genehmigung des Verlags. Bei Fragen zu diesem Thema wenden Sie sich bitte an: mailto:
[email protected] Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf der Website ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen.
Hinweis Dieses und andere eBooks können Sie rund um die Uhr und legal auf unserer Website
(http://www.informit.de) herunterladen