JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

	Nutzen Sie die HTML-Version zum Reinschnuppern oder als immer verfügbare Ergänzung zu Ihrem Buch. Wir hoffen auf Ihre zahlreichen  [image] Rückmeldungen zu diesem Angebot ...

Inhalt

1 Einleitung

1.1 Geschichte von JavaScript

1.2 Voraussetzungen

1.3 Danksagung

1.4 Vorwort zur 2. Auflage

1.5 Vorwort zur 3. Auflage

1.6 Die Icons in diesem Buch

2 Vorbereitung

2.1 Verwendung von <SCRIPT>

  2.1.1 Das LANGUAGE-Attribut

  2.1.2 Browser ohne JavaScript

  2.1.3 Externe Dateien

2.2 JavaScript-Links

2.3 Event-Handler

2.4 JavaScript-Entities

3 Programmierung I

3.1 Variablen

  3.1.1 Namensgebung

  3.1.2 Numerische Variablen

  3.1.3 Zeichenketten

  3.1.4 Boolesche Variablen

  3.1.5 Variablendeklaration

3.2 Operatoren

  3.2.1 Arithmetische Operatoren

  3.2.2 Boolesche Operatoren

  3.2.3 String-Operatoren

  3.2.4 Umwandlung zwischen den Variablentypen

3.3 Kontrollstrukturen: Schleifen

  3.3.1 For-Schleifen

  3.3.2 Do-While-Schleife

  3.3.3 While-Schleife

  3.3.4 For-In-Schleife

  3.3.5 Schleifensteuerung

3.4 Fragen & Aufgaben

4 Programmierung II

4.1 Fallunterscheidung

  4.1.1 If-Anweisung

  4.1.2 switch-Anweisung

4.2 Datenspeicherung

  4.2.1 Die eval-Methode

  4.2.2 Arrays

4.3 Funktionen

4.4 Objekte

4.5 Fragen & Aufgaben

5 Erste Schritte

5.1 JavaScript-Objekte

  5.1.1 Das Objekt Date

  5.1.2 Das Objekt Math

5.2 Browser-Erkennung

5.3 Event-Handler

5.4 Fragen & Aufgaben

6 Fenster I

6.1 Modale Fenster

  6.1.1 Warnung – nur im Notfall

  6.1.2 Bestätigungen

  6.1.3 Benutzereingaben

6.2 Navigationsleiste mit JavaScript

  6.2.1 Das History-Objekt

  6.2.2 Vorwärts und Rückwärts Teil 2

  6.2.3 Drucken mit JavaScript

6.3 Die Statuszeile

  6.3.1 Erläuternde Links

  6.3.2 Laufschrift

6.4 Das location-Objekt

6.5 Fragen & Aufgaben

7 Formulare I

7.1 Überprüfung auf Vollständigkeit

  7.1.1 Allgemeiner Aufbau

  7.1.2 Texteingabefelder

  7.1.3 Radiobuttons

  7.1.4 Checkboxen

  7.1.5 Auswahllisten

  7.1.6 Fehlermeldung ausgeben

  7.1.7 Konstruktive Vorschläge

7.2 Automatische Überprüfung

  7.2.1 Texteingabefelder

  7.2.2 Radiobuttons

  7.2.3 Checkboxen

  7.2.4 Auswahllisten

  7.2.5 Zusammenfassung

7.3 Anwendungsmöglichkeiten für Formulare

  7.3.1 Währungsrechner

  7.3.2 Währungsrechner Teil 2

  7.3.3 Formularfelder für die Textausgabe nutzen

  7.3.4 Navigation mit Auswahllisten

7.4 Fragen & Aufgaben

8 Fenster II: Frames

8.1 Mit Frames arbeiten

  8.1.1 Frames mit HTML

  8.1.2 Frames mit JavaScript füllen

8.2 Auf Daten von Frames zugreifen

  8.2.1 Auf übergeordnete Frames zugreifen

  8.2.2 Auf Daten von Unterframes zugreifen

  8.2.3 Mehrere Frames gleichzeitig ändern

  8.2.4 Gefährliche Fallen

8.3 Ein Warenkorb in JavaScript

  8.3.1 Daten in den Warenkorb eintragen

  8.3.2 Daten aus dem Warenkorb auslesen

  8.3.3 Den Warenkorb verändern

8.4 Diashow

  8.4.1 Vorbereitungen

  8.4.2 Diashow starten

  8.4.3 Diashow anhalten

  8.4.4 Vorwärts und rückwärts springen

  8.4.5 Diashow verlassen

8.5 Fragen & Aufgaben

9 Images

9.1 Bildlein-Wechsle-Dich

  9.1.1 Zugriff auf Grafiken

  9.1.2 Prüfungen auf Kompatibilität

9.2 Animierte JPEGs

  9.2.1 Eine Animation mit JavaScript

  9.2.2 Bilder in den Cache laden

9.3 Animierte Navigation

  9.3.1 Vorüberlegungen

  9.3.2 Auf- und Zuklappen

  9.3.3 Die einzelnen Menüpunkte

  9.3.4 Verlinkung der Menüpunkte

  9.3.5 Einbau in die HTML-Datei

9.4 Erweiterung der Navigation

  9.4.1 Vorbereitungen

  9.4.2 Leichte Änderungen

  9.4.3 Doppeltes Mouseover

  9.4.4 Das komplette Beispiel im Überblick

9.5 Tipps aus der Praxis

  9.5.1 Vorladen – aber richtig

  9.5.2 Ladestand einer Grafik

9.6 Fragen & Aufgaben

10 Fenster III

10.1 Ein neues Fenster öffnen

  10.1.1 Ein Fenster öffnen und füllen

  10.1.2 Ein Fenster öffnen und verlinken

  10.1.3 Ein Fenster öffnen und anpassen

  10.1.4 Modale Fenster

10.2 10.2 Fernsteuerung

  10.2.1 Links mit JavaScript

  10.2.2 Links ohne JavaScript

10.3 Fenster schließen

  10.3.1 Andere Fenster schließen

  10.3.2 Lösung für ältere Browser

10.4 Fenster in den Vordergrund holen

10.5 Fenster bewegen mit JavaScript

  10.5.1 Fenster verschieben

  10.5.2 Fensterinhalt scrollen

10.6 Fragen & Aufgaben

11 Cookies

11.1 Was ist ein Cookie?

11.2 Wie sieht ein Cookie aus?

11.3 Cookies mit JavaScript

  11.3.1 Cookies setzen

  11.3.2 Cookies löschen

  11.3.3 Cookies lesen

  11.3.4 Cookie-Unterstützung überprüfen

  11.3.5 Warenkorb mit Cookies

11.4 Informationen behalten ohne Cookies

11.5 Fragen & Aufgaben

12 Formulare II

12.1 Daten behalten

  12.1.1 Das Eingabeformular

  12.1.2 Die Ausgabeseite

12.2 Dynamische Auswahllisten

  12.2.1 Ein erster Ansatz

  12.2.2 Ein fortgeschrittener Ansatz

12.3 Überprüfungsfunktionen

  12.3.1 Ganze Zahlenwerte

  12.3.2 Dezimalzahlen

  12.3.3 Telefonnummern

  12.3.4 In Zahlenwerte umwandeln

12.4 Reguläre Ausdrücke

  12.4.1 Kurzeinführung

  12.4.2 Ein Objekt erzeugen

  12.4.3 Mit dem Objekt arbeiten

12.5 Fragen & Aufgaben

13 Arrays

13.1 Array-Erweiterungen

  13.1.1 Einfügen, nicht anfügen

  13.1.2 Anfügen und löschen

  13.1.3 Karten mischen

  13.1.4 Sortieren

13.2 Eigene Objekte

  13.2.1 Allgemeines

  13.2.2 Methoden definieren

  13.2.3 Eigene Sortiermethode

  13.2.4 Eigene Sortiermethode, Teil 2

  13.2.5 Zusammenfassung

13.3 Fragen & Aufgaben

14 Musik

14.1 Plugins erkennen

  14.1.1 Zugriff auf Plugins

  14.1.2 Zugriff auf MIME-Typen

  14.1.3 Refresh

14.2 Zugriff auf Musikdateien

  14.2.1 Browsertest

  14.2.2 Soundsteuerung

  14.2.3 Jukebox

15 Events

15.1 Events mit dem Netscape Navigator

  15.1.1 Neue Ereignisse

  15.1.2 Ereignisse als Objekteigenschaften

  15.1.3 Ereignisse abfangen

  15.1.4 Ereignisbehandlung

  15.1.5 Ereignisse umleiten

  15.1.6 Ereignisse durchleiten

  15.1.7 Tastatureingaben

15.2 Events mit dem Internet Explorer

  15.2.1 Neue Ereignisse

  15.2.2 Ereignisse als Objekteigenschaften

  15.2.3 Spezielle Skripten

  15.2.4 Ereignisse abfangen

  15.2.5 Bubbling

  15.2.6 Das Event-Objekt

15.3 Events mit beiden Browsern

  15.3.1 Browser-Unabhängigkeit

  15.3.2 Benutzereingaben

15.4 Event-Handling im Netscape 6

15.5 Fragen & Aufgaben

16 DHTML I: Netscape

16.1 Grundlagen

  16.1.1 Begriffsbestimmung

  16.1.2 Cascading Style Sheets

  16.1.3 Positionierung von Elementen

  16.1.4 JavaScript Style Sheets

  16.1.5 Layer

16.2 Beispiele

  16.2.1 Animiertes Logo

  16.2.2 Drag&Drop

  16.2.3 Sichtbar und unsichtbar

  16.2.4 Neuer Mauszeiger

  16.2.5 Permanentes Werbebanner

16.3 Fragen & Aufgaben

17 DHTML II: Internet Explorer

17.1 Grundlagen

  17.1.1 HTML-Tags

  17.1.2 Objektzugriff

17.2 Beispiele

  17.2.1 Animiertes Logo

  17.2.2 Drag&Drop

  17.2.3 Sichtbar und unsichtbar

  17.2.4 Neuer Mauszeiger

  17.2.5 Permanentes Werbebanner

17.3 Fragen & Aufgaben

18 DHTML III: Netscape 6

18.1 Grundlagen

  18.1.1 HTML-Tags

  18.1.2 Objektzugriff

18.2 Beispiele

  18.2.1 Animiertes Logo

  18.2.2 Sichtbar und unsichtbar

  18.2.3 Neuer Mauszeiger

  18.2.4 Permanentes Werbebanner

18.3 Fragen & Aufgaben

19 DHTML IV: Für alle Browser

19.1 Animiertes Logo

19.2 Drag&Drop

19.3 Sichtbar und unsichtbar

19.4 Neuer Mauszeiger

19.5 Permanentes Werbebanner

19.6 Fragen & Aufgaben

20 Java

20.1 Allgemeines

  20.1.1 Wie funktioniert Java?

  20.1.2 Kurzeinführung in Java

20.2 Java und das WWW

  20.2.1 Ein Beispiel-Applet

  20.2.2 HTML-Integration

20.3 Java ohne Applet

  20.3.1 Exemplarische Java-Objekte

  20.3.2 Blackjack

  20.3.3 Karten initialisieren

  20.3.4 Karten mischen

20.4 Fragen & Aufgaben

21 Signierte Skripten

21.1 Zusätzliche Rechte

  21.1.1 Allgemeines

  21.1.2 Surfüberwachung

  21.1.3 Besondere Fenster

21.2 Signieren

  21.2.1 Zigbert

  21.2.2 HTML-Code anpassen

22 DOM

22.1 DOM-Baum

22.2 Navigation im Baum

22.3 Den Baum modifizieren

22.4 Fragen & Aufgaben

23 Fehler

23.1 Fehler abfangen

  23.1.1 Keine Fehlermeldung

  23.1.2 Besondere Fehlermeldung

  23.1.3 Ausblick: Fehlermeldungen verschicken

23.2 JavaScript Debugger

  23.2.1 Wo ist der Fehler?

  23.2.2 Breakpoints

  23.2.3 Watches

  23.2.4 Einzelne Werte anzeigen

  23.2.5 Schrittweise Programmausführung

23.3 Fragen

24 Lösungen

25 Referenz

25.1 Das Anchor-Objekt

  25.1.1 Allgemeines

  25.1.2 Eigenschaften

25.2 Das Array-Objekt

  25.2.1 Allgemeines

  25.2.2 Methoden

  25.2.3 Eigenschaften

25.3 Das Button-Objekt

  25.3.1 Allgemeines

  25.3.2 Event-Handler

  25.3.3 Methoden

  25.3.4 Eigenschaften

25.4 Das Checkbox-Objekt

  25.4.1 Allgemeines

  25.4.2 Event-Handler

  25.4.3 Methoden

  25.4.4 Eigenschaften

25.5 Das Date-Objekt

  25.5.1 Allgemeines

  25.5.2 Methoden

25.6 Das document-Objekt

  25.6.1 Allgemeines

  25.6.2 Event-Handler

  25.6.3 Methoden

  25.6.4 Eigenschaften

25.7 Das event-Objekt

  25.7.1 Netscape-Eigenschaften

  25.7.2 Internet Explorer-Eigenschaften

25.8 Das FileUpload-Objekt

  25.8.1 Allgemeines

  25.8.2 Event-Handler

  25.8.3 Methoden

  25.8.4 Eigenschaften

25.9 Das Form-Objekt

  25.9.1 Allgemeines

  25.9.2 Event-Handler

  25.9.3 Methoden

  25.9.4 Eigenschaften

25.10 Das Frame-Objekt

25.11 Das Hidden-Objekt

  25.11.1 Allgemeines

  25.11.2 Eigenschaften

25.12 Das History-Objekt

  25.12.1 Allgemeines

  25.12.2 Methoden

  25.12.3 Eigenschaften

25.13 Das Image-Objekt

  25.13.1 Allgemeines

  25.13.2 Event-Handler

  25.13.3 Eigenschaften

25.14 Das Layer-Objekt

  25.14.1 Allgemeines

  25.14.2 Event-Handler

  25.14.3 Methoden

  25.14.4 Eigenschaften

25.15 Das Link-Objekt

  25.15.1 Allgemeines

  25.15.2 Event-Handler

  25.15.3 Eigenschaften

25.16 Das Location-Objekt

  25.16.1 Methoden

  25.16.2 Eigenschaften

25.17 Das Math-Objekt

  25.17.1 Methoden

  25.17.2 Eigenschaften

25.18 Das MimeType-Objekt

  25.18.1 Eigenschaften

25.19 Das Navigator-Objekt

  25.19.1 Methoden

  25.19.2 Eigenschaften

25.20 Das Number-Objekt

  25.20.1 Allgemeines

  25.20.2 Eigenschaften

25.21 Das Object-Objekt

  25.21.1 Allgemeines

  25.21.2 Methoden

  25.21.3 Eigenschaften

25.22 Das Option-Objekt

  25.22.1 Allgemeines

  25.22.2 Eigenschaften

25.23 Das Password-Objekt

  25.23.1 Allgemeines

  25.23.2 Event-Handler

  25.23.3 Methoden

  25.23.4 Eigenschaften

25.24 Das Plugin-Objekt

  25.24.1 Eigenschaften

25.25 Das Radio-Objekt

  25.25.1 Allgemeines

  25.25.2 Event-Handler

  25.25.3 Methoden

  25.25.4 Eigenschaften

25.26 Das RegExp-Objekt

  25.26.1 Allgemeines

  25.26.2 Eigenschaften

  25.26.3 Methoden

25.27 Das Reset-Objekt

  25.27.1 Allgemeines

  25.27.2 Event-Handler

  25.27.3 Methoden

  25.27.4 Eigenschaften

25.28 Das Screen-Objekt

  25.28.1 Eigenschaften

25.29 Das Select-Objekt

  25.29.1 Allgemeines

  25.29.2 Event-Handler

  25.29.3 Methoden

  25.29.4 Eigenschaften

25.30 Das String-Objekt

  25.30.1 Allgemeines

  25.30.2 Methoden

  25.30.3 Eigenschaften

25.31 Das Submit-Objekt

  25.31.1 Allgemeines

  25.31.2 Event-Handler

  25.31.3 Methoden

  25.31.4 Eigenschaften

25.32 Das Text-Objekt

  25.32.1 Allgemeines

  25.32.2 Event-Handler

  25.32.3 Methoden

  25.32.4 Eigenschaften

25.33 Das Textarea-Objekt

  25.33.1 Allgemeines

  25.33.2 Event-Handler

  25.33.3 Methoden

  25.33.4 Eigenschaften

25.34 Das Window-Objekt

  25.34.1 Allgemeines

  25.34.2 Event-Handler

  25.34.3 Methoden

  25.34.4 Eigenschaften

25.35 Top-Level-Eigenschaften und -Methoden

  25.35.1 Methoden

  25.35.2 Eigenschaften

Index

	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 1 Einleitung
			1.1 Geschichte von JavaScript
			1.2 Voraussetzungen
			1.3 Danksagung
			1.4 Vorwort zur 2. Auflage
			1.5 Vorwort zur 3. Auflage
			1.6 Die Icons in diesem Buch

Kapitel 1 Einleitung

So können Angreifer beispielsweise Nutzerkennung mit Passwörtern oder auch lokal gespeicherte Daten von privaten und kommerziellen Internetnutzern ausspionieren. [...] Das BSI empfiehlt deswegen den Betreibern von WWW-Servern dringend, vollständig auf JavaScript zu verzichten oder zumindest für ihre sicherheitsbewussten Kunden Alternativangebote bereitzustellen, die ohne aktive Inhalte dargestellt werden können.

Pressemitteilung des Bundesamtes für Sicherheit in der Informationstechnik, BSI (http://www.bsi.de/aktuell/presse/java99.htm)

Vorsicht ist geboten, wenn Unternehmen für ihre Web-Seiten das Gestaltungssystem JavaScript verwenden. Dahinter verbergen sich kleine Programme, die sich unbemerkt auf dem Kunden-PC einnisten und ihn angreifbar für fremde Zugriffe machen.

BILD am SONNTAG, 21. Mai 2000

JavaScript ist in aller Munde – sowohl im positiven als auch im negativen Sinne. Immer wieder geistern Horrormeldungen wie obige Empfehlung des BSI oder der Unfug aus der BamS durch die Presse. Grund dafür ist, dass den Browser-Herstellern – in diesem Falle vor allem Netscape (Netscape Navigator) und Microsoft (Microsoft Internet Explorer) immer wieder Fehler bei der Programmierung Ihrer Browser unterlaufen (bei Interesse: http://www.nat.bg/~joro/). Zwar werden eiligst Bugfixes zur Verfügung gestellt, aber der (Image-)Schaden ist schon eingetreten. Die andere Seite der Geschichte ist jedoch, dass keine Fälle bekannt sind, wonach Sicherheitslecks zu Schäden geführt haben. So hat die obige Pressemitteilung des BSI in der Fachpresse zu scharfer Kritik geführt, teilweise war von überzogener Panikmache die Rede. Die inhaltliche Qualität der Aussage aus der BamS entbehrt jeden Kommentars.

Ohne die Diskussion allzu sehr vertiefen zu wollen: Mit JavaScript kann man die eher beschränkten Möglichkeiten von HTML erweitern. Es handelt sich hierbei um eine clientseitige Programmiersprache, das heißt, alles läuft im Browser ab, und man muss keine besonderen Server-Voraussetzungen erfüllen. Letzterer Punkt ist (noch) ein großer Nachteil von serverseitigen Sprachen wie ASP, Perl, PHP und Konsorten, denn viele Hoster (und vor allem die günstigen Hoster) gestatten keine serverseitige Programmierung. Mit JavaScript ist dies jedoch alles kein Problem.

In den nun folgenden Kapiteln finden Sie eine komplette Einführung in die Sprache, stets anhand von praxisnahen Beispielen illustriert. Ich habe versucht, mich bei den Beispielen auf das Wesentliche – nämlich die JavaScript-Programmierung – zu konzentrieren, sodass die Beispiele grafisch bei weitem nicht ausgefeilt sind, aber sie erfüllen die gestellten Aufgaben.

Jedes Kapitel wird mit Fragen und Übungen abgeschlossen, sodass Sie das Erlernte gleich in die Tat umsetzen können. Das letzte Kapitel schließlich ist eine komplette Sprachreferenz, die Ihnen auch nach der Lektüre des Buches immer wieder als Nachschlagequelle dienen wird.

MyGalileo

Des Weiteren möchte ich noch auf den Online-Dienst MyGalileo verweisen, der im World Wide Web unter http://www.galileo-press.de zu erreichen ist. Registrieren Sie dieses Buch, und Sie erhalten Zugriff auf die Webseiten, die dieses Buch begleiten. Nach und nach werden dort Inhalte eingefügt, und Sie können mit mir in Kontakt treten. Nutzen Sie diese Gelegenheit, jede Art von konstruktiver Kritik ist willkommen. Wenn Sie einen Fehler finden, teilen Sie mir diesen bitte mit, damit er in einer weiteren Auflage dieses Buches nicht mehr auftritt. Sie helfen damit auch anderen Lesern In MyGalileo werden Sie auch eine aktualisierte Fehlerliste für dieses Buch finden.

1.1 Geschichte von JavaScript

Gegen Ende des Jahres 1995 stellte die Firma Netscape die neueste Version Ihres Internet-Browsers vor. Der Versionssprung von 1.1 auf 2.0 war berechtigt, da solch revolutionäre Dinge wie etwa die Unterstützung von Frames als neues Feature hinzugekommen waren. Unter anderem war auch eine Sprache namens LiveScript eingebaut, mit der man auf HTML-Seiten Einfluss nehmen konnte. Die Syntax dieser Sprache lehnte sich an Java an, und wohl aus marketingtechnischen Gründen wurde die Programmiersprache schließlich in JavaScript umbenannt.

Schon bald begann der Siegeszug dieser Programmiersprache. Zwar war die Implementierung im Browser eher mangelhaft (in Netscape-Version 2.0 konnte man JavaScript nicht einmal deaktivieren, was zu einem bösen Sicherheitsproblem werden sollte), aber mit der Beta-Version des Netscape Navigator 3 wurde die JavaScript-Version 1.1 vorgestellt, die deutlich mehr Möglichkeiten bot. Microsoft wollte nun auch auf den Zug aufspringen und kündigte an, in Version 3 des Internet Explorers auch Skriptunterstützung anzubieten. Aus lizenzrechtlichen Gründen wurde die Sprache JScript getauft, von der Syntax her war sie aber praktisch identisch mit JavaScript.

ECMAScript

Seitdem läuft das übliche Wettrennen zwischen Netscape und Microsoft. Während der Internet Explorer 3 praktisch nur JavaScript 1.0 unterstützte, kann der Internet Explorer 4 schon JavaScript 1.1 – und einige Features aus dem Sprachschatz von JavaScript 1.2, das mit dem parallel zum »IE4« erscheinenden Netscape Navigator 4 eingeführt wurde. Seit dem Netscape Navigator 4.06 gibt es JavaScript Version 1.3, die zwar nur rudimentäre Verbesserungen anbietet, sich aber an dem ECMA-262 Standard, ECMAScript, orientiert. Netscape hat erkannt, dass man auf Standards setzen muss, und gleichzeitig behauptet, dass der Netscape Navigator 4.06 der Browser ist, der der Spezifikation von ECMAScript am nächsten kommt. Microsoft wiederum hat mit dem Internet Explorer 5 den Rückstand weiter verkleinert, setzt aber inzwischen eher auf andere Standards, wie DOM (Document Object Model). Unter dem Codenamen Mozilla wurde mittlerweile die nächste Netscape-Version als Open Source entwickelt, sprich: Der Sourcecode lag offen, und jeder konnte an der neuen Version mitentwickeln. Nichtsdestotrotz wurde der Löwenanteil der Arbeit von Netscape-Angestellten geleistet, das »Linux-Wunder« funktioniert nicht überall!

Im Spätherbst 2000 begannen sich die Ereignisse zu überschlagen. Unter dem Druck des Internet Explorer 5.5, sowie mit einem als Teil des neuen Microsoft-Betriebssystems Whistlers angebotenen Internet Explorer 6 wurde schnell der aktuelle Zwischenstand des Open-Source-Projekts erreicht, eine Installationsroutine dazugebastelt und das Ganze als Netscape 6 als Download angeboten (bezeichnenderweise ist eine fast identische Version auf der Mozilla-Website als Version 0.6 als Download zu haben). Dieser Schritt stieß in der Fachwelt auf große Kritik, denn die Version war noch weit davon entfernt, im Produktiveinsatz verwendet zu werden. Und, aus Sicht der Webdesigner viel schlimmer, die neue Version erwies sich in Sachen JavaScript als nicht abwärts kompatibel, wenn es um »DHTML« ging. So mussten (und müssen immer noch) eine Reihe von Skripten umprogrammiert werden. Doch keine Sorge, denn um eines vorweg zu nehmen, in diesem Buch gehen wir ausführlich auf den neuesten Netscape ein. Die neue Version unterstützt übrigens JavaScript 1.5, das aber nur unwesentliche Änderungen zu den Vorgängerversionen aufweist (es wird eine aktuellere Version von ECMAScript unterstützt).

Die Crux bei der Programmierung von Webseiten besteht darin, dass die beiden großen Browserhersteller immer wieder versucht haben, sich dadurch zu übertrumpfen, dass sie immer neue Features in ihre Browser einbauten. Das ist innerhalb des eigenen Mikrokosmos eine gute Sache, aber wenn die Technik inkompatibel zur Konkurrenz ist, schaut etwa die Hälfte der Websurfer (die nämlich den jeweils anderen Browser benutzen) bildlich gesprochen in die Röhre. Keine Firma kann es sich leisten, ein Web-Angebot nur für die halbe Zielgruppe zu erstellen.

Cross Browser

In diesem Buch geht es nicht nur um die neuesten Effekte und Kniffe. Vielmehr geht es darum, wie Sie Ihre Zielgruppe erweitern können, indem JavaScript-Programme so gestaltet werden, dass sie von den Benutzern beider Browser, und auch von den Benutzern älterer Versionen, verwendet werden können. Bei bekannten Fehlern in der Implementierung einzelner Browser werden – so weit möglich – Workarounds angeboten. Ziel für Sie sollte es nicht nur sein, eine technisch eindrucksvolle Seite zu erstellen, sondern auch Ihre Zielgruppe zu erweitern, indem Sie ältere Browser nicht ausschließen oder zumindest vor Fehlermeldungen bewahren.

Sonstige Browser

Es ist ja nicht so, dass nur der Netscape Navigator und der Internet Explorer JavaScript unterstützen. Die Nummer 3 im Browsermarkt, der Opera-Browser, unterstützt JavaScript-Version 1.3, und das nicht einmal schlecht. Auch der in StarOffice integrierte Webbrowser sowie die Version 3 von Suns HotJava Browser sind javascriptfähig. Diese haben jedoch einen so kleinen Marktanteil, dass sie im Referenzteil nicht extra berücksichtigt werden. Mit umsichtiger Programmierung lassen sich aber auch hier Fehler vermeiden.

1.2 Voraussetzungen

HTML-Kenntnisse vorausgesetzt

Wenn Sie dieses Buch durcharbeiten wollen, sollten Sie zumindest Kenntnisse in HTML vorweisen können – denn dieses Buch sollte nicht künstlich durch einen zusätzlichen HTML-Teil aufgebläht werden. Ebenfalls sollten Sie sicher mit Ihrem Betriebssystem umgehen können und beispielsweise Editoren starten und Dateien speichern können.

Editoren

Apropos Editoren: Im Gegensatz zu HTML gibt es bei der JavaScript-Programmierung keinen großen Markt für Editoren. Hier geschieht das meiste immer noch textbasiert. Die einfachen Texteditoren, die beim Betriebssystem mitgeliefert werden (beispielsweise Notepad oder SimpleEdit), reichen sogar schon aus; wer mehr will, sollte einen der folgenden Editoren versuchen (die sind aber Shareware und damit nach Ablauf einer Testperiode kostenpflichtig), in der Reihenfolge meiner Präferenzen:

	Ultraedit (http://www.ultraedit.com) – Sehr leistungsfähiger Editor inklusive Syntax-Highlighting (Windows).
	Programmer’s File Editor (http://www.lancs.ac.uk/people/cpaap/pfe/) – Die Entwicklung wurde mittlerweile eingestellt, aber unter der genannten Adresse ist dieser Editor immer noch erhältlich (Windows).
	NoteTab (http://www.notetab.ch) – Mehrfach ausgezeichneter Klassiker unter den Texteditoren, auch in kostenfreier Light-Variante erhältlich (Windows).
	BBEdit (http://www.bbedit.com) – der Macintosh-Klassiker, auch in einer Light-Version erhältlich.

Kompatibilität

Außerdem sollten Sie möglichst viele Browser installieren. Sie sollten nämlich Ihre JavaScript-Programme auf möglichst vielen Zielplattformen testen, um sicherzustellen, dass die Programme eben nicht nur bei Ihnen laufen. Wenn Sie den Internet Explorer 5 oder 5.5 über den Internet Explorer 4 installieren, geben Sie bei der Installation unbedingt an, dass die alte Version (im sogenannten Kompatibilitätsmodus) erhalten bleibt. Der Internet Explorer 3 lässt sich in der 32-Bit-Variante nicht parallel installieren, aber wenn Sie ein wenig beherzt sind, verwenden Sie die 16-Bit-Variante, das funktioniert (angeblich; alle Installationen sind Ihr Risiko). Beim Netscape Navigator ist alles ein wenig einfacher. Die Versionen 6, 4.x und 3 lassen sich problemlos parallel installieren. Auf mindestens einem Rechner sollte auch immer noch eine Version 2 laufen, vor allem wenn Sie sehr viele Besucher haben. Ebenfalls sollten Sie den Opera-Browser installieren (http://www.opera.com), da dieser auch eine gute JavaScript-Unterstützung hat.

Netscape 6

Den aktuellen Entwicklungsstand der nächsten Netscape-Version können Sie unter http://www.mozilla.org begutachten. Die offizielle Release unter http://home.netscape.com basiert auf der Version unter Mozilla, hat jedoch noch einige Bugs mehr. Mit der Fertigstellung einer neuen, stabileren Version kann es noch ein Weilchen dauern, aber sobald Netscape 6 einen akzeptablen Status erreicht hat, werden mehr Benutzer die neue Version einsetzen, und darauf sollten Ihre Seiten vorbereitet sein.

Während der Entwicklung Ihrer Programme sollten Sie unbedingt den Netscape Navigator 4.x verwenden. Diese Empfehlung ist kein Glaube oder Fanatismus, sondern beruht auf der Tatsache, dass die Fehlermeldungen des Netscape Navigator viel aussagekräftiger sind als die des Internet Explorers. Läuft ein Programm einmal im Netscape einigermaßen zuverlässig, dann können Sie natürlich sofort dazu übergehen, es im Internet Explorer zu testen.

	Seit Version 4.06 führt ein JavaScript-Fehler beim Netscape Navigator nicht mehr zu einem extra Warnfenster; statt dessen werden alle Fehlermeldungen in der JavaScript-Konsole angezeigt. Diese wird sichtbar, wenn Sie in der Adresszeile des Browsers javascript: eintippen (inklusive dem Doppelpunkt) und auf (¢) drücken. Im Netscape 6 geht das mit dem Menübefehl Task/Tools/JavaScript Console.

Bleibt mir nur noch, Ihnen Spaß bei der Lektüre dieses Buches zu wünschen und viel Erfolg und Kreativität beim Experimentieren mit JavaScript. Und noch einmal die Bitte: Geben Sie mir Rückmeldung über MyGalileo, damit ich Ihre Anregungen für eine Neuauflage in Erwägung ziehen kann. Da ich sehr viele E-Mails bekomme, kann es mit einer Antwort etwas dauern, also bitte nicht ungeduldig werden. Fragen zu Buchthemen beantworte ich gerne, sofern möglich; bei allgemeinen JavaScript-Fragen sind Sie in den folgenden Newsgroups wohl besser aufgehoben und bekommen auch schneller eine Antwort:

	de.comp.lang.javascript
	comp.lang.javascript

Wenn Ihr Provider keine Newsgroup-Anbindung unterstützt, sollten Sie ihn wechseln oder sich ein kostenloses Konto bei http://www.deja.com/usenet oder http://netnews.web.de einrichten lassen.

Vielleicht finden Sie eine Antwort auf Ihre Frage aber auch in der FAQ der Newsgroup de.comp.lang.javascript, die Sie auf der Buch-CD finden. An dieser Stelle herzlichen Dank für die Erlaubnis, die FAQ beilegen zu dürfen. Lesen Sie die FAQ unbedingt durch, bevor Sie eine Frage in der Newsgroup stellen!

1.3 Danksagung

Manche Menschen hassen den Danksagungsteil in einem Buch, ich dagegen lese ihn immer als Erstes. Hier die Namen einiger Leute, die mich vor oder während der Bucherstellung in irgendeiner Art und Weise beeinflusst oder motiviert haben, oder mir anderweitig behilflich waren.

Zunächst einmal gilt der Dank meiner Lektorin Judith Stevens und ihrem Team bei Galileo, die mich fabelhaft betreut haben und stets ein offenes Ohr für meine Wünsche und Anregungen hatten. Herzlichen Dank dafür. Rudolf Krahm ist übrigens »Schuld« daran, dass ich überhaupt an dieses Projekt gekommen bin.

Die sprachlichen Korrekturen wurden von Friederike Daenecke ausgeführt. Sie hat dadurch die sprachliche Qualität dieses Buches deutlich gesteigert.

Das schöne Cover wurde von Barbara Thoben entworfen, die Herstellung lag in den Händen von Petra Strauch, in Vertretung Claudia Lucht.

Für die USA-Erlebnisse habe ich folgenden Leuten zu danken: den Verkehrspolizisten von Colby, Tigger, Jerry S. Für China waren das Thommi, Reinhold, Klaus, Axel, Wei Dan und Qu Jian Ben. Zuhause danke ich neben meiner Familie meinen Freunden Christian, Marianne, Markus und Thorsten; den PP-Kollegen, allen Caipirinha-Anhängern sowie den Sneak-Preview-Fans. Vielen Dank für die »Sabotage« (= Ablenkung von) meiner Arbeit!

Besonders danken möchte ich außerdem noch meinen Freunden Tobias und Matthias, die immer hinter mir stehen und ohne deren Unterstützung ich das Buch wohl nicht hätte schreiben können. Tobias hat übrigens alle Vektorgrafiken für dieses Buch erstellt.

In fachlicher Hinsicht habe ich vieles von dem, was ich weiß, durch das Diskutieren in Mailingslisten und Newsgroups gelernt. Exemplarisch für viele andere möchte ich hier IT und QA nennen, die durch ihr Wissen und ihre Kreativität schon vielen JavaScript-Programmierern geholfen haben.

Last but not least danke ich Thomas Maier, der mir vor ein paar Jahren die Freude am Schreiben wiedergegeben hat, sowie Cecily, die immer an dieses Projekt geglaubt hat.

Christian Wenz, im November 1999

1.4 Vorwort zur 2. Auflage

Nach der erfreulichen Aufnahme der Erstauflage wurde schon bald eine Neuauflage nötig. Da in der Zwischenzeit sowohl Microsoft als auch Netscape neue Beta-Versionen herausgebracht haben, haben wir uns dafür entschieden, dies zu berücksichtigen. Die Neuerungen in Sachen JavaScript sind jedoch relativ überschaubar, sodass wir sie an passender Stelle eingebaut haben, statt sie in eigenen Kapiteln zu sammeln. Das hat für Sie den Vorteil, dass Sie die Neuerungen unter den jeweiligen thematischen Überbegriffen finden, im richtigen Umfeld sozusagen. Und, ganz nebenbei, halten Sie eines der ersten JavaScript-Bücher weltweit in Händen, das auf die neuen Features eingeht (ich sage das natürlich nicht ohne Stolz)!

Ebenfalls wurden alle Kapitel einer Überarbeitung unterzogen. Dabei wurden nicht nur Hinweise und Anmerkungen aus den vielen Leserzuschriften berücksichtigt (für die ich mich im Übrigen herzlich bedanke), sondern auch die Kapitel an der einen oder anderen Stelle erweitert. Insbesondere die drei DHTML-Kapitel wurden um weitere Beispiele ergänzt, was bei den Möglichkeiten der Browser ab Versionsnummer 4 auch nicht weiter schwierig war. Natürlich wurden auch einige Fehler der Erstauflage beseitigt, so weit bekannt. Sollten Sie dennoch auf etwas Falsches stoßen – wenden Sie sich bitte über MyGalileo an mich!

Diese Auflage enthält darüber hinaus noch ein neues Kapitel, in dem es um das Abfangen und Auffinden von Fehlern geht. Ich hoffe, Sie können von den dort gezeigten Techniken und Tipps bei Ihrer (JavaScript-)Programmierarbeit profitieren. In diesem Kapitel finden Sie des Weiteren eine Verbindung von serverseitiger Programmierung und JavaScript. Damit lassen sich tolle Dinge anstellen! Schreiben Sie mir doch bitte – ich bin gespannt auf Ihre Reaktion!

Auch dieses Mal gilt mein ganz besonderer Dank meinen »Golden Girls« (nicht bezogen aufs Alter) Judith Stevens und Friederike Daenecke, ohne deren Arbeit und Unterstützung diesem Buch einiges fehlen würde. Alle Fehler oder Ungenauigkeiten sind mir anzurechnen.

Den restlichen Personenkreis, der es mir erst ermöglicht hat, dieses Buch zu schreiben, entnehmen Sie bitte größtenteils Abschnitt 1.3. Vielen Dank – you know who you are.

Christian Wenz, im Juli 2000

1.5 Vorwort zur 3. Auflage

Die hastige Veröffentlichung von Netscape 6 im Spätherbst 2000 stellt viele Webdesigner vor Probleme. Alte Skripte laufen nicht mehr, und trotz aller negativen Presseberichte tauchen in den Logfiles großer und kleiner Websites der Netscape 6 auf. Grund genug, eine neue Auflage des Buches zu erstellen. Und die umfangreichsten Neuerungen in diesem Buch gibt es auch im Zusammenhang mit dem neuen Browser. Speziell für den Netscape 6 gibt es ein neues DHTML-Kapitel. Sie erfahren, wie Sie dem Netscape 6 dieselben Tricks beibringen, die Sie zuvor dem Netscape 4.x und dem Internet Explorer beigebracht haben. So weit gerüstet, finden Sie im letzten (nämlich vierten) DHTML-Kapitel Techniken, wirklich plattformunabhängiges DHTML zu programmieren.

Des Weiteren haben wir auch dieses Mal wieder versucht, die zahlreichen Leserzuschriften auszuwerten und möglichst viele Verbesserungsvorschläge einzubringen. Es soll hierbei nicht verschwiegen werden, dass auch einige Fehler ausgebessert worden sind. An dieser Stelle nochmals herzlichen Dank für alle Rückmeldungen, sei es direkt an den Verlag oder über MyGalileo.

Die restlichen Änderungen sind eher unter der Motorhaube angesiedelt. Neben kleineren und größeren Korrekturen und Erweiterungen fällt wohl am Deutlichsten die Orthographie ins Auge: Ab dieser Auflage wurde auf die neue Rechtschreibung umgestellt. Es soll hier keine Diskussion überdieses brisante Thema entfacht werden, aber es ist zu hoffen, daß/dass Ihnen das Buch so oder so gefällt.

Wie sieht die Zukunft aus? In etwa einem Jahr wird sich zeigen, ob und wie sich der Netscape 6 durchgesetzt hat, und wie der Browsermarkt im Allgemeinen aussieht. Wenn es so weit ist, wird dieses Buch einer erneuten allgemeinen Prüfung unterzogen werden müssen. In wieweit sind alte Browserversionen noch relevant? In wieweit kann man als Webdesigner auf die erweiterten Funktionalitäten der allerneuesten Browserversionen setzen, in wieweit muss man abwärts kompatibel bleiben? Die Situation in der Praxis bedingt die Ausrichtung dieses Buchs, und hoffentlich auch umgekehrt. Die Aktualität nimmt aber nicht den Hauptteil dieses Buches ein. Sie erhalten eine allgemein gültige Einführung in die Sprache, die wichtigsten Kniffe und Tricks, die Sie in der täglichen Programmierarbeit mit JavaScript benötigen, sowie den einen oder anderen Blick über den Tellerrand. Wir hoffen, auch in dieser Auflage wieder eine ausgewogene Mischung aus Grundwissen, fortgeschrittenen Techniken und State-of-the-art-Technologien bieten zu können.

Bei all den Bestrebungen, dauerhafte Aktualität zu bieten, und dementsprechend kurze Produktionszyklen einzuhalten, kann es natürlich immer mal wieder passieren, dass ein Fehler unterläuft. Bitte behalten Sie hier Ihren Ärger nicht für sich, sondern wenden Sie sich an das Lektorat (judith.stevens@galileo-press.de), damit wir das Versehen in einer nächsten Auflage ausmerzen können. Zum Abschluss noch der obligatorische Hinweis: Aktuelle Korrekturen, Erweiterungen und vieles mehr zu diesem Buch und zum Verlag finden Sie unter MyGalileo, dem Online-Service von Galileo Press (http://www.galileo-press.de). Es lohnt sich, häufig dort vorbeizuschauen!

Christian Wenz, im Februar 2001

1.6 Die Icons in diesem Buch

	Wichtige Hinweise und Tipps finden Sie in Abschnitten, die mit diesem Symbol gekennzeichnet sind.
	Achtung, Abschnitte mit diesem Symbol sprechen eine Warnung aus!
	Dieses Icon markiert Abschnitte, in denen Sie auf Besonderheiten der unterschiedlichen Browserversionen und -typen aufmerksam gemacht werden. Auch die Eigenschaften der verschiedenen JavaScript-Versionen werden an diesen Stellen beschrieben.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 2 Vorbereitung
			2.1 Verwendung von <SCRIPT>
			2.2 JavaScript-Links
			2.3 Event-Handler
			2.4 JavaScript-Entities

Kapitel 2 Vorbereitung

Take three months to prepare your machines and

three months to complete your siege engineering.

– Sun Tzu, The Art Of War

In diesem Kapitel erfahren Sie, wie JavaScript-Code in HTML-Dokumente eingebunden wird. Besondere Beachtung verdienen hierbei die Unterschiede zwischen den einzelnen Browsern.

JavaScript-Kommandos können an mehreren Stellen einer HTML-Datei untergebracht werden:

	Zwischen den Tags <SCRIPT> und </SCRIPT>
	In einer externen Datei
	In Form eines HTML-Links
	Als Parameter von HTML-Tags

In den folgenden Abschnitten werden die einzelnen Möglichkeiten der Reihe nach vorgestellt und beleuchtet.

Als Beispiel hierzu dient die Anweisung document.write("The weather means the seasons"), welche den Text "The weather means the seasons" ausgibt. Warum dieser Befehl so funktioniert, erfahren Sie in den nächsten Kapiteln; fürs erste müssen Sie mir einfach vertrauen.

2.1 Verwendung von <SCRIPT>

Die naheliegenste Methode, JavaScript-Befehle auszuführen, besteht darin, den1  <SCRIPT>-Tag zu verwenden. Folgender Code sorgt dafür, dass »The weather means the seasons« ausgegeben wird:

<SCRIPT>
document.write("The weather means the seasons")
</SCRIPT>

Befehle werden in JavaScript untereinander – einer pro Zeile – dargestellt. Wenn Sie mehrere Kommandos in einer Zeile unterbringen wollen, müssen Sie die Anweisungen durch ein Semikolon voneinander trennen. Im Gegensatz zu anderen Programmiersprachen (beispielsweise Java) muss aber keineswegs jedes Kommando mit einem Strichpunkt enden.

In der ersten Version der JavaScript-Sprachspezifikation war das Semikolon am Ende jeder Anweisung strikt vorgeschrieben. Inzwischen wurde aber davon Abstand genommen, und jeder JavaScript-Programmierer hat seinen eigenen Stil. Ich verzichte auf optionale Strichpunkte, es ist Ihnen aber natürlich freigestellt, sich einen anderen Stil anzueignen – insbesondere, wenn Sie bereits Erfahrungen in einer Programmiersprache gesammelt haben, bei der die Strichpunkte nicht optional sind (z. B. Java).

Die beiden folgenden Anweisungen sind also äquivalent. Einmal stehen die beiden Befehle in verschiedenen Zeilen, einmal in einer Zeile.

<SCRIPT>
document.write("The weather ")
document.write("means the seasons")
</SCRIPT>

und

<SCRIPT>
document.write("The weather ");
document.write("means the seasons")
</SCRIPT>

JavaScript-Code wird hierbei vom JavaScript-Interpreter des verwendeten Browsers ausgeführt. Betrachten Sie zum Beispiel folgendes HTML-Dokument:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT>
document.write("The weather means the seasons")
</SCRIPT>
</BODY>
</HTML>

Wenn es vom Browser interpretiert worden ist, und dieser Browser JavaScript unterstützt, verhält es sich so wie folgendes HTML-Dokument:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
The weather means the seasons
</BODY>
</HTML>

Nehmen es Sie mir nicht übel, wenn die ersten Beispiele in diesem Kapitel nicht unbedingt die breite Funktionspalette von JavaScript demonstrieren.

2.1.1 Das LANGUAGE-Attribut

Das obige Beispiel ist streng genommen etwas unsauber. Der <SCRIPT>-Tag eignet sich auch für andere Programmiersprachen, die in HTML-Dokumente eingebettet werden können, beispielsweise Visual Basic Script (VBScript) oder JScript. Dazu dient das Attribut LANGUAGE des <SCRIPT>-Tags. Ist es nicht gesetzt – wie im obigen Beispiel – so wird angenommen, dass die zwischen den Tags stehenden Kommandos in JavaScript verfasst wurden (deswegen funktioniert obiges Beispiel auch). Aber um auf Nummer sicher zu gehen – es könnte ja sein, dass eine neue Version des Microsoft Internet Explorer als Standardsprache VBScript annimmt – schreiben wir:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
document.write("The weather means the seasons")
</SCRIPT>
</BODY>
</HTML>

	Wie Sie im vorherigen Kapitel erfahren haben, gibt es mehrere Versionen von JavaScript. Sie können im LANGUAGE-Attribut auch explizit eine der Versionen angeben. Der folgende Code wird nur von Browsern ausgeführt, die JavaScript Version 1.1 unterstützen (das sind insbesondere der Netscape Navigator ab Version 3 und der Microsoft Internet Explorer ab Version 4):

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript1.1">
document.write("The weather means the seasons")
</SCRIPT>
</BODY>
</HTML>

Ältere Browser, beispielsweise der Internet Explorer 3, ignorieren den JavaScript-Befehl und geben nichts aus.

Zur Zeit der Drucklegung (Juli 2000) sind die in Tabelle 2.1 aufgeführten Parameter gültig.

Tabelle 2.1  Die gültigen Parameter für <SCRIPT LANGUAGE="…">

Parameter	Bedeutung
JavaScript	Jeder Browser, der JavaScript unterstützt
JavaScript 1.1	Alle Browser, die mindestens JavaScript Version 1.1 unterstützen (ab NN3, IE4)
JavaScript 1.2	Alle Browser, die mindestens JavaScript-Version 1.2 unterstützen (ab NN4, IE5)
JavaScript 1.3	Alle Browser, die mindestens JavaScript-Version 1.3 unterstützen (ab Netscape Navigator 4.06, IE5)
JavaScript 1.4	Netscape 6
JavaScript 1.5	Netscape 6

Mit der folgenden HTML-Seite kann man überprüfen, welche JavaScript-Versionen der jeweilige Browser unterstützt:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
document.write("Der Browser unterstützt JavaScript<HR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1">
document.write("Der Browser unterstützt JavaScript v1.1<HR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.2">
document.write("Der Browser unterstützt JavaScript v1.2<HR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.3">
document.write("Der Browser unterstützt JavaScript v1.3<HR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.4">
document.write("Der Browser unterstützt JavaScript v1.4<HR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.5">
document.write("Der Browser unterstützt JavaScript v1.5<HR>")
</SCRIPT>
</BODY>
</HTML>

In Abbildung 2.1 sehen Sie beispielsweise, was der Netscape Navigator 4.75 ausgibt.

Abbildung 2.1  Die vom Netscape Navigator 4.75 unterstützten JavaScript-Versionen

	Beachten Sie bei obigem Beispiel, dass man mit document.write() insbesondere auch HTML-Code, in diesem Fall den <HR>-Tag für eine horizontale Linie, ausgeben kann.

In Tabelle 2.2 sehen Sie, welche Parameter ausgewählte Browserversionen erkennen bzw. unterstützen:

Tabelle 2.2  Die von ausgewählten Browsern unterstützten Parameter <SCRIPT LANGUAGE="…">

Browser	Unterstützte Parameter
Netscape 4.00-4.05	JavaScript1.0-JavaScript1.2
Netscape 4.06-4.76	JavaScript1.0-JavaScript1.3
Netscape 6	JavaScript1.0-JavaScript1.5
Internet Explorer 4	JavaScript1.0-JavaScript1.2
Internet Explorer 5	JavaScript1.0-JavaScript1.3
Internet Explorer 5.5	JavaScript1.0-JavaScript1.3

Durch die Verwendung spezieller LANGUAGE-Attribute können Sie Fehlermeldungen vermeiden, die bei der Verwendung von zu modernen JavaScript-Kommandos erscheinen würden. Wenn Sie also Sprachelemente von JavaScript verwenden, die erst ab Version 1.1 unterstützt werden, könnten Sie das LANGUAGE-Attribut auf JavaScript1.1 setzen; ältere Browser ignorieren dann die Befehle völlig.

	Das stimmt leider nicht immer. Einige Versionen des Netscape Navigator 3 beispielsweise haben einen Bug und versuchen, auch JavaScript-Blöcke mit LANGUAGE="JavaScript1.2" und LANGUAGE="JavaScript1.3" zu interpretieren. Auch der Internet Explorer führt manchmal Code aus, der nicht für ihn bestimmt ist.

2.1.2 Browser ohne JavaScript

So schön ein Programm auch auf dem eigenen Rechner laufen mag – es kommt darauf an, dass es beim Kunden läuft, und bei allen Besuchern (nun gut, sagen wir, bei den meisten Besuchern) der Website. In vielen Firmennetzwerken ist es beispielsweise so, dass JavaScript aus Sicherheitsgründen nicht aktiviert werden darf. Die Beispiele von oben sehen dann folgendermaßen aus.

Abbildung 2.2  Die Ausgabe bei deaktiviertem JavaScript: Gähnende Leere

Bei ganz alten Browsern ist es noch schlimmer, zuweilen sieht man sogar den JavaScript-Code. Sie können sich aber hier mit einem kleinen Trick behelfen: Mit <!-- wird ein HTML-Kommentar eingeleitet; alles dahinter wird vom HTML-Interpreter ignoriert, jedoch nicht vom JavaScript-Interpreter! Es empfiehlt sich also, JavaScript-Code durch folgenden Befehl einzuleiten:

<SCRIPT LANGUAGE="JavaScript"><!--

Nun stellt sich die Frage, wie der HTML-Kommentar beendet wird. Probieren Sie einmal die einfachste Variante aus, nämlich einfach ein Kommentarende-Tag (-->) vor dem </SCRIPT>:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript"><!--
document.write("The weather means the seasons")
--></SCRIPT>
</BODY>
</HTML>

Wenn Sie diese Seite im Browser laden, sollten Sie eine Fehlermeldung erhalten. Der Grund: Der JavaScript-Interpreter interpretiert --> als JavaScript-Befehl und liefert eine Fehlermeldung.

Abbildung 2.3  Fehlermeldung des Netscape Navigator

Aber auch hier gibt es einen kleinen Trick, mit dem Sie dieses Hindernis aus dem Weg räumen können. Mit // leitet man einen Kommentar im JavaScript-Code ein. Die Verwendung von Kommentaren ist bei der Programmierung sehr wichtig, damit man auch Wochen später noch weiß, was man damals eigentlich beabsichtigt hat, und damit auch andere Menschen mit dem Code arbeiten können. Es gibt zwei Arten von Kommentaren:

	//: Hiermit wird ein einzeiliger Kommentar eingeleitet; alles hinter den beiden Querstrichen in der jeweiligen Zeile wird vom JavaScript-Interpreter ignoriert.
	/* und */: Hiermit wird ein mehrzeiliger Kommentar eingeleitet; alles nach /* wird vom JavaScript-Interpreter ignoriert, bis die Zeichenfolge */ kommt und den Kommentar abschließt.

Im folgenden Listing sehen Sie Beispiele für Kommentare:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
// Hier wird auf generelle JavaScript-Unterstützung geprüft
document.write("Der Browser unterstützt JavaScript<BR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1">
/* Hier geht es um JavaScript 1.1 */
document.write("Der Browser unterstützt JavaScript v1.1<BR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.2">
// JavaScript 1.2 wird überprüft
// und zwar gründlich
document.write("Der Browser unterstützt JavaScript v1.2<BR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.3">
/* JavaScript 1.3 wurde
   mit Netscape Navigator 4.06 eingeführt */
document.write("Der Browser unterstützt JavaScript v1.3<BR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.4">
document.write("Der Browser unterstützt JavaScript v1.4<HR>")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.5">
document.write("Der Browser unterstützt JavaScript v1.5<HR>")
</SCRIPT>
</BODY>
</HTML>

Kommen wir zum ursprünglichen Problem zurück. Der Browser gibt eine Fehlermeldung aus, weil --> als JavaScript-Code interpretiert wird und nicht als HTML-Element. Wenn dem --> jedoch ein // vorangestellt wird, ignoriert der JavaScript-Interpreter diesen Code, der HTML-Interpreter jedoch stellt fest, dass der Kommentar zu Ende ist. Folgender Code wird von Browsern, die JavaScript unterstützen, ausgeführt; Browser, die kein JavaScript unterstützen oder bei denen JavaScript deaktiviert ist, sehen einen HTML-Kommentar, ignorieren das Innere und geben folglich nichts aus, auch keinen puren JavaScript-Code.

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript"><!--
document.write("The weather means the seasons")
//--></SCRIPT>
</BODY>
</HTML>

Browser und

Textausgabe

Sie sehen an den obigen Beispielen, dass es relativ einfach ist, bei Browsern, die JavaScript unterstützen, einen Text auszugeben. Der andere Weg ist aber auch möglich. Es gibt hierfür (ab Netscape Navigator 3 bzw. Internet Explorer 3) einen besonderes HTML-Element, <NOSCRIPT>, das so ähnlich wie <NOFRAMES> funktioniert. Es gibt nun folgende denkbare Szenarien:

	Der Browser unterstützt kein JavaScript, egal, ob der <NOSCRIPT>-Tag bekannt ist oder nicht, er wird notfalls ignoriert, und die darauf folgenden HTML-Elemente werden interpretiert (bzw. der Inhalt wird angezeigt).
	Der Browser unterstützt JavaScript und ist auch eingeschaltet. Dann wird alles, was zwischen <NOSCRIPT> und </NOSCRIPT> steht, nicht dargestellt.
	Der Browser unterstützt JavaScript, es ist jedoch ausgeschaltet. Dann wird auch all das, was zwischen <NOSCRIPT> und </NOSCRIPT> steht, dargestellt.

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript"><!--
document.write("The weather means the seasons")
//--></SCRIPT>
<NOSCRIPT>
Ihr Browser kann mit JavaScript nichts anfangen,
oder es ist ausgeschaltet!
</NOSCRIPT>
</BODY>
</HTML>

	Denken Sie immer auch an diejenigen Besucher, die JavaScript deaktiviert haben oder deren Browser (man denke nur an die eingeschränkten Browser von Handhelds) kein JavaScript unterstützt. Erstellen Sie notfalls eine Version Ihrer Website, die auch ohne JavaScript funktioniert.

2.1.3 Externe Dateien

Wenn Sie später einmal JavaScript-Programme schreiben, die auf mehreren unterschiedlichen Seiten benötigt werden, wäre es eigentlich ziemlich töricht, dasselbe Skript in mehrere Seiten zu kopieren – der Aufwand bei Änderungen am Skript wäre beträchtlich, da mehrere Dateien geöffnet und geändert werden müssten.

Es gibt hier auf den ersten Blick einen Ausweg, der aber auf den zweiten Blick auch seine Nachteile hat. Zuerst zur grauen Theorie: Man kann beim <SCRIPT>-Tag im Attribut SRC den Namen einer externen Datei mit JavaScript-Kommandos angeben. Als Dateiendung hat sich hierbei .js durchgesetzt. Es empfiehlt sich, für alle externen Dateien ein eigenes Verzeichnis anzulegen, damit diese alle gesammelt an einem zentralen Ort zu finden sind.

Folgende Datei sei auf dem Webserver im virtuellen Verzeichnis js unter dem Namen weather.js gespeichert:

//erste externe JavaScript-Datei
document.write("The weather means the seasons")

Sie wird folgendermaßen in ein HTML-Dokument eingebunden, um dieselbe Wirkung zu erzielen wie das Dokument von vorher:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript" SRC="/js/weather.js">
</SCRIPT>
</BODY>
</HTML>

Natürlich kann auch hier das LANGUAGE-Attribut gesetzt werden. Bei dem folgenden Dokument wird nur etwas ausgegeben, wenn der Browser JavaScript Version 1.1 unterstützt:

<HTML>
<HEAD>
<TITLE>JavaScript</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript1.1" SRC="/js/weather.js">
</SCRIPT>
</BODY>
</HTML>

Dieses Vorgehen birgt aber auch einen kleinen Fallstrick: Probieren Sie doch einmal Folgendes in Ihrem Browser aus:

<HTML>
<BODY>
<SCRIPT LANGUAGE="JavaScript" SRC="/js/weather.js"><!--
document.write "<BR>Invincibility is in oneself,
vulnerability is in the opponent"
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 2.4  Der Text wird nur einmal angezeigt

Das Ergebnis sehen Sie in Abbildung 2.4: Der Inhalt des <SCRIPT>-Elements wird ignoriert. Der Grund: ist das SRC-Attribut des <SCRIPT>-Tags gesetzt, wird eingeschlossener JavaScript-Code nicht betrachtet; ist SRC nicht gesetzt, so wird der eingeschlossene Code ausgeführt. Um also beide Sätze auszugeben, muss das HTML-Dokument folgendermaßen abgeändert werden:

<HTML>
<BODY>
<SCRIPT LANGUAGE="JavaScript" SRC="/js/weather.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript"><!--
document.write "<BR>Invincibility is in oneself,
vulnerability is in the opponent"
//--></SCRIPT>
</BODY>
</HTML>

	Obwohl externe Dateien sehr praktisch und auch recht weit verbreitet sind, haben sie einen großen Nachteil, den viele gar nicht kennen: Der Netscape Navigator 2 kann mit dem SRC-Attribut nichts anfangen, und der Internet Explorer 3 hat immer wieder Probleme damit (und im lokalen Betrieb, also ohne Webserver, funktioniert es überhaupt nicht). Die ersten Versionen des Internet Explorer 3 haben dieses Feature gar nicht unterstützt, während es in den Versionen 3.02 und 3.03 hin und wieder funktioniert. Es hilft manchmal, eine vollständige URL anzugeben (also SRC="http://www.ihrefirma.de/skript.js"), aber auch das funktioniert hin und wieder nicht. Setzen Sie also Ihr Skript für den Internet Explorer 3 in das HTML-Dokument selbst, oder testen Sie es intensiv. Kontaktieren Sie außerdem den Betreiber Ihres Webservers; er muss ihn so konfigurieren, dass Dateien mit der Endung .js mit dem MIME-Typ application/x-javascript verknüpft werden.

Sollten in diesem Kapitel externe Dateien verwendet werden, so dient das in der Regel der Übersichtlichkeit des Codes. Natürlich muss verhindert werden, dass ältere Browser eine Fehlermeldung ausgeben.

2.2 JavaScript-Links

JavaScript-Befehle werden oft aufgrund von Benutzereingaben ausgeführt. Eine Möglichkeit besteht darin, aufgrund eines Mausklicks eine Aktion zu starten. Bevor ein paar Beispiele vorgestellt werden, muss noch ein neuer JavaScript-Befehl eingeführt werden. Mit window.alert("Invincibility is in oneself, vulnerability is in the opponent") wird ein modales Fenster ausgegeben, das den Text »Invincibility is in oneself, vulnerability is in the opponent« anzeigt. Je nach verwendetem Browser sieht das etwas anders aus, in Abbildung 2.5 sehen Sie die Darstellung im Netscape Navigator 4.

Abbildung 2.5  Ein Warnfenster mit dem Netscape Navigator

Protokolle

HTML-Links können auf URLs mit den verschiedensten Protokollen verweisen, so zum Beispiel http:, ftp:, news: oder mailto:. Nun kommt ein weiteres Protokoll hinzu, welches jedoch lediglich im Zusammenhang mit JavaScript eine Bedeutung hat: javascript:. Folgender Link gibt »I still have a dream« in einem modalen Fenster aus, wenn man darauf klickt:

<A HREF="javascript:window.alert('Invincibility
is in oneself, vulnerability is in the opponent')">

Beachten Sie die Anführungszeichen. In JavaScript ist es prinzipiell egal, ob Sie einfache oder doppelte Anführungszeichen verwenden – Hauptsache, Sie hören so auf, wie Sie angefangen haben.

Folgendes ist also völlig korrekt:

document.write("The weather means the seasons")
document.write('<BR>Invincibility is in oneself,
vulnerability is in the opponent')

Falsch ist dagegen:

document.write("The weather means the seasons ')
document.write('<BR>Invincibility is in oneself,
vulnerability is in the opponent")

Obwohl man mit dem Pseudo-Protokoll javascript: bequem JavaScript-Befehle aufrufen kann, gibt es doch einen kleinen Nachteil: Browser, die kein JavaScript unterstützen, geben eine Fehlermeldung aus. Im folgenden Abschnitt wird diesem Missstand abgeholfen.

2.3 Event-Handler

Ohne anderen Kapiteln allzu sehr vorgreifen zu wollen – wenn Sie bestimmte Aktionen tätigen, beispielsweise die Maus bewegen oder auf einen Link klicken, tritt JavaScript-intern ein sogenanntes Ereignis (engl. event) ein. Manche dieser Ereignisse können Sie mit JavaScript abfangen und darauf reagieren. Dazu benötigen Sie Event-Handler, die als Attribute mancher HTML-Tags in den HTML-Code eingebunden werden. Eine vollständige Auflistung aller Event-Handler finden Sie in der Referenz; davor werden die wichtigsten Handler in den jeweiligen Kapiteln anhand eines Beispiels vorgestellt.

Grundsätzlich gilt Folgendes: Ein Event-Handler beginnt stets mit on. Der Event-Handler, der zuständig ist, wenn auf einen Link geklickt wird, heißt onClick. Wenn folgender Link angeklickt wird, wird ein modales Fenster geöffnet:

<A HREF="irgendwohin.html" onClick="alert('Invincibility is in
oneself, vulnerability is in the opponent')">Sun Tzu</A>

Vom Prinzip her wunderbar – Browser, die JavaScript unterstützen, führen den Code aus, folgen danach aber dem Link (in späteren Kapiteln dazu mehr). Ältere Browser »sehen« nur den Link und würden versuchen, das Ziel des Links aufzurufen. Das ist aber in der Regel nicht erwünscht. Das HREF-Attribut des Links muss gesetzt werden, sonst wird er nicht angezeigt. Es gibt aber eine Möglichkeit, einen Link anzugeben, der keine neue Seite lädt:

	<A HREF="#" onClick="alert('Invincibility is in oneself, vulnerability is in the opponent')">Sun Tzu</A>

Diesen Trick sollten Sie sich gut merken!

2.4 JavaScript-Entities

Die letzte Möglichkeit, um JavaScript-Code in das HTML-Dokument einzubetten, wird sehr selten verwendet, was unter anderem auch daran liegt, dass hier nur Werte von HTML-Attributen gesetzt werden können – und es nur mit dem Netscape Navigator funktioniert. Sie kennen bereits HTML-Entities, die mit & beginnen und ; enden. Ein Beispiel ist die HTML-Entity für Ä, &Auml;. JavaScript-Entities sind ganz ähnlich aufgebaut: sie beginnen mit &, enden mit ; und dazwischen steht ein JavaScript-Ausdruck. Für dieses Beispiel wird ein weiteres neues JavaScript-Kommando (genauer: Objekteigenschaft, aber dazu später mehr) eingeführt: location.protocol gibt das verwendete Protokoll der aktuellen Seite vor, also beispielsweise file: bei lokalen Dateien und http: bei Dateien aus dem World Wide Web. In dem folgenden Dokument wird das VALUE-Attribut eines Texteingabefelds auf den Wert von location.protocol gesetzt. Die JavaScript-Entity heißt &location.protocol; – beachten Sie insbesondere, dass der JavaScript-Ausdruck in geschweifte Klammern eingeschlossen werden muss!

<HTML>
<HEAD>
<TITLE>JavaScript-Entities</TITLE>
</HEAD>
<BODY>
<FORM>
Protokoll: <INPUT TYPE="TEXT" VALUE="&{location.protocol};">
</FORM>
</BODY>
</HTML>

Abbildung 2.6  HTML-Attribute setzen mit Entities

1    Der Tag oder das Tag? Manche Autoren bevorzugen »das Tag«, um eine eindeutige Abgrenzung vom (Wochen-)Tag zu gewährleisten; ich bevorzuge jedoch »der Tag«.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 3 Programmierung I
			3.1 Variablen
			3.2 Operatoren
			3.3 Kontrollstrukturen: Schleifen
			3.4 Fragen & Aufgaben

Kapitel 3 Programmierung I

There was Winnie the Pooh,

and Tigger, too.

– frei nach: A. A. Milne, Pooh’s Bedtime Book

Gut gerüstet

In diesem und dem folgenden Kapitel werden die Grundprinzipien der Programmierung an sich und der Programmierung mit JavaScript im Besonderen erläutert. An Praxisbeispielen ist dieses Kapitel recht arm, aber Sie werden die hier vorgestellten Techniken in den weiteren Kapiteln noch des Öfteren benötigen. Sie erhalten hier das Rüstzeug, das die Grundlage für alle kommenden Kapitel ist.

Grundbegriffe der Programmierung werden hier ebenfalls erläutert. Leser, die bereits Erfahrungen mit der einen oder anderen Programmiersprache haben, mögen diesen kleinen Exkurs verzeihen, aber so soll auch Neulingen die Chance geboten werden, in die Materie einzusteigen. Auf der anderen Seite wiederum sind die Erklärungen recht knapp gehalten, und nur das Nötigste wird hierzu erklärt. Schließlich geht es ja darum, möglichst schnell brauchbare Anwendungen zu schreiben.

3.1 Variablen

Bei der Programmierung müssen immer wieder Daten zwischengespeichert werden. Hierzu bedient man sich so genannter Variablen (in manchen Büchern – aber sehr wenigen – auch als »Veränderliche« bezeichnet).

3.1.1 Namensgebung

Jede Variable wird anhand ihres Namens angesprochen. Bei der Namensgebung haben Sie größtenteils freie Hand. Ein Variablenname besteht aus einer Folge von Buchstaben, Ziffern und dem Unterstrich ( _ ). Einzige Bedingung: Das erste Zeichen darf keine Ziffer sein. Außerdem wird zwischen Groß- und Kleinschreibung unterschieden. Die Bezeichner Pooh, pooh und POOH sind also verschiedene Variablen. Beispiele für Variablennamen sind etwa:

	Winnie_The_Pooh
	WinnieThePooh
	Winnie2000
	_Winnie_

JavaScript-Schlüsselworte und -begriffe dürfen Sie nicht als Variablennamen verwenden. Ein Beispiel hierfür ist etwa alert, das Sie im vorherigen Kapitel schon einmal in Aktion gesehen haben.

Um einer Variablen einen Wert zuzuweisen, wird das Gleichheitszeichen verwendet. Links vom Gleichheitszeichen steht der Variablenname, rechts davon der neue Wert (oder eine andere Variable, deren Wert dann zugewiesen wird).

3.1.2 Numerische Variablen

Es gibt verschiedene Typen von Variablen. Zahlenwerte werden wie im amerikanischen Zahlensystem mit einem Dezimalpunkt statt einem Dezimalkomma angegeben:

Pi = 3.1415926
Mauerfall = 1989
MinusHundert = -100

3.1.3 Zeichenketten

Sehr oft werden Zeichenketten, auch Strings genannt, verwendet. Die zweite Bezeichnung kommt daher, dass es ein so benanntes Objekt in JavaScript gibt, aber dazu später mehr. In diesem Buch werden beide Begriffe äquivalent verwendet.

Ein String wird von Anführungszeichen eingeschlossen, entweder von einfachen (Apostrophen) oder doppelten. Hierbei ist zu beachten, dass unbedingt gerade Anführungszeichen ((ª)+(2)) und Apostrophe ((ª)+(#)) verwendet werden. Im Gegensatz zu beispielsweise Perl ist es hier egal, ob einfache oder doppelte Anführungszeichen verwendet werden, Hauptsache, die Zeichenkette wird mit derselben Art von Anführungszeichen beendet, wie sie eingeleitet worden ist.

WinniesFreund = "Piglet"
WinniesAndererFreund = 'Tigger'

Die verschiedenen Anführungszeichen haben unter anderem den folgenden Sinn: Wenn Sie beispielsweise ein Apostroph in einer Zeichenkette verwenden wollen, können Sie diese Zeichenkette ja schlecht mit Apostrophen eingrenzen, da der JavaScript-Interpreter dann nicht weiß, wo die Zeichenkette aufhört. In diesem Fall muss man die andere Sorte von Anführungszeichen verwenden:

WinnieSays = "It's me, Winnie the Pooh"

Wenn man aber in der Verlegenheit ist, beispielsweise beide Arten von Anführungszeichen in einer Zeichenkette verwenden zu müssen, kommt man in Schwierigkeiten. Hier hilft der Backslash (\) weiter. Das dem Backslash folgende Zeichen wird »entwertet«, d. h. es nimmt in der Zeichenkette keine besondere Bedeutung ein. Beim Anführungszeichen oder Apostroph bedeutet das: Die Zeichenkette wird hiermit nicht beendet.

WinnieSays = 'It\'s me, Winnie the Pooh'

Wenn man nun den Backslash selbst in der Zeichenkette verwenden will, muss man auch ihn entwerten:

WindowsVerzeichnis = "C:\\WINDOWS"

Mit dem Backslash können auch einige besondere Zeichen dargestellt werden. Tabelle 3.1 zeigt eine Übersicht:

Tabelle 3.1  Sonderzeichen innerhalb von Zeichenketten

Ausdruck	Bedeutung
\r	Wagenrücklauf
\n	Neue Zeile
\t	Tabulator
\b	Backspace (Löschtaste)
\f	Seitenvorschub

3.1.4 Boolesche Variablen

Oft ist man nicht an einem Zahlenwert oder einem String interessiert, sondern an einem Wahrheitswert, also wahr oder falsch. Man spricht hier auch von Booleschen Variablen. Solche Variablen können als Wert nur true (wahr) oder false (falsch) annehmen. Später werden Sie sehen, dass Boolesche Werte indirekt auch bei einigen anderen JavaScript-Konstrukten vorkommen.

Ist2000einSchaltjahr = true
Ist3000einSchaltjahr = false

3.1.5 Variablendeklaration

Wie bereits gesehen, kann mit dem Gleichheitszeichen einer Variablen ein Wert zugewiesen werden. Ein Variablenname kann auch öfter verwendet werden, und ihm kann auch mehrmals ein Wert zugewiesen werden, es handelt sich dann jedoch immer um dieselbe Variable. Sehr oft findet man in der Praxis das Schlüsselwort var vor der ersten Verwendung einer Variablen. Dies dient zur Initialisierung der Variablen und wird ab hier der Übersichtlichkeit halber in diesem Buch konsistent verwendet. So sieht man auf den ersten Blick, welche Variable schon einmal deklariert worden ist und welche nicht. Später, bei der Einführung von Funktionen, wird das Schlüsselwort noch eine besondere Bedeutung erhalten.

Beachten Sie, dass Sie das Schlüsselwort var nur einmal pro Variable verwenden sollten. Richtig ist also Folgendes:

var AnzahlHonigtoepfe = 5
// Befehle zum Einkaufen von mehr Vorräten
AnzahlHonigtoepfe = 6

Nicht so gut ist dagegen:

var AnzahlHonigtoepfe = 5
// Befehle zum Einkaufen von mehr Vorräten
var AnzahlHonigtoepfe = 6

In diesem und auch in einigen der anderen Beispiele in diesem Buch sind gegenüber einem vorherigen Listing veränderte Programmzeilen durch Fettdruck hervorgehoben.

3.2 Operatoren

Durch Operatoren wird eine gewisse Anzahl von Variablen miteinander kombiniert. Beispiele für Operatoren sind die Grundrechenarten. Durch den Plus-Operator werden zwei Zahlen miteinander kombiniert, und als Ergebnis erhält man die Summe dieser beiden Zahlen. Man unterscheidet – auch je nach Typ der beteiligten Variablen – verschiedene Arten von Operatoren.

3.2.1 Arithmetische Operatoren

Diese Art von Operatoren arbeitet mit numerischen Variablen. Sie sollten also sicherstellen, dass auch wirklich Zahlenvariablen vorliegen, sonst könnten Sie eine Fehlermeldung erhalten. In Kapitel »Formulare II« finden Sie im übrigen Techniken, wie man Zahlenvariablen als solche erkennen kann. Tabelle 3.2 zeigt alle arithmetischen Operatoren anhand eines Beispiels.

Tabelle 3.2  Arithmetische Operatoren

Operator	Beschreibung	Beispiel	Ergebnis (Wert von a)
+	Addition	a = 7 + 4	11
-	Substraktion	a = 7 – 4	3
*	Multiplikation	a = 7 * 4	28
/	Division	a = 7 / 4	1.75
%	Modulo (Restrechnung)1	a = 7 % 4	3
-	Negation	b = 7 a = -b	-7

Will1 man eine Variable um einen bestimmten Wert erhöhen, kann man sich des folgenden Konstrukts bedienen:

AnzahlHonigtoepfe = AnzahlHonigtoepfe + 5

Der Variablen AnzahlHonigtoepfe wird als Wert der alte Wert dieser Variablen plus fünf zugewiesen, der Wert der Variablen wird also de facto um fünf erhöht. In der Praxis kommt es sehr häufig vor, dass der Wert einer Variablen um genau eins erhöht oder verringert werden soll; für diesen Fall sieht JavaScript eine Abkürzung vor:

	AnzahlHonigtoepfe++ erhöht den Wert der Variablen um eins.
	AnzahlHonigtoepfe-- verringert den Wert der Variablen um eins.

Die Operatoren ++ und -- können auch direkt vor dem Variablennamen stehen. Der Unterschied liegt in der Reihenfolge, in der diese Operation im Vergleich mit anderen Operationen ausgeführt werden soll. Am Beispiel des Operators ++ soll das einmal durchexerziert werden; -- verhält sich analog.

Das Endergebnis des Standalone-Ausdrucks

AnzahlHonigtoepfe++

ist äquivalent mit dem von

++AnzahlHonigtoepfe

Einen Unterschied stellt man jedoch fest, wenn der Ausdruck bei einer Zuweisung verwendet wird:

AnzahlHonigtoepfe = 5
var Anzahl = ++AnzahlHonigtoepfe
var Anzahl2 = AnzahlHonigtoepfe++

Welchen Wert hat Anzahl, welchen Wert hat Anzahl2?

Die (vielleicht etwas überraschende) Antwort lautet: Anzahl hat den Wert 6, Anzahl2 hat auch den Wert 6. Betrachten Sie zunächst die zweite Zeile:

var Anzahl = ++AnzahlHonigtoepfe

Der ++-Operator steht vor dem Variablennamen, das bedeutet hier, es wird zunächst diese Operation ausgeführt (AnzahlHonigtoepfe um eins erhöhen), und dann wird der neue Wert (6) der Variablen Anzahl zugewiesen.

Bei der dritten Zeile ist es genau andersherum:

var Anzahl2 = AnzahlHonigtoepfe++

Zuerst wird der Variablen Anzahl2 der (aktuelle) Wert von AnzahlHonigtoepfe zugewiesen, dann wird der Wert von AnzahlHonigtoepfe um eins vergrößert.

Wenn man den Wert einer Variablen nicht um exakt eins erhöhen oder verringern will, kann man sich einer anderen Abkürzung bedienen. Diese Abkürzung existiert für jede der vier Grundrechenarten sowie für den Modulo-Operator:

Tabelle 3.3  Abkürzungen für arithmetische Operationen

Operator	Bedeutung	Langform	Kurzform
+=	Addition	a = a + b	a += b
-=	Subtraktion	a = a – b	a -= b
*=	Multiplikation	a = a * b	a *= b
/=	Division	a = a / b	a /= b
%=	Modulo	a = a % b	a %= b

Auch in JavaScript gilt, dass Punktrechnung vor Strichrechnung geht, d. h. Multiplikationen und Divisionen werden vor Additionen und Subtraktionen ausgeführt. Der folgende Ausdruck liefert also 7 und nicht 9:

var PunktVorStrich = 1+2*3

3.2.2 Boolesche Operatoren

Mit Logikoperatoren (oder Booleschen Operatoren) kann man Wahrheitswerte miteinander verknüpfen. Die Bedeutung der Operatoren ist die mathematische Bedeutung, nicht unbedingt die umgangssprachliche Bedeutung. Aus diesem Grund werden die einzelnen Operatoren explizit behandelt.

UND (&&)

Nur, wenn beide (bzw. alle) beteiligten Variablen den Wert true haben, liefert die Operation true zurück, ansonsten false.

var t = true
var f = false
var bool1 = t && f  //liefert false
var bool2 = t && t  //liefert true

ODER (||)

Ist eine der beteiligten Variablen true, so liefert die Operation true zurück. Das Ergebnis ist nur dann false, wenn alle Variablen den Wert false haben. Hier liegt ein Unterschied zum Deutschen vor, denn dort bedeutet »oder« eher »Entweder-oder«: Nur dann ist das Ergebnis true, wenn genau eine der beteiligten Variablen den Wert true hat.

var t = true
var f1 = false
var f2 = false
var bool1 = t || f1 || f2  //liefert true
var bool2 = f1 || f2  //liefert false

NEGATION (!)

Der Negationsoperator macht true zu false und false zu true.

var t = true
var f = false
var bool1 = !t  //liefert false
var bool2 = !f  //liefert true

Short Evaluation

Wie Sie bereits gesehen haben, genügt genau eine Variable mit dem Wert true, damit das Ergebnis einer Oder-Verknüpfung ganz sicher den Wert true hat. Analog liefert eine Und-Verknüpfung auf jeden Fall den Wert false, wenn eine Variable den Wert false hat.

JavaScript benutzt hier das Prinzip der so genannten Short Evaluation (wörtlich: kurze Auswertung), zumindest die existierenden Implementierungen. Bei einer Und- bzw. Oder-Verknüpfung werden die beteiligten Variablen von links nach rechts durchgegangen. Sollte bei einer dieser Variablen aufgrund ihres Werts das Ergebnis der gesamten Operation schon feststehen, wird der Rest gar nicht ausgewertet.

Vergleichsoperatoren

Vergleichsoperatoren werden meistens bei Zahlenwerten verwendet. Auch bei Zeichenketten sind diese Vergleiche möglich, hier richtet sich die Rangfolge der einzelnen Zeichen (welches Zeichen ist »größer« als ein anderes?) nach dem ASCII-Code des Zeichens.

Tabelle 3.4  Vergleichsoperatoren

Operator	Beschreibung	Beispiel	Ergebnis (Wert für a)
==	Gleich	a = (3 == 4) a = ("Pooh" == "Piglet")	false
!=	Ungleich	a = (3 != 4) a = ("Pooh" != "Piglet")	true
>	Größer als	a = ( 3 > 4)	false
<	Kleiner als	a = (3 < 4 )	true
>=	Größer oder gleich	a = ( 3 >= 4)	false
<=	Kleiner oder gleich	a = (3 <= 4 )	true
	Eine der häufigsten Fehlerquellen besteht in der Verwechslung der Zuweisung = mit dem Vergleichsoperator ==. Ab JavaScript Version 1.3 gibt der Interpreter eine Fehlermeldung aus, wenn offensichtlich ein Vergleich durchgeführt werden soll, aber der Zuweisungsoperator verwendet wird.

3.2.3 String-Operatoren

Auch mit Zeichenketten kann man »rechnen«; man kann zwei Zeichenketten aneinander hängen. Hierzu wird auch der Plus-Operator (+) verwendet:

var Vorname = "Winnie"
var Nachname = "Pooh"
var Baer = Vorname + " " + Nachname  //liefert "Winnie Pooh"

Ansonsten kann man mit Zeichenketten nicht rechnen. Dennoch sollen an dieser Stelle noch drei Möglichkeiten vorgestellt werden, um mit Zeichenketten etwas anzufangen:

	Zeichenkette.length: Liefert die Anzahl der Zeichen in einer Zeichenkette zurück.
	Zeichenkette.charAt(x): Liefert das Zeichen an Position x in der Zeichenkette zurück. Dabei beginnt die Zählung bei 0, das vierte Zeichen erhält man also mit Zeichenkette.charAt(3).
	Zeichenkette.substring(start, ende): Liefert eine Teilzeichenkette zurück, und zwar ab dem Zeichen an Position start (Zählung beginnt wieder bei 0) und bis zu dem Zeichen vor dem Zeichen an der Position ende.

Hierzu ein kleines Beispiel. In den Variablen a und b stehen das erste Zeichen der Zeichenkette und die folgenden Zeichen:

var z = "Winnie The Pooh"
var a = z.charAt(0)
var b = z.substring(1, z.length)

3.2.4 Umwandlung zwischen den Variablentypen

Die vorgestellten Operatoren können auch dazu verwendet werden, zwischen den einzelnen Variablentypen umzuwandeln. JavaScript ist in Sachen Variablentypus nicht so strikt wie andere Programmiersprachen. Eine Variable kann auch ihren Typ während des Programmablaufs ändern. Beispielsweise werden Sie in einem späteren Kapitel feststellen, dass Formulareingaben stets als Zeichenketten vorliegen. Wenn Sie sich aber sicher sind, dass die Zeichenkette eine korrekt formatierte Zahl enthält, können Sie JavaScript dazu zwingen, die Variable als Zahlenwert zu betrachten. Der Trick besteht darin, die Variable mit eins zu multiplizieren (oder 0 zu addieren). Eine Multiplikation kann nur mit Zahlenwerten durchgeführt werden, sodass JavaScript die Variable in eine Zahl umwandelt – und eine Multiplikation mit eins ändert am Wert der Zahl auch nichts.

Außerdem ist es manchmal notwendig, eine Boolesche oder numerische Variable in eine Zeichenkette umzuwandeln. Diesmal muss der Konkatenationsoperator (Verkettungsoperator), das Plus, verwendet werden. Indem eine Variable mit einer leeren Zeichenkette konkateniert (verkettet) wird, erhält man als Ergebnis eine Zeichenkette, ändert aber ansonsten den Wert der Variablen nicht.

var AnzahlHonigtoepfe = "5"
AnzahlHonigtoepfe *= 1  //Zeichenkette in Zahl
var wahrheitswert = true
wahrheitswert += ""  //Wahrheitswert in Zeichenkette
var Anzahl = 6
Anzahl += ""  //Zahl in Zeichenkette

JavaScript führt zwar eine automatische Typenkonvertierung durch, aber nicht immer in die gewünschte Richtung:

var summe = "47" + 11  //liefert "4711" und nicht etwa 58

3.3 Kontrollstrukturen: Schleifen

Hin und wieder kommt es vor, dass eine Anweisung mehrmals ausgeführt werden muss, beispielsweise bei einer Aufzählung. Hierzu bietet JavaScript mehrere Kontrollstrukturen an. Mit JavaScript Version 1.2 (sowie beim Internet Explorer 4) wurden neue Kontrollstrukturen eingeführt, die aber mit dem Befehlssatz von JavaScript 1.0 vollständig nachgebildet werden können.

3.3.1 For-Schleifen

Diese Art der Schleife führt eine Anweisung eine (in der Regel) bestimmte Anzahl von Malen aus. Die Syntax sieht dabei folgendermaßen aus:

for (Initialisierung; Bedingung; Befehlsfolge){
   //Anweisungen
}

Die for-Schleife hat drei Parameter:

	Initialisierung: Oft läuft bei einer Schleife eine Zählvariable mit, die die Anzahl der Wiederholungen zählt. Diese Variable kann hier initialisiert werden. Sollen mehrere Variablen initialisiert werden, so werden die einzelnen Anweisungen durch Kommata voneinander getrennt.
	Bedingung: Die for-Schleife wird so lange ausgeführt, bis diese Bedingung nicht mehr erfüllt ist.
	Befehlsfolge: Nach jedem Durchlauf der Anweisungen wird diese Befehlsfolge (in der Regel ein Befehl; mehrere Befehle werden durch Kommata voneinander getrennt) ausgeführt. Wenn die Schleife irgendwann enden soll, sollten hier in der Regel Befehle ausgeführt werden, die nach einer bestimmten Anzahl von Durchläufen die Bedingung (den zweiten Parameter) nicht mehr erfüllbar machen.

Die geschweiften Klammern um den Anweisungsblock sind dann zwingend, wenn der Block aus mehr als einem Befehl besteht. Handelt es sich um nur einen Befehl, so kann man die geschweiften Klammern weglassen. Man sollte aber zumindest den Code einrücken, damit das ganze übersichtlich und lesbar bleibt.

Der folgende Code gibt zehnmal Winnie aus. Dabei wird eine Zählvariable mit 0 initialisiert und in jedem Schleifendurchlauf um eins erhöht. Die Abbruchbedingung prüft, ob die Zählvariable kleiner als zehn ist. Vor dem elften Durchlauf wird die Variable auf zehn erhöht, und die Schleife wird verlassen.

for (var i=0; i<10; i++)
   document.write("Winnie<BR>")

Sehr oft wird die Zählvariable auch direkt in der Schleife verwendet. Der folgende Code gibt alle Quadratzahlen von 0  =  0 bis 10  =  100 aus:

for (var i=0; i<=10; i++){
   document.write("Das Quadrat von " + i + " ist: ")
   document.write(i*i + "<BR>")
}

Sie sehen hierbei die Verwendung des Plus-Operators: Hier werden eine Zeichenkette und eine Zahl zusammengefügt. Das Ergebnis ist eine Zeichenkette, die Zahl wird also in eine Zeichenkette umgewandelt.

Beachten Sie ebenso, dass Sie einen Zeilenumbruch nicht mit \r\n angeben sollten, sondern mit dem entsprechenden HTML-Tag, <BR>. Bei Tags gibt es noch eine Besonderheit zu beobachten, aber hierzu kommen wir erst im nächsten Kapitel.

Wie bereits erwähnt, kann man auch mehrere Zählvariablen verwenden, die man dann durch Kommata voneinander trennen muss. Anwendungen gibt es ziemlich selten, hier folgt ein sehr praxisfremdes Beispiel. Es werden zwei Zählvariablen verwendet, i und j. Die erste enthält eine Zahl, die zweite eine Zeichenkette. Der Zahlenwert wird in eine Zeichenkette umgewandelt und an j angehängt. Sobald j mehr als 15 Zeichen enthält, wird die Schleife verlassen.

for (var i=1, j=""; j.length<=15; i++, j += i)
   document.write(i + " – " + j + "<BR>")

Dieses Programm gibt Folgendes auf dem Bildschirm aus:

1 – 1
2 – 12
3 – 123
4 – 1234
5 – 12345
6 – 123456
7 – 1234567
8 – 12345678
9 – 123456789
10 – 12345678910
11 – 1234567891011
12 – 123456789101112

Vor dem nächsten Schleifendurchlauf würde an die Zeichenkette 13 angehängt, die Länge würde dadurch auf 17 Zeichen anwachsen, also wird die Schleife hier verlassen.

3.3.2 Do-While-Schleife

	Nicht immer weiß man, wie oft ein Anweisungsblock hintereinander ausgeführt werden soll. Statt dessen will man den Block so lange ausführen, bis eine Bedingung nicht mehr erfüllt ist. Im folgenden Beispiel sollen in einer Zeichenkette alle As durch Bs ersetzt werden. Hierbei ist die Methode Zeichenkette.indexOf(Teilstring) nützlich; diese gibt nämlich zurück, an welcher Position in der Zeichenkette der Teilstring das erste Mal vorkommt. Ist dieser nicht in der Zeichenkette enthalten, wird -1 zurückgegeben. Das erste Zeichen steht, wie auch schon vorher, an Position 0. Diese Art von Schleife gibt es jedoch erst seit Netscape Navigator 4 und Internet Explorer 4.

Die Syntax ist die Folgende:

do {
   //Anweisungsblock
} while (Bedingung)

Der Anweisungsblock wird ausgeführt, und dann wird die Bedingung überprüft. Ist sie erfüllt, wird der Block erneut ausgeführt (und dann wieder die Bedingung geprüft); andernfalls wird die Schleife verlassen.

var Zeichenkette = "AXAYAZ"
do{
   io = Zeichenkette.indexOf("A")
   Zeichenkette = Zeichenkette.substring(0, io) + "B" +
      Zeichenkette.substring(io+1, Zeichenkette.length)
} while (Zeichenkette.indexOf("A")>-1)

Nach dem Durchlauf enthält Zeichenkette den Wert BXBYBZ.

Beachten Sie insbesondere, dass die Schleife auf jeden Fall einmal ausgeführt wird! Im Beispiel führt das zu einem Fehler, wenn die Zeichenkette zu Anfang überhaupt kein A enthält. Im Folgenden lernen Sie Methoden kennen, um dies zu vermeiden.

Noch ein Wort zu der Zuweisung. Wenn Sie bei einer Zeichenkette z das Zeichen an Stelle x in das Zeichen X ändern wollen (Zählung beginnt wie immer bei 0), kommen Sie mit folgender Anweisung weiter:

z = z.substring(0, x) + "X" + z.substring(x+1, z.length)

Alle Zeichen vor und hinter dem zu ändernden Zeichen werden durch die beiden substring()-Anweisungen erhalten.

3.3.3 While-Schleife

Schon seit JavaScript Version 1.0 gibt es eine weitere Form der Schleifen, und zwar while-Schleifen (ohne do). Die Syntax ist der von do-while-Schleifen sehr ähnlich, der Unterschied steckt im Detail:

while (Bedingung){
   //Anweisungsblock
}

Die Bedingung wird also hier vor dem Durchlaufen des Anweisungsblocks überprüft. Im Beispiel von oben, der Ersetzung aller As durch Bs, ist das sehr nützlich, da hier der Anweisungsblock nicht ausgeführt wird, wenn die Zeichenkette von Anfang an keine As enthält:

var Zeichenkette = "AXAYAZ"
while (Zeichenkette.indexOf("A")>-1){
   io = Zeichenkette.indexOf("A")
   Zeichenkette = Zeichenkette.substring(0, io) + "B" +
     Zeichenkette.substring(io+1, Zeichenkette.length)
}

3.3.4 For-In-Schleife

Diese Schleife wird recht selten verwendet, und an dieser Stelle fehlt noch das Grundwissen über Objekte, um eine ausreichende Erklärung geben zu können. Prinzipiell sei gesagt, dass man hier mit der Schleife durch alle Eigenschaften eines Objekts laufen kann. Die folgende Schleife gibt das NAME-Attribut aller Elemente eines Formulars wieder. Spätestens im Kapitel »Formulare I« werden Sie diesen Code verstehen, vorerst aber müssen Sie mir einfach glauben.

for (e in document.forms[0].elements)
   document.write(e.name+"<BR>")

3.3.5 Schleifensteuerung

Eine Schleife muss nicht unbedingt so oft durchlaufen werden, wie vorgesehen ist. Angenommen, in einer Schleife wird eine Zeichenkette auf das Vorhandensein eines bestimmten Zeichens überprüft (das geht mit indexOf() sehr schnell, aber das soll an dieser Stelle nicht interessieren). Sobald das Zeichen gefunden worden ist, muss die Schleife nicht unbedingt weiter ausgeführt werden, denn das Ergebnis (»Das Zeichen ist in der Zeichenkette enthalten«) steht ja jetzt schon fest. Aus diesem Grund gibt es den Befehl break, der das sofortige Verlassen der aktuellen Schleife veranlasst. Der Interpreter fährt also hinter dem aktuellen Anweisungsblock fort.

Ebenso kann es bei Schleifen, insbesondere bei for-Schleifen, immer wieder vorkommen, dass man zum nächsten Schleifendurchlauf springen möchte, beispielsweise, wenn man genau weiß, dass dieser Durchlauf nicht das gewünschte Ergebnis bringt, und man den Rest der Schleife aus Effizienzgründen nicht ausführen lassen möchte. Der entsprechende Befehl heißt continue.

Auch hier ist es leider so, dass das momentane Wissen noch nicht ausreicht, um ein sinnvolles Beispiel anzugeben. Am Ende des nächsten Kapitels werden Sie aber in der Lage sein, die Befehle break und continue einzusetzen.

Allgemein wird die Verwendung von break und continue als eher schlechter Programmierstil angesehen; zu sehr ähneln diese Befehle dem Spaghetti-Code aus alten BASIC-Zeiten2 .

In der Praxis werden die beiden Befehle jedoch durchaus angewandt, und zumindest im JavaScript-Bereich ist nach Meinung des Autors nichts dagegen einzuwenden.

3.4 Fragen & Aufgaben

1.	Welche der folgenden Variablennamen sind gültig?
		Winnie-The-Pooh
		Winnie1
		1Winnie
		Winnie Pooh
		_1a
2.	Woran scheitert dieser Aufruf?
<A HREF="#" onClick="alert(\"I love Tigger\")">

3.	Was sind die prinzipiellen Unterschiede zwischen einer while- und einer do-while-Schleife?
4.	Erzeugen Sie einen JavaScript-Code, der in einer Zeichenkette alle Leerzeichen durch %20 ersetzt.

1    Siehe Beispiel: 7 Modulo 4 liefert 3, weil 7 bei der Division durch 4 den Rest 3 lässt. Analog ist beispielsweise 11 Modulo 4 auch 3.

2    Bei den Ur-Versionen von BASIC wurde jede Programmzeile anhand ihrer Nummer identifiziert. Schleifen gab es nur in sehr eingeschränkter Form, sodass einer der häufigsten Befehle GOTO hieß, mit dem eine Zeilennummer direkt angesprungen werden konnte. Dadurch wurde der Quellcode sehr unübersichtlich und auch unsauber.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 4 Programmierung II
			4.1 Fallunterscheidung
			4.2 Datenspeicherung
			4.3 Funktionen
			4.4 Objekte
			4.5 Fragen & Aufgaben

Kapitel 4 Programmierung II

Up, down, touch the ground,

gets me in the mood,

in the mood for food.

– frei nach Disney’s Winnie the Pooh sing along

Dieses Kapitel beendet auch schon die Grundlagen der Programmierung. Nach der Lektüre sind Sie in der Lage, in JavaScript zu programmieren – lediglich, wie man mit JavaScript auf Elemente einer HTML-Seite zugreift, wissen Sie noch nicht. Darüber erfahren Sie aber in den restlichen Kapiteln noch genug. An dieser Stelle wird die Auflistung der Sprachelemente von JavaScript vollendet, und auch der prinzipielle Zugriff auf HTML-Dokumente und die Elemente dieser HTML-Dokumente wird dargestellt.

4.1 Fallunterscheidung

Eines der Hauptelemente aller JavaScript-Programme ist die Fallunterscheidung. Schon im vorherigen Kapitel haben Sie gesehen, dass man mit den bereits vorgestellten Mitteln schnell an seine Grenzen stößt.

4.1.1 If-Anweisung

Gehen wir zu dem Beispiel zurück, in dem alle As durch Bs ersetzt werden sollen. Mit einer while-Schleife geht das, aber bei einer do-while-Schleife hatten wir das Problem, dass es eine Fehlermeldung gibt, wenn die Zeichenkette von Anfang an kein A enthält. Der Code sah folgendermaßen aus:

var Zeichenkette = "AXAYAZ"
do{
   io = Zeichenkette.indexOf("A")
   Zeichenkette = Zeichenkette.substring(0, io) + "B" +
     Zeichenkette.substring(io+1, Zeichenkette.length)
} while (Zeichenkette.indexOf("A")>-1)

Wenn man die Möglichkeit hätte, innerhalb der Schleife zu überprüfen, ob die Zeichenkette noch ein A enthält, hätte man kein Problem. Natürlich gibt es eine solche Möglichkeit. Man bedient sich einer if-Anweisung, oder einer if-else-Anweisung.

Die Syntax sieht folgendermaßen aus:

if (Bedingung){
   //Anweisungsblock
} else {
   //Anweisungsblock
}

Ist die Bedingung erfüllt, wird der erste Anweisungsblock ausgeführt; falls nicht, wird der zweite Anweisungsblock ausgeführt. Der else-Teil ist hier optional, und wieder können die geschweiften Klammern weggelassen werden, wenn der Anweisungsblock aus genau einer Anweisung besteht.

	Wenn der erste Anweisungsblock keine geschweiften Klammern enthält, und das else in derselben Zeile steht, muss die Anweisung mit einem Semikolon beendet werden. Falsch ist also:

if (a==5) b=6 else c=7

Richtig ist dagegen:

if (a==5) b=6; else c=7

	Bei einer if-Anweisung ist die Gefahr besonders groß, dass statt des Gleichheitsoperators == die Zuweisung = verwendet wird. Achten Sie hier besonders auf Ihre Syntax!

Aber zurück zum Beispiel. Es gibt hier mehrere Möglichkeiten. Die Überprüfung, ob die Zeichenkette ein A enthält, ist recht einfach darzustellen, bei den Konsequenzen hat man die Wahl. Nahe liegend ist die folgende Variante:

var Zeichenkette = "AXAYAZ"
do{
   io = Zeichenkette.indexOf("A")
   if (io>-1)
      Zeichenkette = Zeichenkette.substring(0, io) + "B" +
        Zeichenkette.substring(io+1, Zeichenkette.length)
} while (Zeichenkette.indexOf("A")>-1)

Man kann auch bei Bedarf die Schleife einfach verlassen:

var Zeichenkette = "AXAYAZ"
do{
   io = Zeichenkette.indexOf("A")
   if (io==-1)
      break
   Zeichenkette = Zeichenkette.substring(0, io) + "B" +
     Zeichenkette.substring(io+1, Zeichenkette.length)
} while (Zeichenkette.indexOf("A")>-1)

Dann braucht man die while-Bedingung aber gar nicht mehr und könnte beispielsweise folgende Variante verwenden:

var Zeichenkette = "AXAYAZ"
do{
   io = Zeichenkette.indexOf("A")
   if (io==-1)
      break
   Zeichenkette.charAt(io) = "B"
} while (true)

Die Bedingung true ist immer erfüllt, der Anweisungsblock kann also nur durch ein break verlassen werden. Ob der Programmierstil des obigen Beispiels besonders gut ist, steht auf einem völlig anderen Blatt.

Eine besondere, verkürzte Variante der if-else-Anweisung gibt es noch. Sie hat folgende Syntax:

(Bedingung) ? Wert1 : Wert2

Ist die Bedingung erfüllt, ihr Wert also true, so wird Wert1 zurückgegeben, ansonsten Wert2. Meistens wird diese Schreibweise bei einer Variablenzuweisung verwendet, also in der Form:

Figur = (Essen=="Honig") ? "Pooh" : "Tigger"

Es gibt somit eine weitere Möglichkeit, in einer Zeichenkette alle As durch Bs zu ersetzen, indem alle Zeichen überprüft und gegebenenfalls ersetzt werden. Auch hier gibt es mehrere Möglichkeiten, um das ganze auszuprogrammieren, aber unter Verwendung der gerade vorgestellten Kurzschreibweise bietet sich die folgende Variante an:

var Zeichenkette = "AXAYAZ"
for (var i=0; i<Zeichenkette.length; i++){
   ca = Zeichenkette.charAt(i)
   ca = (ca=="A") ? "B" : ca
   Zeichenkette = Zeichenkette.substring(0, i) + ca +
Zeichenkette.substring(i+1, Zeichenkette.length)
}

Ausgeschrieben hätte das Beispiel die folgende, etwas längere Form:

var Zeichenkette = "AXAYAZ"
for (var i=0; i<Zeichenkette.length; i++){
   ca = Zeichenkette.charAt(i)
   if (ca=="A")
      ca = "B"
   Zeichenkette = Zeichenkette.substring(0, i) + ca +
Zeichenkette.substring(i+1, Zeichenkette.length)
}

4.1.2 switch-Anweisung

Die Aufgabenstellung klingt einfach: In einer Variablen steht die Nummer eines Monats. Das Programm soll den Namen des Monats ausgeben. Mit if-Anweisungen kann das ganze folgendermaßen erledigt werden:

if (monat==1)
   document.write("Januar")
if (monat==2)
   document.write("Februar")
if (monat==3)
   document.write("März")
if (monat==4)
   document.write("April")
if (monat==5)
   document.write("Mai")
if (monat==6)
   document.write("Juni")
if (monat==7)
   document.write("Juli")
if (monat==8)
   document.write("August")
if (monat==9)
   document.write("September")
if (monat==10)
   document.write("Oktober")
if (monat==11)
   document.write("November")
if (monat==12)
   document.write("Dezember")

	Dieses Beispiel hat wenigstens den Vorteil, dass man keine else-Zweige verwenden muss1 , dann würde nämlich der obige Code noch viel unübersichtlicher werden. Die Browser der Version 4 kennen jedoch eine Spracherweiterung, mit der man den Code etwas übersichtlicher gestalten kann. Sie hat folgende Syntax:

switch (Ausdruck){
   case Wert1:
      //Programmblock
      break
   case Wert2:
      //Programmblock
      break
   //usw.
   default:
      //Programmblock
}

Es dreht sich hierbei alles um Ausdruck, der in der Regel eine Variable ist. Hat dieser Ausdruck den Wert Wert1, wird der erste Programmblock ausgeführt, bei Wert2 der zweite Programmblock, und so weiter. Der default-Abschnitt wird ausgeführt, wenn keiner der vorherigen Werte zutrifft. Dieser Abschnitt ist optional. Jeder Programmblock muss mit dem Kommando break abgeschlossen werden.

Das Monats-Beispiel lässt sich folgendermaßen umformulieren, und der Code ist deutlich kürzer und übersichtlicher:

switch (monat){
   case 1: var m = "Januar"; break
   case 2: var m = "Februar"; break
   case 3: var m = "März"; break
   case 4: var m = "April"; break
   case 5: var m = "Mai"; break
   case 6: var m = "Juni"; break
   case 7: var m = "Juli"; break
   case 8: var m = "August"; break
   case 9: var m = "September"; break
   case 10: var m = "Oktober"; break
   case 11: var m = "November"; break
   case 12: var m = "Dezember"; break
   default: var m = "Unbekannter Monat"
}
document.write(m)

4.2 Datenspeicherung

Wenn man viele Variablen braucht, oder nicht genau weiß, wie viele Variablen man benötigt, ist das Konzept der Standardvariablen nicht flexibel genug. Beispielsweise sollte man sich bei der Benennung der Variablen schon vorher ein Konzept zurechtlegen, um effizient auf die Variablen zuzugreifen. In diesem Abschnitt werden zwei Möglichkeiten vorgestellt, um mehrere Variablen zu speichern.

4.2.1 Die eval-Methode

Wieder einmal sollen die Monatsnamen gespeichert werden. Anhand der Nummer des Monats soll auf den Monatsnamen zugegriffen werden. Der Variablenname setzt sich aus dem Wort »Monat« und der Zahl zusammen. Die Variablendeklaration sieht also folgendermaßen aus:

var Monat1 = "Januar"
var Monat2 = "Februar"
var Monat3 = "März"
var Monat4 = "April"
var Monat5 = "Mai"
var Monat6 = "Juni"
var Monat7 = "Juli"
var Monat8 = "August"
var Monat9 = "September"
var Monat10 = "Oktober"
var Monat11 = "November"
var Monat12 = "Dezember"

	Die Frage lautet nun: Wenn (beispielsweise in einer Variablen) die Monatsnummer vorliegt, wie erhält man dann daraus den Monatsnamen? Natürlich kann man eine Reihe von if-Anweisungen verwenden oder die switch-Anweisung, die jedoch nur ab der Browser-Version 4 (Netscape Navigator bzw. Internet Explorer) unterstützt wird. Schön wäre es jedoch, wenn man direkt den Variablennamen verwendet. Folgender Code funktioniert natürlich nicht wie beabsichtigt:

document.write("Monat"+monat)

In monat steht die Monatsnummer, aber obige Zeile würde die Zeichenkette "Monat" konkateniert mit der Monatsnummer ausgeben, also den Namen der Variablen, nicht die Variable selbst. JavaScript bietet eine besondere Funktion, die es ermöglicht, Code auszuführen, der als Zeichenkette vorliegt. Diese Funktion heißt eval. Als Parameter wird eine Zeichenkette übergeben, und eval führt den JavaScript-Code aus, der in der Zeichenkette steht. Der folgende Aufruf gibt den Wert der Variablen zurück, nicht ihren Namen:

eval("Monat"+monat)

Will man also den Monatsnamen auf dem Bildschirm ausgeben, kann man folgende Zeile verwenden:

document.write(eval("Monat"+monat))

Alternativ dazu kann der document.write-Befehl auch innerhalb der eval-Klammern geschrieben werden:

eval("document.write(Monat"+monat+")")

Steht in der Variablen monat beispielsweise der Wert 12, so würde der eval-Befehl nach dem Einsetzen der Variablen folgendermaßen aussehen:

eval("document.write(Monat12)")

	Wenn in der Anweisung, die als Parameter an eval() übergeben wird, Anführungszeichen vorkommen, müssen Sie die herkömmlichen Regeln beachten, also entweder andere Anführungszeichen verwenden oder Anführungszeichen mit einem Backslash entwerten. Oft ist es jedoch sinnvoll, den Aufruf von eval() möglichst weit innen zu plazieren.

document.write("Der Monatsname lautet "+eval("Monat"+monat))

4.2.2 Arrays

Die obige Vorgehensweise funktioniert zwar tadellos, ist aber kompliziert, und auch hier werden die Befehle schnell unübersichtlich. In der Praxis werden zumeist sogenannte Arrays verwendet. Das sind Variablencontainer, die mehrere Variablen beinhalten können. Auf eine einzelne Variable im Container greift man über den Variablennamen und eine Nummer zu. Die Nummer nennt man auch Index. Standardmäßig wird ein Array in JavaScript folgendermaßen definiert:

var a = new Array()
a[1] = "Januar"
a[2] = "Februar"
//usw.

Mit der ersten Zeile, var a = new Array(), wird eine Arrayvariable deklariert. Man kann auch einen Parameter übergeben, aber da gibt es je nach JavaScript-Version Unterschiede. Genauere Informationen finden Sie im Referenz-Teil. Kleiner Hinweis am Rande: Wenn man mehr als einen Parameter übergibt, kann man das Array vorbelegen:

var a = new Array("Januar", "Februar", "März")

Der Index, über den auf ein Array-Element zugegriffen wird, steht in eckigen Klammern. JavaScript-Arrays beginnen, wie in vielen anderen Programmiersprachen und in Java übrigens auch, mit 0. Mit obigem Aufruf würde also a[2] auf März gesetzt. Man müsste die Anweisung folgendermaßen modifizieren, damit a[3] den Wert »März« enthält:

var a = new Array("", "Januar", "Februar", "März")

	Leider werden Sie solchen Code nicht auf allen Seiten finden. Das hat historische Gründe: In allen Versionen des Netscape Navigator 2 waren Arrays nicht so. Der Internet Explorer 3 unterstützt auch nur eine Rohform der Arrays. Die Netscape-Entwickler haben das Problem erkannt (aber erst in Browser-Version 3 behoben) und in ihrer Dokumentation eine Möglichkeit vorgestellt, um Arrays auch mit dem Netscape Navigator 2 zu erzeugen. Eine leicht modifizierte Version dieses Codes wird hier vorgestellt.

Zuerst einmal muss man auf allen Seiten, die Arrays verwenden, folgenden Code plazieren:

function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
}

Die exakte Funktionsweise dieses Codes wird teilweise später in diesem Kapitel, teilweise im Kapitel »Arrays« erläutert. Vereinfacht gesagt, kann nun mit MakeArray() ein Array erzeugt werden. Als Parameter wird die Anzahl der Elemente im Array festgelegt. Jedes Element wird mit dem Wert 0 vorbelegt. Außerdem kann man (bei korrekter Verwendung) über Arrayname.length herausfinden, wie viele Elemente das Array überhaupt enthält (wie bei »normalen« Arrays auch). Somit hat man die wichtigsten Funktionalitäten der JavaScript-Arrays nachgebildet.

	Das Beispiel von oben lässt sich nun folgendermaßen darstellen – und diesmal auch auf dem Netscape Navigator 2:

var m = new MakeArray(13)
m[0] = "Unbekannter Monat"
m[1] = "Januar"
m[2] = "Februar"
m[3] = "März"
m[4] = "April"
m[5] = "Mai"
m[6] = "Juni"
m[7] = "Juli"
m[8] = "August"
m[9] = "September"
m[10] = "Oktober"
m[11] = "November"
m[12] = "Dezember"

Beachten Sie, dass das Array 13 Elemente enthalten muss, da (zur besseren Übersichtlichkeit) der Index des entsprechenden Monatsnamens im Array mit der Monatszahl identisch sein soll. Es gibt also 13 Array-Elemente, der Index läuft von 0 bis 12.

Es stellt sich nun natürlich die Frage, ob man Netscape Navigator 2 (und indirekt auch Internet Explorer 3) überhaupt noch explizit unterstützen sollte, da der Anteil dieser Browserim niedrigen einstelligen Bereich liegt. Dennoch stehe ich auf dem Standpunkt, dass man – sofern möglich – abwärtskompatibel programmieren sollte. Auch wenn Benutzer alter Browser im Web sowieso eine Menge Fehlermeldungen gewohnt sind, hebt man sich gerade dann wohltuend von der Masse der Seiten (insbesondere der der Konkurrenten) ab, wenn man Fehlermeldungen möglichst vermeidet. Wenn der Aufwand nicht allzu groß ist (wie in diesem Fall), sollte man die Extra-Arbeit tun, denn ein potentieller Kunde könnte durch eine vermeidbare Fehlermeldung abgeschreckt werden (durch eine unvermeidbare sowieso).

4.3 Funktionen

In diesem Kapitel wird document.write() ziemlich oft eingesetzt. Es gibt jedoch zwei Nachteile dieser Funktion. Zum einen hat der Netscape Navigator 2 einen Bug, der dazu führt, dass ein document.write() innerhalb einer Tabellenzelle ohne Effekt ist (Ausnahme: Wenn die gesamte Tabelle mit document.write() erzeugt worden ist). Der zweite Nachteil ist ein (nicht auf document.write() beschränkter) Fehler im Netscape Navigator 3. Anweisungen der folgenden Art tauchen relativ oft auf:

document.write("<P>Winnie Pooh</P>")

Oft enthält die Zeichenkette noch weitaus mehr HTML-Tags. Der Netscape Navigator 3 kommt hierbei häufig durcheinander und gibt – trotz eigentlich korrektem Programmcode – eine Fehlermeldung aus. Abhilfe schaffen Sie hier, indem Sie nicht den gesamten Tag verwenden, sondern zumindest die spitzen Klammern als einzelne Zeichenketten behandeln und diese dann mit dem Plus-Operator konkatenieren:

document.write("<"+"P"+">"+"Winnie Pooh"+"<"+"/P"+">")

Bei vielen Anweisungen ist das recht aufwendig, vor allem die Tipparbeit verlangt viel Zeit und Konzentration. Hier kann man sich mit Funktionen behelfen. Unter einer Funktion versteht man einen Programmblock, der nicht sofort ausgeführt wird, aber explizit auf- bzw. abgerufen werden kann. So eine Funktion führt entweder ein paar Befehle aus (dann nennt man sie mitunter auch eine Prozedur), oder es wird ein Wert zurückgegeben. Eine Prozedur ist mit document.write() vergleichbar, während eine Funktion beispielsweise Zeichenkette.length entspricht.

Eine Funktion hat folgende Syntax:

function Funktionsname(Parameter1, Parameter2){
   //Programmblock
   return Wert
}

Die Anzahl der Parameter ist beliebig. Es kann auch kein Parameter verwendet werden (dann ist die Klammer leer). Innerhalb der Funktion können die Parameter dann unter dem Namen angesprochen werden, unter dem sie im Funktionskopf eingeführt wurden.

Die Zeile mit dem return ist optional. Der Befehl return sorgt dafür, dass die Funktion sofort verlassen wird (wie break). Wird hinter dem return ein Wert angegeben, so ist dieser der Rückgabewert der Funktion.

Im Gegensatz zu manchen anderen Programmiersprachen muss die Funktion nicht vor ihrem ersten Aufruf deklariert werden. Erkennt der JavaScript-Interpreter, dass ein Funktionsaufruf vorliegt, so wird das Dokument nach einer Funktion dieses Namens durchsucht.

Diese theoretische Einleitung soll anhand von praktischen Beispielen verdeutlicht werden. Prinzipiell geht es darum, dass an eine Funktion der Name eines Tags übergeben wird (beispielsweise "P" oder "FONT"), und die Funktion dann entweder den Tag ausgibt (mit den dazugehörigen spitzen Klammern) oder den Tag als Zeichenkette zurückgibt. Somit wird auch das obengenannte Problem mit den spitzen Klammern gelöst.

Die erste Variante gibt den entsprechenden Tag direkt mittels document.write() aus.

function tag_ausgeben(s){
   document.write("<"+s+">")
}
//Test-Aufruf
tag_ausgeben("P")
document.write("Winnie Pooh")
tag_ausgeben("/P")

In der zweiten Variante wird der return-Befehl verwendet. Die Funktion gibt also nichts direkt aus, sondern liefert einen Wert zurück, der dann im eigentlichen Programm weiterverwendet werden kann.

function tag(s){
   return "<"+s+">"
}
document.write(tag("P")+"Winnie Pooh"+tag("/P"))

Es sind noch zwei Fälle möglich:

	Es werden weniger Parameter übergeben, als im Funktionsrumpf angegeben sind.
	Es werden mehr Parameter übergeben, als im Funktionsrumpf angegeben sind.

Der erste Fall lässt sich recht schnell abhandeln. In diesem Fall hat der entsprechende Parameter den Wert null. Die Funktion tag() kann also erweitert werden, so dass eine leere Zeichenkette zurückgegeben wird, wenn kein Parameter übergeben worden ist:

function tag(s){
   if (s==null)
      return ""
   else
      return "<"+s+">"
}

Der zweite Fall ist nicht ganz so einfach. Die gute Nachricht vorweg: Alle Parameter, die an eine Funktion übergeben werden, sind in einem Array gespeichert. Es ist jedoch noch nicht intuitiv einsichtig, wie auf dieses Array zugegriffen werden kann. Der entsprechende Bezeichner heißt Funktionsname.arguments – und hier sehen Sie gleich direkt, dass man als JavaScript-Funktionsnamen keine reservierten Begriffe (etwa document, write etc.) verwenden darf.

Die folgende Funktion gibt gleich eine ganze Liste von Tags aus. In einer for-Schleife wird das Array arguments durchlaufen, und alle Werte werden mit spitzen Klammern ausgegeben. Wie bereits oben angemerkt, kann mit Arrayname.length die Anzahl der Elemente des Arrays bestimmt werden; in obigem Fall also Funktionsname.arguments.length!

function tag(){
   var returnstring = ""
   for (var i=0; i<tag.arguments.length; i++)
      returnstring += "<"+tag.arguments[i]+">"
   return returnstring
}

Der Aufruf

tag("FONT SIZE='2'", "FONT FACE='Arial'", "B")

würde also folgende Zeichenkette als Ergebnis erhalten:

"<FONT SIZE='2'><FONT FACE='Arial'><B>"

Natürlich gibt es sinnvollere Einsatzgebiete für eine Funktion als Workarounds für Netscape-Bugs bereitzustellen. Kommen wir noch einmal zu Schleifen zurück. Es war ja immer etwas umständlich, ein Zeichen durch ein anderes auszutauschen. Mit einer Funktion kann man das ganze etwas übersichtlicher gestalten:

function ersetzeZeichen(Zeichenkette, Position, Neu){
   //Zeichenkette ist die betrachtete Zeichenkette
   //Position ist die Pos. des Zeichens, das ersetzt wird
   //Neu ist das neue Zeichen
   var neueZ = Zeichenkette.substring(0, Position)
   neueZ += Neu
   neueZ += Zeichenkette.substring(Position+1, Zeichenkette.length)
   return neueZ
}

Bei der Wahl der Variablennamen muss man Vorsicht walten lassen. Existiert die Variable auch außerhalb der Funktion, so wird keine neue Variable erzeugt, sondern auf die alte Variable zugegriffen. Umgekehrt kann man auf Variablen, die nur innerhalb einer Funktion auftreten, nicht von außen zugreifen. Man unterscheidet hier in globale (außerhalb und innerhalb einer Funktion gültig) und lokale (nur innerhalb von Funktionen gültig) Variablen. Will man innerhalb einer Funktion eine lokale Variable erzeugen, deren Name schon eine globale Variable trägt, so muss man der ersten Verwendung ein var voranstellen.

Folgendes Beispiel verdeutlich das eben Gesagte:

var a=0
var b=0
function test(){
   a++  //Zugriff auf globale Variable a
   var b=1  //Neue lokale Variable
            //hat mit der globalen Variablen b nichts zu tun
   var c=0  //Neue lokale Variable
}

4.4 Objekte

Objektbasiert

JavaScript gehört zu den sogenannten objektorientierten Programmiersprachen (oder, um genauer zu sein, zu den objektbasierten Sprachen). Das Konzept der objektorientierten Programmierung (OOP) wird im folgenden sehr stark vereinfacht erklärt. Der interessierte oder vorgebildete Leser möge diese Vereinfachung verzeihen, aber für das Verständnis von JavaScript ist nur ein gewisser Überblick über das Konzept der Objektorientierung in JavaScript nötig.

In JavaScript ist (mit Ausnahme der Variablen) alles, worauf man zugreift, ein Objekt. Ein Objekt ist der Versuch, die reale Welt in eine Programmiersprachenumgebung abzubilden. Ein Standardbeispiel für Objekte ist etwa ein Auto. Das Auto an sich (als abstrakter Begriff) kann als Objekt angesehen werden, ein einzelnes Auto wird als Instanz des Objekts //Auto// bezeichnet. Sie haben so etwas in diesem Kapitel schon einmal gesehen – Array ist so ein Objekt, und mit new Array() wird eine Instanz des Array-Objekts, also ein konkretes Array erzeugt.

Ein Auto, oder ein Objekt im allgemeinen, wird durch gewisse Parameter spezifiziert. Bei diesen unterscheidet man Methoden und Eigenschaften.

	Eine Eigenschaft kann als Variable angesehen werden, also als ein Wert, der fest mit dem Objekt verbunden ist und gelesen und geschrieben (gesetzt) werden kann. Bei einem Auto ist das beispielsweise die aktuelle Geschwindigkeit oder die aktuelle Menge Benzin im Tank. Eine Eigenschaft kann mit einem Funktionsaufruf verglichen werden, der immer einen Wert zurückgibt.
	Eine Methode ist eine Funktion, die ebenfalls fest mit dem Objekt verbunden ist. Im Gegensatz zur Eigenschaft wird hier aber nicht immer ein Wert zurückgegeben. Um auf das Auto-Beispiel zurückzukommen: Eine mögliche Methode wäre eine Methode vollbremsung(), die die (Eigenschaft) Geschwindigkeit abrupt auf 0 setzt. Eine andere Möglichkeit wäre eine Methode beschleunigen(); je nach Definition könnte man als Parameter angeben, auf welche Geschwindigkeit oder um wieviel Stundenkilometer die Geschwindigkeit erhöht werden soll. An der Schreibweise sieht man schon eine verwendete Konvention: Methoden werden immer durch nachgestellte Klammern gekennzeichnet; dies soll verdeutlichen, dass es sich hier nicht um eine Eigenschaft, sondern um einen »echten« Funktionsaufruf handelt.

Wie Sie vielleicht schon bei den vorherigen Beispielen in diesem Kapitel gesehen haben, ruft man eine Eigenschaft oder eine Methode auf, indem man den Namen des entsprechenden Objekts nimmt und den Namen der Methode oder Eigenschaft mit einem Punkt anhängt. Methoden werden dabei immer mit Klammern geschrieben; sollten keine Parameter übergeben werden, so werden leere Klammern verwendet. Bei Eigenschaften werden keine Parameter übergeben. Um auf die vorherigen Beispiele zurückzukommen: document.write() ist eine Methode des document-Objekts, Arrayname.length ist eine Eigenschaft des Array-Objekts.

In den folgenden Kapiteln werden Sie nach und nach alle JavaScript-Objekte kennenlernen. Einige davon, wie beispielsweise das Array-Objekt, erleichtern die Programmierung, haben aber mit Webseiten nichts zu tun. Man kann von diesen Objekten Instanzen erzeugen und diese dann verwenden. Andere Objekte wiederum, wie beispielsweise die Objekte window, document oder location, haben dagegen direkt etwas mit der entsprechenden Webseite zu tun und enthalten beispielsweise Informationen über die URL der aktuellen Seite oder die Anzahl der Links im HTML-Dokument. In den nächsten Kapitel werden diese Objekte an praxisnahen Beispiele vorgeführt.

Wenn Sie eigene Objekte erstellen möchten, sollten Sie das Kapitel »Arrays« lesen, dort wird dies an einem Beispiel durchexerziert. Im Praxiseinsatz werden Sie – vor allem bei »Standardaufgaben« – eher selten selbst Objekte erstellen, aber bei größeren Projekten ist das mitunter sehr nützlich.

4.5 Fragen & Aufgaben

1.	Schreiben Sie das Beispiel mit den Monatsnamen derart um, dass nicht der Name des aktuellen Monats ausgegeben wird, sondern der des Folgemonats.
2.	Wie Aufgabe 1, nur verwenden Sie weder Arrays noch if-Abfragen.
3.	Schreiben Sie eine Funktion istSchaltjahr(n), die angibt, ob n ein Schaltjahr ist oder nicht (Tip: Modulo-Operator verwenden!). Zusatzaufgabe: Versuchen Sie auch hier, ohne if-Abfragen auszukommen.
4.	Schreiben Sie eine Funktion istPrim(n), die angibt, ob n eine Primzahl2 ist.
5.	Ist die Funktion zum Ausgeben von modalen Hinweisfenstern (Warnfenstern), die Sie im Kapitel »Vorbereitung« kennengelernt haben, eine Methode, eine Eigenschaft oder keins von beiden? Geben Sie eine Begründung an!
6.	Versuchen Sie, die Funktion MakeArray() so umzuschreiben, dass ein optionaler zweiter Parameter unterstützt wird, der den Initialwert für jedes Arrayfeld angibt. Sie müssen dazu unter anderem die Zeile ändern, in der allen Array-Elementen der Wert 0 zugewiesen wird.

1    Das ist gleichzeitig auch ein Nachteil – bei obigem Code werden für jeden Wert von monat 12 Überprüfungen durchgeführt.

2    Eine Primzahl ist nur durch zwei verschiedene Zahlen ohne Rest teilbar: durch eins und sich selbst. Daraus folgt, dass eins selbst keine Primzahl ist.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 5 Erste Schritte
			5.1 JavaScript-Objekte
			5.2 Browser-Erkennung
			5.3 Event-Handler
			5.4 Fragen & Aufgaben

Kapitel 5 Erste Schritte

Der schwerste Anfang ist der Anfang vom Ende

– Hans-Helmut Dickow

Ziel dieses Kapitels ist, einige erste Grundtechniken vorzustellen, die Sie in den folgenden Kapiteln benötigen. Beispielsweise wird gezeigt, wie der Browser des Benutzers erkannt werden kann und wie bestimmte Browser auf bestimmte Seiten weitergeleitet werden können. Außerdem werden öfter benötigte mathematische Methoden, wie etwa die Rundungsfunktion oder die Generierung von Zufallszahlen, vorgeführt, und das sogar an einem praxisnahen Beispiel. Zu guter Letzt erhalten Sie eine Übersicht über die häufigsten Event-Handler von JavaScript. Damit nähern Sie sich schon stark der JavaScript-Programmierung im Produktivbetrieb, und im nächsten Kapitel, »Fenster I«, wird direkt in die Materie eingestiegen.

5.1 JavaScript-Objekte

Wie bereits im vorherigen Kapitel angekündigt, gibt es in JavaScript einige Objekte, die einem die Programmierung erleichtern, so zum Beispiel das Array-Objekt. In diesem Abschnitt werden zwei weitere Objekte anhand eines kurzen Beispiels vorgestellt, die Objekte Date (für Datumsfunktionen) und Math (für mathematische Berechnungen).

5.1.1 Das Objekt Date

Bei dem Date-Objekt handelt es sich um ein Objekt, von dem man eine Instanz erzeugen kann, und zwar – analog zu Arrays – folgendermaßen:

var d = new Date()

Die Variable d ist eine Datumsvariable und enthält das aktuelle Datum (inklusive Uhrzeit) auf dem lokalen Rechner (nicht auf dem Server), und zwar das Datum zu dem Zeitpunkt, zu dem die Instanz erzeugt worden ist. Wenn also nach der Generierung der Variablen d eine lange Schleife folgt, die mehrere Sekunden dauert, ändert d seinen Wert nicht.

Bei der Erzeugung der Instanz kann man die Datumsvariable auch direkt mit (anderen) Werten belegen. Dazu gibt es zwei Möglichkeiten:

var d = new Date(Jahr, Monat, Tag)

bzw.

var d = new Date(Jahr, Monat, Tag, Stunde, Minute, Sekunde)

	Bitte beachten Sie untenstehende Hinweise, insbesondere die für den Monatswert!

Man kann mit geeigneten Methoden den Wert der Variablen d ändern, beispielsweise Tag, Monat und Jahr. Natürlich hat das überhaupt keine Auswirkung auf die Systemzeit des Clients oder des Servers, das wäre ja aus Sicherheitsgründen völliger Wahnsinn, sondern lediglich der Wert der Variablen ändert sich.

Zu den Standardanwendungen des Date-Objekts gehören die Anzeige des aktuellen Datums sowie die Berechnung, wie viel Zeit zwischen zwei Daten liegt. Im folgenden sollen diese beiden Möglichkeiten anhand von Beispielen erläutert werden.

Tagesdatum

Hat man erst einmal eine Instanz des Date-Objekts erzeugt, kann man das genaue Datum mit entsprechenden Methoden abfragen. Wie unter UNIX generell üblich, speicherte JavaScript 1.0 jedes Datum als die Anzahl der Millisekunden seit dem 1. Januar 1970; in neueren Versionen ist das nicht mehr so. Da es ein wenig aufwendig wäre, aus diesem Wert die interessanteren Daten wie etwa die Jahreszahl herauszufinden, gibt es hierfür vorgefertigte Methoden. Eine komplette Liste befindet sich in der Referenz, in Tabelle 5.1 finden Sie lediglich die wichtigsten Methoden.

Tabelle 5.1  Die wichtigsten Methoden des Date-Objekts

Methode	Beschreibung
getDate()	Aktueller Tag der Datumsvariablen (1..31)
getMonth()	Aktueller Monat der Datumsvariablen minus Eins (0..11)
getYear()	Aktuelles Jahr der Datumsvariablen; für Wertebereich siehe Abschnitt »Y2K«
getHours()	Aktuelle Stunde der Datumsvariablen (0..23)
getMinutes()	Aktuelle Minute der Datumsvariablen (0..59)
getSeconds()	Aktuelle Sekunde der Datumsvariablen (0..59)
getMilliseconds()	Aktuelle Millisekunden der Datumsvariablen (0..999)

Hiermit ist es recht einfach, das aktuelle Datum auszugeben. Will man auf Monatsnamen nicht verzichten, muss man diese wieder in einem Array speichern:

<HTML>
<HEAD>
<TITLE>Tagesdatum</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var monatsnamen = new MakeArray(12)
monatsnamen[0] = "Januar"; monatsnamen[1]="Februar"
monatsnamen[2] = "März"; monatsnamen[3]="April"
monatsnamen[4] = "Mai"; monatsnamen[5]="Juni"
monatsnamen[6] = "Juli"; monatsnamen[7]="August"
monatsnamen[8] = "September"; monatsnamen[9]="Oktober"
monatsnamen[10] = "November"; monatsnamen[11]="Dezember"
function tagesdatum(){
   var d = new Date()
   var datumsstring = d.getDate()
   datumsstring += "."+monatsnamen[d.getMonth()]
   datumsstring += "."+d.getYear()
   document.write(datumsstring)
}
function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Tagesdatum</H3>
Guten Tag, heute ist der
 <SCRIPT LANGUAGE="JavaScript"><!--
 tagesdatum()
 //--></SCRIPT>
!
</BODY>
</HTML>

Y2K

Auch JavaScript ist vom ominösen Jahr-2000(Y2K-)Problem betroffen, allerdings ist das hier nicht so schlimm wie in weiten Teilen der Wirtschaft. Probleme bereiten hier (natürlich) wieder ältere Browser, insbesondere der Netscape Navigator 2 und zum Teil der Internet Explorer 3. Die Crux liegt in der Methode getYear(). Je nach Browser werden manche Jahre anders interpretiert. Tabelle 5.2 zeigt auf, welche Rückgabewerte die verschiedenen Browser bei den jeweiligen Zeiträumen haben. Dabei bedeutet »volle Jahreszahl« eine vierstellige Jahreszahl (außer natürlich bei Jahreszahlen vor 1000); »kurze Jahreszahl« bedeutet eine zweistellige Jahreszahl im 20. Jahrhundert, also etwa »99« statt »1999«.

Tabelle 5.2  Die Jahreszahlbehandlung der verschiedenen JavaScript-Versionen

Zeitraum	JS 1.0	JS 1.1/1.2	JS 1.3 und höher
<1970	Nicht unterstützt	Volle Jahreszahl	Jahreszahl minus 1900 (1800 wird durch -100 dargestellt)
1970..1999	Jahreszahl minus 1900	Kurze Jahreszahl	Jahreszahl minus 1900
³ 2000	Jahreszahl minus 1900	Volle Jahreszahl	Jahreszahl minus 1900

Tabelle 5.2 wirkt erschreckend, aber in der Praxis kann man relativ einfach einen Ausweg finden. Üblicherweise liegen alle verwendeten Daten im Bereich von 1970 bis ins 21. Jahrhundert hinein. Eine Jahreszahl kleiner als 200 ist also um 1900 zu niedrig; andere Jahreszahlen sind – nehmen wir einfach einmal an – korrekt. Man kann also eine Funktion schreiben, die das Y2K-sichere Jahr zurückgibt:

function getYearY2K(d){
   var y = d.getYear()
   if (y<200)
      return y+1900
   else
      return y
}

	Ab JavaScript 1.3 (also insbesondere ab Netscape Navigator 4.06) gibt es eine Methode getFullYear(), die grundsätzlich kein verkürztes Datum zurückgibt, sondern stets die volle Jahreszahl. Alle Browser, die ab dem heutigen Zeitpunkt erscheinen, sollten diese Methode unterstützen. Bis jedoch die Verbreitung dieser Browser so groß ist, dass man den »zurückgebliebenen Rest« vernachlässigen kann, muss noch einige Zeit vergehen. Aus diesem Grund sollten Sie sich noch eine Zeitlang mit getYearY2K() begnügen. Eine Alternative besteht darin, ein eigenes Datumsobjekt zu schreiben; das nötige Rüstwerkzeug bekommen Sie im Kapitel »Arrays«.

Mit Daten rechnen

In JavaScript Version 1.0 wurden Datumswerte intern als Zahl der seit dem 1. Januar 1970 verstrichenen Millisekunden gespeichert. Diese auf den ersten Blick merkwürdig anmutende Vorgehensweise bietet einen großen Vorteil: Rechenoperationen werden dadurch ermöglicht, die ansonsten nur sehr schwer und kompliziert zu implementieren gewesen wären.

Die Hauptanwendung ist hier die Berechnung der Differenz zweier Datumswerte. Wie viele Tage oder Stunden dauert es noch bis zum 1.1.2001? Wie viele Tage bin ich alt? Um wie viele Stunden ist mein Bruder/meine Schwester/mein Hund älter/jünger?

Sie nutzen dazu die Methode getTime() und ganz wenig Mathematik. Die Methode getTime() gibt die Zeit in der Datumsvariablen im Format »Millisekunden seit 1.1.1970« zurück. Wenn zwei Datumsvariablen vorliegen, deren zeitliche Differenz berechnet werden muss, so kann der Millisekundenwert beider Variablen voneinander abgezogen werden, und man hat das Ergebnis. Dieses liegt dann zwar in Millisekunden vor, aber die Umrechnung in handlichere Werte ist recht einfach. Eine Division durch 1 000 ergibt Sekunden (eine Sekunde dauert 1 000 Millisekunden); 1 000 ¥ 60 ergibt die Minuten (analog: 60 Sekunden sind eine Minute) und so fort. Die Division durch 1 000 ¥ 60 ¥ 60 ¥ 24 gibt die Zeit in Tagen an.

Noch wissen Sie nicht, wie man Benutzereingaben mit JavaScript abfängt; aus diesem Grund muss im folgenden Beispiel zum Testen an einer Variablen »herumgeschraubt« werden. Das Beispiel mit den Geburtsdaten ist heikel, wenn man vor dem 1. Januar 1970 geboren ist (aus Gründen der Abwärtskompatibilität), also wird nun die zeitliche Differenz des aktuellen, lokalen Datums zum »echten« Jahrtausendwechsel, also dem 1.1.2001, berechnet:

<HTML>
<HEAD>
<TITLE>Jahrtausendwechsel</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var d = new Date(89, 9, 3)  //3.10.1989
var d2 = new Date(2001, 0, 1)  //1.1.2001
function differenz(){
   var dtime = d.getTime()
   var d2time = d2.getTime()
   var diff = d2time – dtime
   var diffstring = (diff/1000) + " Sekunden"
   diffstring += " oder " + (diff/(1000*60)) + " Minuten"
   diffstring += " oder " + (diff/(1000*60*60)) + " Stunden"
   diffstring += " oder " + (diff/(1000*60*60*24)) + " Tage"
   document.write("Zeitunterschied: " + diffstring)
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Zeitunterschied</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
   differenz()
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 5.1  So viel Zeit vergeht noch bis zum 1. Januar 2001

Lokales Datumsformat

Mit der Methode toLocaleString() können Sie einen Datumswert an die lokalen Einstellungen (das heißt, Sprachversion des Betriebssystems und lokale Spracheinstellungen) anpassen. So recht funktionieren will das aber erst mit dem Internet Explorer 5.5, der die entsprechenden Informationen direkt aus den Daten in der Systemsteuerung holt (unter Windows, bei anderen Betriebssystemen stehen diese Informationen an anderer Stelle). In Tabelle 5.3 sehen Sie, wie drei Browserversionen das aktuelle Datum nach Anwendung von toLocaleString() ausgeben – bei identischen Einstellungen in der Systemsteuerung.

Tabelle 5.3  Die Ergebnisse von toLocaleString()

Browser	Ausgabe (am 31. Dezember 2000, 12 Uhr mittags)
Netscape Navigator 4.7x	Sunday, December 31, 2000 12:00:00
Internet Explorer 5.0x	12/31/2000 12:00:00
Internet Explorer 5.5	Sonntag, 31. Dezember 2000 12:00:00

5.1.2 Das Objekt Math

Mit diesem Objekt, von dem man im übrigen keine Instanz erzeugen muss, können mathematische Berechnungen ausgeführt werden. Dabei spreche ich nicht von elementaren Funktionen wie etwa den vier Grundrechenarten (die, wie bereits bekannt, durch entsprechende Operatoren abgedeckt sind), sondern von den trigonometrischen Funktionen (Sinus, Kosinus etc.) oder den Exponentialfunktionen (x »hoch« y, Logarithmus etc.). In der Praxis kommen diese Funktionen jedoch eher selten vor, weswegen hier auf die Referenz verwiesen wird. Viel interessanter ist da schon die Generierung von Zufallszahlen.

Zeitbasierender Zufall

Auch wenn sporadisch auftretende Systemabstürze das Gegenteil vermuten lassen, ist im Computerbereich eigentlich nichts richtig zufällig. Oft jedoch will man seinem Besucher das Element Zufall bieten, beispielsweise könnte man sich einen zufälligen Link vorstellen. Eine Reihe von Links wird (beispielsweise in einem Array) gespeichert, und wenn ein Besucher die Seite aufruft, wird ein Link »zufällig« ausgewählt und angezeigt. Das »zufällig« ist aber hier ein Problem: Ein Computer kann keine Zufälle produzieren, er kann nur berechnen.

Aus diesem Grund muss man einen kleinen Umweg einschlagen und ein mehr oder minder zufälliges Element in die Berechnung bringen. Ein gutes Beispiel hierfür ist das aktuelle Datum (im bekannten Format »Millisekunden seit 1.1.1970«). Diese Zahl ist zumindest einigermaßen zufällig und schwer zu beeinflussen. Hat man etwa sechs Links zur Auswahl, so könnte man den Sechserrest der aktuellen Zeit (also den Rest einer Division durch sechs, eine Zahl zwischen 0 und 5) verwenden, um einen Link mehr oder minder zufällig auszuwählen.

Aus Gründen der Browserkompatibilität empfiehlt es sich, die aktuelle Zeit zuerst durch zehn zu teilen und das Ergebnis dann zu runden, weil der Internet Explorer 3 gern nur durch zehn teilbare Zeitwerte ausspuckt. In diesem Falle wären mögliche Sechserreste nur die Zahlen 0, 2 und 4, was die Auswahl der Links halbiert.

Zum Runden verwendet man die Funktion Math.round(), die den übergebenen Parameter rundet, wie Sie es in der Schule gelernt haben: Ab 0,5 wird aufgerundet, davor abgerundet. Alternativ können Sie auch Math.ceil() verwenden, das aufrundet, oder Math.floor(), das abrundet.

Der folgende Code ist zweigeteilt. Am Anfang stehen Variablen wie etwa die Links, die leicht angepasst werden können, mitunter auch von Leuten, die sich in JavaScript nicht so gut auskennen. Der zweite Teil enthält das eigentliche Programm. Dieses Vorgehen hat den Vorteil, dass der Pflegeaufwand für die Seite nicht mehr so hoch ist, da auch andere Leute Rahmenparameter anpassen können, ohne dass Sie Angst haben müssen, dass in Ihrer Programmierung herumgepfuscht wird.

<HTML>
<HEAD>
<TITLE>Zufallslink</TITLE>
</HEAD>
<BODY>
<H3>Zufallslink</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
var urls = new MakeArray(3)
urls[0] = "http://www.galileo-press.de"
urls[1] = "http://www.spiegel.de"
urls[2] = "http://www.muelltonne.de"
// ab hier: nichts mehr verändern! – Der Webmaster
var d = new Date()
var t = d.getTime()
t = Math.round(t/10)  //durch 10 teilen und runden
var zufallsurl = urls[t % 3]
document.write(tag("A HREF='"+zufallsurl+"'"))
document.write(zufallsurl)
document.write(tag("/A"))
// Funktionen
function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
}
function tag(s){ return "<"+s+">" }
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 5.2  Ein zufälliger Link

Eingebauter Zufall

Den obigen Aufwand muss man zum Glück nicht treiben. Das Math-Objekt hat auch die Methode random(), die eine Zufallszahl zwischen 0 und 1 zurückliefert:

var z = Math.random()

Natürlich verwendet der Netscape Navigator auch einen Berechnungsalgorithmus für die Erzeugung der »Zufallszahl«, und auch dieser Algorithmus ist von der aktuellen Zeit abhängig. Auf den ersten Blick ist diese Zahl jedoch nicht besonders nützlich, da beispielsweise in obiger Anwendung eine Zahl zwischen null und fünf benötigt wird. Mit einem kleinen Trick kann man sich aber hier behelfen. Wird nämlich die Zufallszahl mit sechs multipliziert und dann abgerundet, so erhält man eine ganze Zahl zwischen null und fünf:

var z = Math.floor(6*Math.random())

Allgemein kann man das auch in einer Funktion schreiben. Die Funktion random2(n) erzeugt eine ganze Zahl zwischen 0 und n:

function random2(n){
   return Math.floor((n+1)*Math.random())
}

Hiermit kann das Beispiel mit dem Zufallslink umgeschrieben werden:

<HTML>
<HEAD>
<TITLE>Zufallslink</TITLE>
</HEAD>
<BODY>
<H3>Zufallslink</H3>
 <SCRIPT LANGUAGE="JavaScript"><!--
var urls = new MakeArray(3)
urls[0] = "http://www.galileo-press.de"
urls[1] = "http://www.spiegel.de"
urls[2] = "http://www.muelltonne.de"
// ab hier: nichts mehr verändern! -Der Webmaster
var zufallsurl = urls[random2(3)]
document.write(tag("A HREF='"+zufallsurl+"'"))
document.write(zufallsurl)
document.write(tag("/A"))
// Funktionen
function random2(n){
   return Math.floor((n+1)*Math.random())
}
function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
}
function tag(s){ return "<"+s+">" }
//--></SCRIPT>
</BODY>
</HTML>

	Dieses Vorgehen hat leider auch einen kleinen Nachteil: Die Funktion Math.random() ist beim Netscape Navigator 2 ausschließlich in der Unix-Version implementiert.

5.2 Browser-Erkennung

Während des gesamten Buchs werde ich mich über die Inkompatibilitäten der Browser beschweren und Sie beschwören, diese immer zu berücksichtigen, um nicht aus reiner Faulheit und/oder Arroganz einen möglichen Kunden zu verlieren. Oft werden Alternativen zu inkompatiblen Methoden angeboten, so dass gewisse Features auch auf möglichst vielen Browsern laufen. In diesem Abschnitt wird eine andere Lösung aufgezeigt. Man kann nämlich versuchen, den Browser-Typ und die Browser-Version des Benutzers zu erkennen und gewisse Browser auf spezielle Seiten, die für diesen Browser »optimiert« (ein schreckliches Wort) worden sind, umzuleiten. Wenn Sie also auf Ihren Seiten die neuesten Effekte verwenden, sollten Sie auf Ihrer Homepage den Browser des Besuchers erkennen und nur Nutzer mit neuen Browsern auf Ihre effektbeladene Seite weiterleiten; der Rest darf eine schlankere, kompatiblere Version der Seiten (die Sie hoffentlich erstellt haben!) betrachten.

Die Browser-Erkennung wurde mittlerweile von Netscape praktisch perfektioniert; der »Client Sniffer« ist weit bekannt und erkennt fast alle Unterversionen der meisten bekannten JavaScript-fähigen Browser. In der Praxis braucht man das freilich nicht so genau. Oft kann man abfragen, ob ein Browser ein Objekt unterstützt (dazu in späteren Kapiteln mehr), oder es gibt eine Möglichkeit, die Funktionalität auch mit der Urversion, also JavaScript 1.0, nachzubilden (siehe beispielsweise Arrays). Ebenso kann man mit den verschiedenen Werten für das LANGUAGE-Attribut des <SCRIPT>-Tags operieren. Wenn man jedoch mehrere Seiten in seiner Anwendung hat, die erst ab JavaScript 1.1 funktionieren, und man dann Benutzer älterer Browser schon auf der (JavaScript 1.0-kompatiblen) Homepage auf einen alternativen, schlankeren Bereich weiterleiten will, kann sich eine Browser-Erkennung lohnen. Star Division setzt so etwas beispielsweise ein – ohne jedoch eine schlankere Version der Seiten parat zu haben.

Für die Erkennung der Browser-Version gibt es ein eigenes Objekt, navigator. Man braucht davon keine Instanz zu erzeugen, sondern kann direkt darauf zugreifen. Das Objekt hat drei interessante Eigenschaften. Bei zwei Browsern, einem Netscape 4.75 unter Windows 98 und einem Internet Explorer 5.01 unter Windows 95, haben diese Eigenschaften die in Tabelle 5.4 aufgeführten Werte:

Tabelle 5.4  Werte des navigator-Objekts bei zwei exemplarischen Browsern

Eigenschaft	Netscape 4.75 deutsch	Internet Explorer 5.01 deutsch
navigator.appName	Netscape	Microsoft Internet Explorer
navigator.userAgent	Mozilla/4.75 [de] (Win98; U)	Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)
navigator.appVersion	4.75 [de] (Win98; U)	4.0 (compatible; MSIE 5.01; Windows 98)

Sie sehen insbesondere, dass man eigentlich mit navigator.appName schon einmal zwischen Netscape und Internet Explorer unterscheiden kann. Doch leider haben einige frühere Versionen des Internet Explorer als navigator.appName auch Netscape angegeben. Daher muss man auf navigator.userAgent zurückgreifen. Diese Eigenschaft hat den Aufbau Mozilla/Versionsnummer, und dahinter plattformspezifische Informationen. Bei der Versionsnummer ist der Internet Explorer so ehrlich und gibt (in vielen Versionen) zu, meistens in Sachen JavaScript eine Version hinter dem Netscape-Pendant zurückzuliegen. Der Internet Explorer 5 ist in Sachen JavaScript in etwa auf Höhe des Netscape Navigator 4, also fängt navigator.userAgent mit Mozilla/4.0 an. Insbesondere kann man also von der Zeichenkette hinter Mozilla/ keine direkten Rückschlüsse auf die Browserversionsnummer ziehen!

Ausführliche Informationen zur Browser-Erkennung finden Sie unter http://devedge.netscape.com/docs/examples/javascript/browser_type.html. In diesem Abschnitt werden nur die Versionsnummern von Netscape Navigator und Internet Explorer bestimmt. Unter der angegebenen URL finden Sie noch detailliertere Informationen, auch für Browser wie etwa Opera.

Wann ist es Netscape?

Wie Sie bereits gesehen haben, kann man mit navigator.appName nicht auf den Browser-Hersteller schließen, auch nicht dann, wenn navigator.userAgent mit Mozilla beginnet. Statt dessen muss man zusätzlich feststellen, ob man nicht einen anderen Browser hat. Andere Browser erkennt man an den folgenden Kriterien:

	navigator.userAgent enthält die Zeichenkette compatible (typisch für Internet Explorer).
	navigator.userAgent enthält die Zeichenkette Opera (Opera-Browser).
	navigator.userAgent enthält die Zeichenkette WebTV (WebTV-Browser).

Da es zwischen Groß- und Kleinschreibung Unterschiede geben kann, empfiehlt es sich, vor den Überprüfungen navigator.userAgent in Kleinbuchstaben umwandeln. Hierzu verwendet man die Methode Zeichenkette.toLowerCase().

var ua = navigator.userAgent.toLowerCase()
var netscapebrowser = (ua.indexOf("mozilla")!=-1 &&
ua.indexOf("compatible")==-1 && ua.indexOf("opera")==-1)

Wann ist es der Internet Explorer?

Der Internet Explorer ist viel einfacher zu erkennen. Wie Sie bereits gesehen haben, schreibt der Internet Explorer in navigator.userAgent seine Versionsnummer in der folgenden Form: MSIE Versionsnummer. Es muss also einfach das Vorhandensein der Zeichenkette MSIE geprüft werden, bzw. nach der Umwandlung in Kleinbuchstaben, die Existenz der Zeichenkette msie:

var ua = navigator.userAgent.toLowerCase()
var netscapebrowser = (ua.indexOf("mozilla")>-1 &&
ua.indexOf("compatible")==-1 && ua.indexOf("opera")==-1)
var iebrowser = (ua.indexOf("msie")>-1)

Versionsnummer erkennen

Die Eigenschaft navigator.appVersion enthält die Zeichenkette nach Mozilla/ aus navigator.userAgent, zumindest für Netscape-Browser. Es gibt hier zwei Möglichkeiten, um die Versionsnummer herauszubekommen. Die Erste besteht darin, die Versionsnummer aus navigator. appVersion herauszuschneiden (die Versionsnummer endet vor dem ersten Leerzeichen), und dann mit eval() oder mit einer Multiplikation mit 1 in eine numerische Variable umzuwandeln:

var ua = navigator.userAgent.toLowerCase()
var netscapebrowser = (ua.indexOf("mozilla")!=-1 &&
ua.indexOf("compatible")==-1 && ua.indexOf("opera")==-1)
var iebrowser = (ua.indexOf("msie")>-1)
var av = navigator.appVersion
var version = av.substring(0, av.indexOf(" ")) *1
var version2 = av.substring(0, av.indexOf(".")) *1

In der Variablen version2 wird die Versionsnummer vor dem Punkt gespeichert, also im obigen Beispiel jeweils 4.

Hinweis

Der Netscape 6 meldet sich mit Versionsnummer 5.0. Da es keine Version Netscape 5 mehr geben wird, ist diese Unterscheidung eindeutig.

Die Versionsnummer eines Netscape-Browsers wurde nun direkt ermittelt. Beim Internet Explorer muss man etwas trickreicher vorgehen. Es wird an dieser Stelle darauf verzichtet, mühsam anhand einer umfangreichen Tabelle die Versionsunterschiede zwischen den Internet Explorer-Versionen herauszuarbeiten; nachfolgend kurz die Regeln, woran man die Versionen 3, 4 und 5.x erkennt:

	IE3: version2 muss kleiner als 4 sein (ist 2 oder 3).
	IE4: version2 muss 4 sein.
	IE5: version2 ist ebenfalls 4, und navigator.userAgent enthält die Zeichenkette »MSIE 5.«).

In der folgenden, endgültigen Variante des Codes steht in der Variablen versionsnummer die Versionsnummer des Browsers, also eine ganze Zahl zwischen zwei und sechs:

var ua = navigator.userAgent.toLowerCase()
var netscapebrowser = (ua.indexOf("mozilla")!=-1 &&
ua.indexOf("compatible")==-1 && ua.indexOf("opera")==-1)
var iebrowser = (ua.indexOf("msie")>-1)
var av = navigator.appVersion
var version = av.substring(0, av.indexOf(" ")) *1
var version2 = av.substring(0, av.indexOf(".")) *1
if (netscapebrowser)
   var versionsnummer = version2
else if (iebrowser){
   if (version2<4)
      versionsnummer=3
   if (version2==4 && ua.indexOf("msie 5")==-1)
      versionsnummer = 4
   if (version2==4 && ua.indexOf("msie 5")>-1)
      versionsnummer = 5
}

Sie sehen hier, dass man den Code für den Internet Explorer beim Erscheinen einer neuen Version stets anpassen muss. Zwar könnte man versuchen, eine Gesetzmäßigkeit zu erkennen, und beispielsweise davon ausgehen, dass der Internet Explorer 6 in navigator.userAgent die Zeichenkette MSIE 6 enthält, aber zum einen hatte Microsoft immer mal wieder eine Überraschung bei navigator.userAgent parat, und was spricht zum anderen gegen eine Version 5.751 ?

Eine kleine Anekdote am Rande: Auf manchen Seiten durchsuchte man navigator.userAgent nach der Zeichenkette Mozilla/4.0; damit wollte man Internet Explorer 4 und Netscape Navigator 4 erkennen. Das ging ganz gut, auch bei den Unterversionen Netscape Navigator 4.01 bis 4.08. Die nächste Version hatte jedoch die Versionsnummer 4.5, und so kam es, dass eine gewisse Funktionalität ausgerechnet beim neuesten Browser auf dem Markt nicht funktioniert. Aus diesem Grund sollten Sie nie explizit auf eine Versionsnummer prüfen, sondern auf eine Mindestversionsnummer. Schreiben Sie also nicht

if (version2==4)

sondern:

if (version2>=4)

Weiterleitung

Alle Angaben zur URL der aktuellen Seite sind im location-Objekt gespeichert, das wiederum ein Unterobjekt des window-Objekts ist. Das window-Objekt kennen Sie ja bereits ein wenig, beispielsweise von window.alert(). Man greift also auf das location-Objekt mit window.location zu. Das window-Objekt ist jedoch das Standardobjekt unter JavaScript, der Name kann also weggelassen werden. Ein einfaches location (bzw. alert()) reicht also zum Aufruf aus.

	Das location-Objekt hat mehrere Eigenschaften und Methoden. Zunächst ist für Sie die Eigenschaft href interessant, die die gesamte URL enthält. Ab Netscape Navigator 2 bzw. Internet Explorer 4 erhält man diese auch, wenn man direkt auf location zugreift, aber der Internet Explorer 3 fällt mal wieder aus der Reihe. Aus diesem Grund sollten Sie immer location.href verwenden.

Das war auch schon alles, was wissenswert war. Der folgende Code zeigt noch einmal exemplarisch auf, wie verschiedene Browser auf verschiedene Seiten umgeleitet werden. Achten Sie darauf, wie verschachtelte if-Anweisungen vermieden werden: Wenn location.href mit einem neuen Wert besetzt wird, wird die Ausführung des Skripts sofort beendet.

var ua = navigator.userAgent.toLowerCase()
var netscapebrowser = (ua.indexOf("mozilla")!=-1 &&
ua.indexOf("compatible")==-1 && ua.indexOf("opera")==-1)
var iebrowser = (ua.indexOf("msie")>-1)
var av = navigator.appVersion
var version = av.substring(0, av.indexOf(" ")) *1
var version2 = av.substring(0, av.indexOf(".")) *1
if (netscapebrowser)
   var versionsnummer = version2
else if (iebrowser){
   if (version2<4)
      versionsnummer=3
   if (version2==4 && ua.indexOf("msie 5")==-1)
      versionsnummer = 4
   if (version2==4 && ua.indexOf("msie 5")>-1)
      versionsnummer = 5
}
//Weiterleitung
if (netscapebrowser&&versionsnummer==2)
   location.href="nn2.html"
if (netscapebrowser&&versionsnummer==3)
   location.href="nn3.html"
if (netscapebrowser&&versionsnummer==4)
   location.href="nn4.html"
if (netscapebrowser&&versionsnummer==5)
   location.href="nn6.html"
if (iebrowser&&versionsnummer==3)
   location.href="ie3.html"
if (iebrowser&&versionsnummer==4)
   location.href="ie4.html"
if (iebrowser&&versionsnummer==5)
   location.href="ie5.html"

5.3 Event-Handler

Im Kapitel »Vorbereitung« schon angesprochen, werden hier noch kurz einige Event-Handler vorgestellt. Dies dient nur dazu, Ihnen einen groben Überblick zu geben; konkrete Anwendungen folgen in den nächsten Kapiteln.

	onBlur: Wenn ein Fenster oder Formularfeld den Fokus verliert (nicht mehr im Vordergrund ist bzw. den Cursor enthält)
	onChange: Wenn der Wert eines Formularfelds geändert wird
	onClick: Beim Klicken auf einen Link oder auf ein Formularelement
	onFocus: Wenn ein Fenster oder Formularfeld den Fokus erhält (Mausklick)
	onLoad: Beim Laden eines Dokuments
	onMouseover: Wenn mit der Maus über einen Link gefahren wird
	onMouseout: Wenn der Link mit der Maus wieder verlassen wird (nach onMouseover)
	onUnload: Beim Verlassen eines Dokuments

Wie Event-Handler eingesetzt werden, ist ja auch bereits bekannt. In geeigneten HTML-Tags dienen die Event-Handler als Attributsname. Der Wert des Attributs ist dann das JavaScript-Kommando, das beim Eintreten des Ereignisses ausgeführt werden soll.

5.4 Fragen & Aufgaben

1.	Wie kann man mit getTime() feststellen, ob ein Jahr ein Schaltjahr ist?
2.	Simulieren Sie eine Lottoziehung (6 aus 49 plus Zufallszahl). Achten Sie darauf, dass keine Zahl zweimal gezogen wird.
3.	Fassen Sie zwei Beispiele in diesem Kapitel zusammen: Die Zufalls-URL soll nicht als Link angezeigt, sondern direkt aufgerufen werden.
4.	Wie kann man das letzte Listing in diesem Kapitel, die Weiterleitung der verschiedenen Browser, kürzer formulieren? (Tipp: Die URLs sind nach einem bestimmten Schema aufgebaut.)

1    Wie gesagt, aktuell ist Version 5.5, die sich nun schon seit einigen Monaten auf dem Markt ist

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 6 Fenster I
			6.1 Modale Fenster
			6.2 Navigationsleiste mit JavaScript
			6.3 Die Statuszeile
			6.4 Das location-Objekt
			6.5 Fragen & Aufgaben

Kapitel 6 Fenster I

Fensterln, älter auch fenstern »abends bei seinem Mädchen in die Kammer einsteigen« (< 16. Jh.)

– Kluge, Etymologisches Wörterbuch der deutschen Sprache

Das window-Objekt ist das wohl am häufigsten verwendete JavaScript-Objekt – und das, welches am seltensten ausgeschrieben wird. Die Methoden des Fenster-Objekts können nämlich aufgerufen werden, ohne dass man das Objekt voranstellt. Sie kennen ja bereits den Befehl window. alert("Was nun, sprach Zeus"); alternativ dazu reicht auch alert("Was nun, sprach Zeus"). Die Methode document.write() ist streng genommen auch eine Abkürzung. Das document-Objekt ist ein Unterobjekt des window-Objekts, ganz korrekt wäre also window.document.write(). Das window-Objekt bezeichnet ein Browser-Fenster oder einen Frame, denn jeder Frame wird intern als eigenes Fenster behandelt. Auf den aktuellen Frame beziehungsweise das aktuelle Browser-Fenster greift man mit window oder self oder this zu. Wie gesagt – den Sermon könnte man sich sparen, aber man macht seine Skripte so übersichtlicher und programmiert auch sauberer. Als Entwickler muss man immer fürchten, dass es eine neue Browser-Version oder einen ganz neuen Browser gibt, der die Syntax etwas strenger auslegt.

In diesem Kapitel werden einige seltenere Methoden und Eigenschaften des window-Objekts vorgestellt. Mit den Details beschäftigen wir uns erst in den Kapiteln »Fenster II« und »Fenster III«.

6.1 Modale Fenster

Unter einem modalen Fenster einer Applikation versteht man ein Fenster, das in den Vordergrund tritt, den Fokus bekommt und den Zugriff auf das Hauptapplikationsfenster sperrt: Solange das (modale) Fenster offen ist, kann auf das Hauptfenster nicht mehr zugegriffen werden. Ein Beispiel ist die Meldung einer Textverarbeitung, die den Benutzer vor dem Verlassen des Programms fragt, ob das aktuelle Dokument gespeichert werden soll (sofern es noch nicht gespeichert wurde). Sie müssen entweder auf Ja, Nein oder Abbrechen klicken, um wieder auf die Textverarbeitung zugreifen zu können. Auch die Cookie-Warnung des Netscape Navigator ist ein modales Fenster.

Abbildung 6.1  Cookie-Warnung des Netscape Navigator

Sie merken es bereits: Ein modales Fenster greift stark in die Benutzerführung ein. Sie können mit JavaScript auch modale Fenster erstellen (zu nicht-modalen Fenstern kommen wir im Kapitel »Fenster II«), aber gehen Sie damit sehr sparsam um. Zum einen geben Sie damit einem anderen Fenster den Fokus, was störend ist, und zum anderen werden modale Fenster vom Betriebssystem oft mit einem Warnton begleitet.

6.1.1 Warnung – nur im Notfall

Eine Möglichkeit, ein modales Fenster mit JavaScript zu erstellen, haben Sie bereits kennen gelernt: window.alert() oder kurz alert(). Damit wird ein modales Fenster mit einem Text angezeigt; als Icon wird ein Warndreieck verwendet (deswegen auch der Name: »alert«, dt. »Warnung«).

Da die Syntax des Befehls sehr einfach ist – Sie schreiben alert("I have a dream"), und »I have a dream« wird angezeigt –, kommen wir gleich zu den Anwendungsmöglichkeiten. Es wird nur ein Text angezeigt, was ja auch mit anderen Mitteln möglich wäre. Die Besonderheit dieser Funktion ist gleichzeitig auch ihr großer Nachteil: Das modale Fenster muss erst einmal geschlossen werden, um weiterzumachen. Wenn Sie also eine besonders wichtige Mitteilung zu machen haben, können Sie so ein Warnfenster verwenden.

Die SmartUpdate-Applikation von Netscape, mit der man seinen Browser auf die neueste Version bringen kann, ohne das gesamte Paket herunterladen zu müssen, verwendet beispielsweise window.alert(), um den Benutzer darauf hinzuweisen, dass er seinen Browser neu starten oder gar den Rechner neu booten muss, um in den Genuss der neuen Funktionalität zu kommen. Das wurde eingeführt, weil viele Benutzer den Hinweis, der zuvor lediglich als Text dargestellt wurde, einfach weggeklickt haben, und sich dann wunderten, wo die neuen Programme blieben. Dieses Beispiel ist eine der wenigen nützlichen Anwendungen von window.alert(). Allzu oft sieht man – vor allem auf privaten Homepages – nicht ganz so wichtige Hinweise: »Sie betreten gerade dieSuper- JavaScript-Homepage von N.N.« ist Grund genug, weiterzusurfen – zum Beispiel zu MyGalileo.

Während der Programmierung wird die Funktion allerdings auch von Profis eingesetzt. Bei der Fehlersuche leistet window.alert() wertvolle Dienste, da der Wert einzelner Variablen schnell angezeigt werden kann. Ein document.write() ist ja nicht möglich, sobald ein Dokument vollständig geladen worden ist.

Im folgenden Beispiel befindet sich ein Stück Programmcode, der nicht funktioniert.

<HTML>
<HEAD>
<TITLE>Fehlersuche window.alert()</TITLE>
</HEAD>
<BODY>
<H3>Alle ungeraden Zahlen kleiner als 10</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
var rest
for (var i=1; i<10; i++){
   rest = i % 2
   if (rest=1)
      document.write(i+" ist ungerade!"+"<"+"BR"+">")
}
//--></SCRIPT>
</BODY>
</HTML>

	Dieses Listing liefert als Ergebnis ein paar Zahlen zu viel (siehe//Abbildung 6.2). Mit window.alert() kommt man dem Fehler auf die Schliche, wenn man sich die Variable rest an den richtigen Stellen anzeigen lässt:

<HTML>
<HEAD>
<TITLE>Fehlersuche window.alert()</TITLE>
</HEAD>
<BODY>
<H3>Alle ungeraden Zahlen kleiner als 10</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
var rest
for (var i=1; i<10; i++){
   rest = i % 2
   alert("vorher: "+rest)
   if (rest=1){
      alert("nachher: "+rest)
      document.write(i+" ist ungerade!"+"<"+"BR"+">")
   }
}
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 6.2  Ein offensichtlich falsches Ergebnis

Des Rätsels Lösung liegt in der folgenden Abfrage:

if (rest=1)

Hierdurch wird die Variable rest mit dem Wert 1 belegt, und diese Anweisung liefert – bei einer if-Anweisung – den Wert true. Korrekt wäre ein Vergleich:

if (rest==1)

	Einige Versionen des Netscape Navigator lassen Zuweisungen innerhalb von Bedingungen nicht mehr zu, und geben eine Fehlermeldung aus. Ein Grund mehr, diese Fehler tunlichst zu vermeiden!

6.1.2 Bestätigungen

Bot das letzte modale Fenster noch sehr wenig Eingriffsmöglichkeiten – nur eine OK-Schaltfläche –, so kann man mit window.confirm() ein modales Fenster mit zwei Schaltflächen anbieten: je nach Betriebssystem und Sprache OK und Cancel oder OK und Abbrechen. Klickt der Benutzer auf OK, so liefert die Methode true zurück, ansonsten false.

Auch hier macht Netscape wieder vor, wie man diese Methode sinnvoll einsetzen könnte. Unter http://www.mozilla.org kann man den aktuellen Entwicklungsstand des Generation 6-Browsers von Netscape herunterladen. Zwar gibt es in unterschiedlichen Abständen sogenannte Milestones (Meilensteine), die auch schon relativ stabil laufen, aber jede Nacht wird der aktuelle Stand der Dinge kompiliert und via FTP zur Verfügung gestellt. Es ist nicht sichergestellt, dass diese Version überhaupt startet. Aus diesem Grund wird mit JavaScript sicherheitshalber noch einmal nachgefragt, ob der Benutzer diese Version wirklich herunterladen will. Der zugehörige Code sieht dort ungefähr folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>window.confirm()</TITLE>
</HEAD>
<BODY>
<H3>Laden Sie die Alpha-Version des neuen Netscape herunter!</H3>
<A HREF="datei.exe" onClick="return confirm('Are you sure you want
    to do this crazy thing?')">Hier klicken</A>
</BODY>
</HTML>

Hier sind ein paar zusätzliche Erklärungen notwendig. Der Befehl confirm('Are you sure you want to do this crazy thing?') öffnet ein modales Fenster. Klickt der Benutzer darin auf OK, wird true zurückgeliefert, ansonsten false. Stimmt der Benutzer also dem Download zu, so lautet das onClick-Attribut des <A>-Tags return true, ansonsten return false.

Die Bedeutung ist relativ einfach: Im obigen Fall kollidieren der HTML-Link und der onClick-Event-Handler. Ein Klicken auf den Link führt dazu, dass die Datei datei.exe vom Webserver angefordert wird; der onClick-Event-Handler führt den entsprechenden JavaScript-Code aus. Wer macht das Rennen?

Der Trick hierbei ist Folgender: Der JavaScript-Code wird auf jeden Fall ausgeführt. Endet der Code mit return true, so wird daraufhin das Ziel des HTML-Links aufgerufen, bei return false wird der HTML-Link nicht aufgerufen. So funktioniert auch die Abfrage von oben: Verneint der Benutzer die Frage im modalen Fenster, so lautet der onClick-Event-Handler return false, und der Link wird nicht ausgeführt. Bejaht der Benutzer die Abfrage, so lautet der onClick-Event-Handler return true und datei.exe wird wie geplant aufgerufen.

Abbildung 6.3  Download für Furchtlose

6.1.3 Benutzereingaben

Es gibt noch eine weitere Stufe, und diese ist das luxuriöseste Fenster, das Sie mit einem einzelnen JavaScript-Befehl erzeugen können: window.prompt(). Außer den Schaltflächen OK und Cancel (oder Abbrechen) gibt es noch ein einzeiliges Texteingabefeld. Bei der Überprüfung auf Vollständigkeit von Formulareingaben kann das recht nützlich werden.

Der Rückgabewert der Methode ist der eingegebene Text, sofern der Benutzer auf OK klickt. Bei der Betätigung der Schaltfläche Cancel oder Abbrechen wird der spezielle Wert null zurückgegeben, egal was in das Textfeld eingegeben worden ist. Der folgende Code fragt den Namen des Benutzers ab und gibt ihn in einem weiteren modalen Fenster aus – sofern die Schaltfläche OK angeklickt worden und ein Name eingegeben worden ist.

<HTML>
<HEAD>
<TITLE>window.prompt()</TITLE>
</HEAD>
<BODY>
<H3>What's your name?</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
var benutzername = prompt("Wie heißen Sie?")
if (benutzername)
   alert("Guten Tag, Herr/Frau " + benutzername)
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 6.4  Dateneingabe mit JavaScript

Wie die Praxis zeigt, wird der auf if (benutzername) folgende Befehl auch dann nicht ausgeführt, wenn die Schaltfläche OK betätigt, aber kein Name eingegeben worden ist.

6.2 Navigationsleiste mit JavaScript

Die Navigationsleiste des Browsers wird ziemlich häufig benutzt. Vor allem die Schaltflächen Zurück (oder Back), Drucken (oder Print) und Neu laden (oder Aktualisieren, Refresh, Reload) werden angeblich am häufigsten betätigt. Mit JavaScript kann man diese Funktionalität nachbilden.

6.2.1 Das History-Objekt

Die History eines Browser-Fensters oder eines Frames ist nichts weiter als eine Liste der zuvor besuchten Seiten des aktuellen Fensters oder Frames. Beim Internet Explorer gibt es einen eigenen Ordner namens History oder Verlauf, der die globale History, also alle aufgerufenen Seiten enthält, während der Netscape Navigator diese Daten in einer einzelnen Datei ablegt. Auf die Elemente des History-Objekts haben Sie natürlich keinen Schreibzugriff. Stellen Sie sich vor, eine bösartige Seite würde die gesamte History des Benutzers überschreiben. Egal, ob der Benutzer vor oder zurück will, er würde immer auf der falschen Seite landen. Aber auch der Lesezugriff ist stark eingeschränkt, und zwar aus Sicherheitsgründen. Wenn man mit JavaScript (oder anderen Mitteln) die History-Liste des Benutzers auslesen könnte, wäre der gläserne Benutzer geschaffen. Manchmal werden auch Passwörter und andere vertrauliche Informationen in der URL übertragen, ein Lesezugriff wäre also ein Unding. Mit einem signierten Skript kann man auf diese Werte zugreifen, aber das ist nicht Thema dieses Kapitels.

Schon interessanter ist es, in der History nach vorn oder hinten zu springen, wie man es auch mit den Schaltflächen in der Navigationsleiste des Browsers machen kann.

Wenn Sie einen englischsprachigen Browser verwenden, haben Sie die Funktionsnamen direkt vor sich: back() springt zurück, forward() nach vorn. Mit dem folgenden Skript wird ein Teil der Navigationsleiste nachgebildet. Beachten Sie, dass Sie zwar auch mit window.history.methode() auf die Methoden des History-Objekts zugreifen können; aber wie bereits schon mehrfach betont, kann man das window. auch weglassen.

<HTML>
<HEAD>
<TITLE>History-Objekt</TITLE>
</HEAD>
<BODY>
<H3>Navigation mit JavaScript</H3>
<A HREF="javascript:history.back()">Zurück</A> -
<A HREF="javascript:history.forward()">Vor</A>
</BODY>
</HTML>

	Es gibt noch eine weitere Methode des History-Objekts: history.go(). Mit dieser Methode kann man in der History mehr als einen Eintrag vor- oder zurückspringen. Als Parameter wird hierbei angegeben, um wie viel vor (positiver Wert) oder zurück (negativer Wert) gesprungen wird. Statt history.back() kann man also auch history.go(-1) verwenden; history.forward() wird durch history.go(1) ersetzt. Mit history.go(0) wird übrigens die aktuelle Seite neu geladen. Dennoch ist es gefährlich, history.go() zu verwenden. Auf verschiedenen Plattformen gibt es fehlerhafte Implementierungen. So unterstützt beispielsweise der Internet Explorer 3 nur history.go(-1) und history.go(0); andere numerische Werte werden wie -1 behandelt.

6.2.2 Vorwärts und Rückwärts Teil 2

Seit der Version 3 von Netscape Navigator bzw. Internet Explorer hat jeder Frame seine eigene History. Man kann also problemlos zwischen den Seiten hin- und herspringen, die in einem bestimmten Frame geladen worden sind. Nun kommt es in der Realität aber des Öfteren vor, dass sich der Inhalt mehrerer Frames ändert. Stellen Sie sich vor, Sie haben eine Webseite mit einem Frame für den Inhalt und einem Frame für Werbebanner. Der Werbebanner-Frame wird alle 60 Sekunden neu geladen, während im Inhalts-Frame immer dann neuer Inhalt geladen wird, wenn der Benutzer auf einen Link klickt. Mit den bisherigen Methoden ist es zwar möglich, die History jedes einzelnen Frames zu verfolgen, nicht aber die globale History des Fensters, die aus einer Mischung von Seiten im Inhalts- und im Werbe-Frame besteht.

	Seit Netscape Navigator 4 hat das window-Objekt ebenfalls die Methoden back() und forward(), die es dem Benutzer erlauben, durch die globale History des Fensters zu navigieren. Mit dem folgenden Skript, das am besten in einem Frame platziert wird, kann der Benutzer durch die History des Hauptfensters navigieren:

<HTML>
<HEAD>
<TITLE>window-Objekt: vorwärts und rückwärts</TITLE>
</HEAD>
<BODY>
<H3>Navigation mit JavaScript</H3>
<A HREF="javascript:top.Hauptfenster.back()">Zurück</A> -
<A HREF="javascript:top.Hauptfenster.forward()">Vor</A>
</BODY>
</HTML>

6.2.3 Drucken mit JavaScript

Eine sehr häufige Frage in Newsgroups lautet: Wie kann ich mit JavaScript drucken? Die Antwort ist nur auf den allerersten Blick unbefriedigend: Es ist nicht möglich, automatisch Daten zum Drucker zu senden – stellen Sie sich nur einmal vor, Sie surfen und plötzlich fängt Ihr Drucker an, unkontrolliert Seiten auszuspucken.

	Aber zurück zum Thema: Das Dialogfenster des Drucken-Dialogs kann nicht nur mit dem entsprechenden Menübefehl oder der Schaltfläche in der Navigationsleiste aufgerufen werden. Ab JavaScript 1.2 (das heißt in diesem Fall: Ab Netscape Navigator 4 und Internet Explorer 5) gibt es die Methode print() des window-Objekts, die genau dieses Dialogfenster aufruft. Zwar haben Sie auf den ersten Blick keinen Mehrwert gegenüber der Navigationsleiste, aber viele Benutzer rufen gern das Kontextmenü des Fensters oder Frames auf und wählen dort den Drucken-Eintrag. Der Netscape Navigator erlaubt so etwas nicht, und diese Benutzer freuen sich sicherlich über den zusätzlichen Komfort, wenn Sie das Drucken mit JavaScript ermöglichen. Im Kapitel »Fenster III« werden Sie außerdem Fenster ohne Navigationsleiste und ohne Menüleiste kennen lernen. Wer hier nicht die Tastenkombination zum Drucken kennt, hat ein ernsthaftes Problem, den Inhalt des Fensters zu Papier zu bringen. Eine JavaScript-Lösung schafft hier eine Erleichterung.

Sie sollten auf jeden Fall überprüfen, ob der Browser die Methode unterstützt. Dazu müssen Sie entweder im Code mit den bekannten Methoden auf die Unterstützung von JavaScript Version 1.2 überprüfen oder eine if-Abfrage benutzen, wie wir sie bereits bei anderen Beispielen verwendet haben. Im folgenden Code sehen Sie beide Varianten:

<HTML>
<HEAD>
<TITLE>window.print()</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function drucken(){
   if (window.print)
      window.print()
   else
      window.alert("Leider nicht möglich!")
}
function drucken2(){}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.2"><!--
function drucken2(){
   window.print()
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Drucken mit JavaScript</H3>
<A HREF="javascript:drucken()">Drucken über if-Abfrage</A><B>
<A HREF="javascript:drucken2()">Drucken über JS-Version</A>
</BODY>
</HTML>

6.3 Die Statuszeile

Kommen wir nun zu einer der umstrittensten JavaScript-Anwendungen. Die meisten Browser-Fenster haben eine Statuszeile, in der während des Ladens des Dokuments der Ladestatus angezeigt und beim Bewegen der Maus über einen Link das Ziel des Links angezeigt wird. Schon bald nach dem Erscheinen des Netscape Navigator 2 sind pfiffige Programmierer auf die Idee gekommen, die Statuszeile als bequeme Möglichkeit der Textausgabe zu verwenden. Natürlich ist das bequem, und es gibt auch nützliche Anwendungen. Diese sind leider zeitweise in der Minderheit, und in den folgenden Abschnitten soll eine deutliche Warnung ausgesprochen werden, was tunlichst vermieden werden sollte. Dem Benutzer dient die Statuszeile als Informationsquelle, und sie sollte nicht für Spielereien missbraucht werden.

6.3.1 Erläuternde Links

Unerfahrenen Anwendern sollte man die Navigation im World Wide Web so einfach und intuitiv wie möglich gestalten. Irgendwann ist es in Mode gekommen, erklärende Hilfetexte in der Statuszeile des Browsers zu platzieren. Das bietet sich vor allem bei Hyperlinks an. Es ist doch viel schicker, wenn in der Statuszeile Hier geht's zu unseren Produkten steht anstelle von http://www.ihrefirma.de/produkte/index.html.

Die Umsetzung ist nicht weiter schwierig. Die entsprechende Eigenschaft, die den Text in der Statuszeile angibt, ist window.status; lediglich einen kleinen Fallstrick müssen Sie noch umgehen. Der folgende Code liefert nicht mit allen Browsern das gewünschte Ergebnis:

<A HREF="/produkte/index.html" ="window.status=
'Unsere Produkte'">Produkte</A>

Der Text wird kurzzeitig in der Statuszeile angezeigt, aber dann erscheint die Ziel-URL des Hyperlinks. Der Grund: Auch hier kollidieren der Event-Handler und die Browser-Aktion, wenn der Mauszeiger über den Hyperlink fährt. Sie wissen eigentlich bereits von oben, wie Sie dem JavaScript-Event-Handler den Vorrang geben – doch leider funktioniert das an dieser Stelle nicht. Es handelt sich hier um eine Art unlogische Ausnahme. Nur wenn der Event-Handler auf return true endet, wird der Text in der Statuszeile angezeigt, andernfalls nicht.

	Noch ein kleiner Hinweis, bevor der HTML-Code präsentiert wird: Vergessen Sie nicht, mit dem onMouseout-Event-Handler die Eigenschaft window.status wieder auf eine leere Zeichenkette zu setzen; ansonsten bleibt der Text in der Stauszeile stehen. Beachten Sie dabei, dass der onMouseout-Event-Handler erst ab Netscape Navigator 3 und Internet Explorer 4 zur Verfügung steht.

<A HREF="/produkte/index.html"
onMouseover="window.status='Unsere Produkte';
     return true" onMouseout="window.status='';
       return true">Produkte</A>

	Viele erfahrene Benutzer wissen eigentlich ganz gern, wohin ein Link führt. Ich öffne beispielsweise Links gern in einem neuen Fenster. Wird jedoch die Statuszeile überschrieben, so kann man nicht feststellen, ob der Link eine HTML-Seite aufruft oder eine JavaScript-Funktion (im letzteren Fall ist das Öffnen im neuen Fenster nicht möglich). Wenn Sie auf diese Form von erklärenden Links nicht verzichten wollen, sollten Sie wenigstens zusätzlich die URL der Zielseite in der Statuszeile angeben.

6.3.2 Laufschrift

Sie kennen das sicherlich: In der Statuszeile des Browsers läuft ein Text von rechts nach links. Um es gleich vorwegzusagen: Dieser Effekt gilt seit ungefähr vier Jahren als veraltet, sorgt nur für Verärgerung beim Benutzer und besitzt keinen wirklichen Nutzen. Warum der Effekt hier trotzdem vorgeführt wird? Es handelt sich hierbei um eines der Standardbeispiele für die Möglichkeiten von JavaScript, und man muss es einfach einmal gesehen haben.

Timeouts setzen

Oft ist es bei der JavaScript-Programmierung notwendig, einen Befehl nicht sofort auszuführen, sondern erst später. Dafür benutzt man sogenannte Timeouts, die mit einer Methode des window-Objekts gesetzt werden können. Die Befehlssyntax lautet leicht vereinfacht folgendermaßen:

window.setTimeout(Befehl, Verzögerung)

Dabei ist Befehl eine Zeichenkette, die den entsprechenden JavaScript-Befehl enthält, und Verzögerung ist die Zeitspanne in Millisekunden, die verstreichen muss, bis der Befehl ausgeführt wird. Folgender Befehl ruft nach fünf Sekunden die Homepage des Galileo-Verlags auf:

setTimeout("location.href='http://www.galileo-press.de'", 5000)

Beachten Sie, dass folgender Code nicht funktionieren wird:

<HTML>
<HEAD>
<TITLE>Timeouts</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function galileo(){
   var galileo_url = "http://www.galileo-press.de"
   setTimeout("location.href=galileo_url", 5000)
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="galileo()">
<H3>Verbinde mit Galileo Press...</H3>
</BODY>
</HTML>

Der Grund ist, dass galileo_url eine lokale Variable ist. Wenn der Befehl nach fünf Sekunden ausgeführt wird, steht diese Variable nicht mehr zur Verfügung, da sie außerhalb der Funktion ausgeführt wird. Es gibt drei Auswege aus diesem Dilemma:

1.	Verwendung einer globalen Variablen
2.	Verwendung einer eigenen Funktion
3.	Verwendung keiner Variablen

Zu 1.: Der <SCRIPT>-Teil des vorherigen Listings muss folgendermaßen geändert werden:

<SCRIPT LANGUAGE="JavaScript"><!-
var galileo_url
function galileo(){
   galileo_url = "http://www.galileo-press.de"
   setTimeout("location.href=galileo_url", 5000)
}
//--></SCRIPT>

Zu 2.: Der <SCRIPT>-Teil muss folgendermaßen geändert werden:

<SCRIPT LANGUAGE="JavaScript"><!--
function galileo_laden(){
   var galileo_url = "http://www.galileo-press.de"
   location.href=galileo_url
}
function galileo(){
   setTimeout("galileo_laden()", 5000)
}
//--></SCRIPT>

Zu 3.: Der <SCRIPT>-Teil muss folgendermaßen geändert werden:

<SCRIPT LANGUAGE="JavaScript"><!--
function galileo(){
   var galileo_url = "http://www.galileo-press.de"
   setTimeout("location.href='"+galileo_url+"'", 5000)
}
//--></SCRIPT>

Timeouts löschen

Es kommt in der Praxis des Öfteren vor, dass man den Befehl dann doch nicht mehr ausführen, also den Timeout löschen will. Jeder Aufruf von setTimeout() gibt einen Wert zurück, der als eindeutiger Identifikator für den Timeout dient. Je nach Browser ist das entweder ein numerischer Wert oder ein Objekt. Hüten Sie sich also davor, numerische Berechnungen mit dem Rückgabewert auszuführen. Sie können aber jederzeit den Rückgabewert der Methode window.clearTimeout() als Parameter übergeben, um den Timeout zu löschen.

Im folgenden Beispiel wird wieder die Homepage von Galileo Press nach fünf Sekunden aufgerufen, außer der Benutzer klickt auf den Link auf der Seite. Beachten Sie, dass die von setTimeout() zurückgegebene ID in einer globalen Variablen gespeichert werden muss.

<HTML>
<HEAD>
<TITLE>Timeouts setzen und löschen</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!-
var ID
function galileo(){
   ID = setTimeout("location.href='http://www.galileo
     press.de'", 5000)
}
function kein_galileo(){
   clearTimeout(ID)
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="galileo()">
<A HREF="javascript:kein_galileo()">Laden stoppen</A>
</BODY>
</HTML>

Laufschrift mit Timeouts

Kommen wir zum ursprünglichen Beispiel zurück, der Laufschrift. Diese ist mit Timeouts recht schnell zu erstellen, und zwar folgendermaßen:

	In einer globalen Variablen wird der Text abgespeichert, der in der Statuszeile angezeigt werden soll.
	In einer JavaScript-Funktion wird der entsprechende Text in der Statuszeile angezeigt, und dann wird der Text verändert, sodass der Scrolleffekt entsteht (der erste Buchstabe wird entfernt und hinten wieder angehängt).
	Dann wird ein Timeout gesetzt, der die Funktion nach Ablauf einer gewissen Zeitspanne wieder aufruft.

<HTML>
<HEAD>
<TITLE>Laufschrift</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var lauftext = " +++ Read my lips: no tax on beer "
function laufschrift(){
   window.status = lauftext
   lauftext = lauftext.substring(1, lauftext.length) +
     lauftext.substring(0,1)
   setTimeout("laufschrift()", 100)
//Weiter nach einer Zehntelsekunde
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="laufschrift()">
<H3>Laufschrift mit JavaScript</H3>
</BODY>
</HTML>

Nachteile

	Noch ein paar Sätze zu Laufschriften: Ihnen wird aufgefallen sein, dass auf größeren und seriösen Seiten keine Statuszeilen-Laufschriften vorkommen (außer eine Zeit lang auf den Seiten einer Gruppe von Online-Versendern, aber Ausnahmen bestätigen bekanntermaßen die Regel). Das hat auch seinen Grund. Durch die Laufschrift ist die Statuszeile permanent belegt, und man kann beispielsweise das Ziel von Links nicht mehr sehen. Eine nützliche Anwendung für eine Laufschrift habe ich auch noch nirgends gesehen. Wichtige Mitteilungen kann man auch an exponierter Stelle auf der eigentlichen Webseite platzieren. Mit Laufschriften ist es beinahe so wie mit dem <MARQUEE>-HTML-Tag (der beim Internet Explorer eine Laufschrift erzeugt): Man disqualifiziert sich eher, als dass man mit seinen JavaScript-Kenntnissen imponiert.

Man kann auch in einem Formular-Eingabefeld eine Laufschrift erzeugen. Das ist nicht ganz so schlimm, da wenigstens die Statuszeile frei bleibt. Hat man viel Text und wenig Platz, ist das akzeptabel, weswegen dieses Beispiel im Kapitel »Formulare I« in einer Übungsaufgabe vorkommt. Aber ansonsten gilt: Verzichten Sie auf solche Spielereien, wenn der Sinn des ganzen im Verborgenen bleibt.

Bequemere Timeouts

	Sie haben gesehen, dass die Implementierung der Laufschrift ein wenig umständlich war: Eine Funktion musste geschrieben werden, die sich selbst nach ein paar Sekunden wieder aufruft. Seit Netscape Navigator 4 und Internet Explorer 4 gibt es die Möglichkeit, eine Funktion von außen wiederholt aufzurufen, und zwar immer nach Ablauf einer festen Zeitspanne. Der erforderliche Befehl heißt setInterval(), und der korrespondierende Löschbefehl heißt clearInterval(). Der erste Parameter ist wieder der JavaScript-Befehl oder Funktionsname, der zweite Parameter ist die Verzögerung in Millisekunden zwischen den Aufrufen. Beim dritten Parameter verhalten sich der Netscape Navigator und der Internet Explorer unterschiedlich; hier sei auf die Referenz verwiesen. Das Laufschrift-Beispiel jedenfalls kann folgendermaßen umgeschrieben werden – aber nur für Browser ab der vierten Generation.

<HTML>
<HEAD>
<TITLE>Laufschrift für Browser der vierten Generation</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var lauftext = " +++ Read my lips: no tax on beer "
function laufschrift(){
   window.status = lauftext
   lauftext = lauftext.substring(1, lauftext.length) +
     lauftext.substring(0,1)
}
setInterval("laufschrift()", 5000)
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Laufschrift mit JavaScript ab Browser-Version 4</H3>
</BODY>
</HTML>

6.4 Das location-Objekt

Zum Abschluss dieses Kapitels noch ein kurzer Blick auf das Objekt location. Sie haben es ja schon bei den verschiedensten Beispielen in diesem Buch kennen gelernt, und es scheint etwas mit der aktuellen URL des Browser-Fensters zu tun zu haben.

Eine URL besteht aus verschiedenen Teilen, die Sie in der Abbildung zusammen mit dem Namen der entsprechenden JavaScript-Eigenschaft sehen können.

Abbildung 6.5  Die Eigenschaften des location-Objekts

In der Praxis wird location.href am häufigsten eingesetzt. Zwar liefert auch location die komplette URL der aktuellen Seite zurück, tut das aber nur bei neueren Browsern konsistent. Um abwärts kompatibel zu bleiben, ist die Verwendung von location.href zwingend.

Interessanter sind da schon die Methoden des location-Objekts. location.reload() (ab JavaScript Version 1.1) lädt die aktuelle URL neu. Ohne Parameter oder mit dem Parameter false wird die URL aus dem Cache des Browsers neu geladen, sofern sie verfügbar ist; wird true übergeben, so wird eine Anforderung an den Server geschickt. Das entspricht dem Klicken auf die Schaltfläche Reload der Navigationsleiste bei gleichzeitigem Drücken der Shift-Taste. Beachten Sie jedoch, dass hierbei Formulareingaben gelöscht werden. Um ein so genanntes »weiches Neuladen« zu veranlassen (das die aktuelle Scroll-Position im Dokument und in Formulareingaben beibehält), müssen Sie das bereits bekannte history.go(0) verwenden. (Das dauert allerdings beim Internet Explorer 3 relativ lange.)

JavaScript Version 1.1 hat auch die Methode location.replace() eingeführt. Hiermit kann man die History-Liste zumindest in begrenztem Umfang manipulieren. Wenn Sie mit location.replace(url) eine neue URL laden, nimmt diese in der History-Liste die Position der vorherigen Seite ein. Angenommen, Sie haben zuerst die Seite A.html geladen, gehen dann auf B.html und laden dann mittels location.replace("C.html") die Seite C.html. Ein Klick auf die Zurück-Schaltfläche in der Navigationsleiste führt dann zur Seite A.html zurück. Dies wird oft bei mehrseitigen Formularen verwendet, wenn man vermeiden will, dass der Benutzer zurückspringt und alte Eingaben nochmals ändert.

6.5 Fragen & Aufgaben

1.	Welche Arten von modalen Fenstern gibt es, und welche Anwendungsmöglichkeiten sind jeweils vorhanden?
2.	Was ist der Unterschied zwischen window.back() und history.back()?
3.	Was ist der Unterschied zwischen history.go(0) und location.reload()?
4.	Erstellen Sie eine Seite mit einem Inhalts- und einem Werbe-Frame. Geben Sie drei Möglichkeiten an, um den Werbe-Frame alle zwei Minuten neu zu laden (Tipp: Es muss nicht immer JavaScript sein).
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 7 Formulare I
			7.1 Überprüfung auf Vollständigkeit
			7.2 Automatische Überprüfung
			7.3 Anwendungsmöglichkeiten für Formulare
			7.4 Fragen & Aufgaben

Kapitel 7 Formulare I

Von allen Plagen, mit denen Gott der Herr unser Wirtschaftsleben heimsucht, ist die Bürokratie die weitaus schlimmste.

– Ephraim Kishon

Es gibt prinzipiell drei Einsatzgebiete für JavaScript: Grafische Effekte (Beispiele gibt es zum ersten Mal im Kapitel »Images I«), Navigationshilfen (zum Beispiel im Kapitel »Fenster II«) und echte Interaktion mit dem Benutzer. Interaktion bedeutet hier, dass der Benutzer etwas tut und die Webseite sich dementsprechend verändert. Sehr oft benutzt man hier HTML-Formulare. Das hat mehrere Gründe. HTML-Schaltflächen eignen sich vorzüglich, um JavaScript-Funktionen auszuführen, und in HTML-Eingabefeldern kann man Daten vom Benutzer abfragen. In diesem Kapitel soll es primär darum gehen, einen HTML-Fragebogen mit JavaScript-Funktionalität zu versehen.

7.1 Überprüfung auf Vollständigkeit

Sie haben das garantiert schon einmal im World Wide Web gesehen: Wenn Sie sich bei einem Freemail-Dienst, einer Online-Community oder MyGalileo registrieren, müssen Sie einige persönliche Angaben machen. Die Betreiber der Website haben natürlich ein großes Interesse daran, dass das Formular vollständig ausgefüllt wird. Das kann serverseitig gelöst werden, was den Vorteil hat, dass die Überprüfung auch mit wirklich jedem Browser funktioniert. Die Nachteile liegen aber gleichzeitig auf der Hand. Nicht immer steht dem Programmierer eine serverseitige Programmiersprachen-Unterstützung zur Verfügung. Der Programmieraufwand ist hierbei recht hoch, denn es soll ja nicht nur eine Fehlermeldung ausgegeben werden, sondern wenn möglich das Formular auch noch mit den zuvor eingegebenen Daten dargestellt werden. Es wäre schon sehr ärgerlich für den Benutzer, wenn er ein Formular fast vollständig ausfüllt und aufgrund einer einzigen Auslassung das komplette Formular noch einmal ausfüllen müsste.

Mit JavaScript kann auch auf der Clientseite die Überprüfung auf Vollständigkeit durchgeführt werden. Damit wird keine neue Seite in den Browser geladen, die Formulardaten bleiben unangetastet, und der Benutzer kann sofort den Fehler korrigieren.

Im Folgenden finden Sie ein HTML-Formular, das ausschließlich aus Pflichtfeldern bestehen soll. Nach dem Anklicken der Absende-Schaltfläche soll die Funktion pruefen() aufgerufen werden, die überprüft, ob das Formular vollständig ausgefüllt wurde, und gegebenenfalls eine Fehlermeldung ausgibt. Diese Funktion wird in diesem Kapitel schrittweise erarbeitet. Vorab jedoch noch ein paar Hinweise, wie diese Funktion in das HTML-Dokument eingebunden wird.

Das <FORM>-Tag hat den Event-Handler onSubmit, der ausgelöst wird, sobald das Formular abgeschickt wird. Wie schon bei anderen Beispielen in diesem Buch kann hier ein altbekannter Trick angewandt werden. Beim Versenden des Formulars kollidieren wieder die HTML-Konsequenzen des Versendens (nämlich das Aufrufen einer anderen Seite) und die mit onSubmit zugeordneten JavaScript-Aktionen. Endet der onSubmit-Event-Handler jedoch auf return false, so wird die HTML-Aktion (das Aufrufen der anderen Seite) nicht ausgeführt; bei return true wird sie ausgeführt. Also hat der <FORM>-Tag in diesem Beispiel folgenden Aufbau:

<FORM ACTION="/cgi-bin/skript" NAME="Fragebogen"
onSubmit="return pruefen()">

Die Funktion pruefen() gibt nur dann true zurück, wenn das Formular vollständig ausgefüllt worden ist, ansonsten false. Somit ist sichergestellt, dass nur vollständige Formulare verschickt werden – sofern der Browser des Benutzers JavaScript unterstützt und es auch aktiviert hat. Ältere Browser oder solche mit ausgeschaltetem JavaScript ignorieren den Skriptteil komplett und versenden das Formular direkt.

<HTML>
<HEAD>
<TITLE>Formular-Überprüfung</TITLE>
<SCRIPT><!--
function pruefen(){
   // ... kommt noch
   return true
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Anmeldeformular</H3>
<FORM ACTION="/cgi-bin/skript" NAME="Fragebogen"
onSubmit="return pruefen()">
Vorname: <INPUT TYPE="TEXT" NAME="Vorname"><BR>
Nachname: <INPUT TYPE="TEXT" NAME="Nachname"><BR>
E-Mail-Adresse: <INPUT TYPE="TEXT" NAME="Email"><BR>
<INPUT TYPE="RADIO" NAME="Geschlecht" VALUE="m"> männlich |
<INPUT TYPE="RADIO" NAME="Geschlecht" VALUE="w"> weiblich<BR>
Welche Bücher von Galileo Press besitzen Sie?<BR>
<INPUT TYPE="CHECKBOX" NAME="Flash"> Flash | <INPUT TYPE="CHECKBOX"
  NAME="JavaScript"> JavaScript | <INPUT TYPE="CHECKBOX"
    NAME="InDesign"> InDesign<BR>
Welches der Bücher hat das schönste Cover?
 <SELECT NAME="Cover">
 <OPTION>Bitte wählen</OPTION>
 <OPTION VALUE="Flash">Flash</OPTION>
 <OPTION VALUE="JavaScript">JavaScript</OPTION>
 <OPTION VALUE="InDesign">InDesign</OPTION>
 </SELECT><BR>
<INPUT TYPE="SUBMIT" VALUE="Absenden"> <INPUT TYPE="RESET" VALUE
  "Formular löschen">
</FORM>
</BODY>
</HTML>

Abbildung 7.1  Das (noch) funktionslose Formular

7.1.1 Allgemeiner Aufbau

Alle Formulare werden im Array document.forms[] gespeichert. Auf dieses Formular kann über den Array-Index zugegriffen werden, wobei die Formulare in der Reihenfolge im Array stehen, in der sie im HTML-Dokument vorkommen. Die Nummerierung beginnt beim Index 0. In unserem Beispiel benutzen wir also document.forms[0].

Alternativ dazu kann man auch über das NAME-Attribut des <FORM>-Tags auf das Formular zugreifen, im Beispiel also mit document.Fragebogen. Sollte das NAME-Attribut Spezialzeichen wie etwa das Leerzeichen enthalten (beispielsweise "Mein Fragebogen"), so kann noch mit document. forms["Mein Fragebogen"] darauf zugegriffen werden, allerdings erst ab JavaScript Version 1.1. Im allgemeinen aber sollte man den Array-Index verwenden. Da die meisten HTML-Seiten maximal ein Formular enthalten, reicht ein document.forms[0], und es ist auch nicht sonderlich unleserlich. Bei anderen Arrays, die viele Elemente besitzen (im Kapitel 9, »Images« finden Sie Beispiele), ist dieses Vorgehen sicherlich unpraktikabel.

Das Formular speichert all seine Elemente (also alle HTML-Formularelemente in diesem Formular) im Array elements[]. Auch hier kann man auf die einzelnen Elemente über den Array-Index zugreifen; im obigen Beispiel greift man auf das erste Texteingabefeld mit document.forms[0]. elements[0] zu. Alternativ können Sie auch wieder das NAME-Attribut verwenden, in diesem Fall document.forms[0].Vorname. Die meisten Formularelemente haben eine Eigenschaft value, die in der Regel die Eingabe des Benutzers angibt. Details hierzu finden Sie in den entsprechenden Abschnitten.

Zur Vereinfachung wird folgende Zeile am Anfang der Funktion pruefen() eingeführt:

var f = document.Fragebogen

Hiermit spart man sich ein wenig Tipparbeit; statt document.Fragebogen.elements[0] reicht jetzt f.elements[0].

7.1.2 Texteingabefelder

Unter Texteingabefeldern werden in diesem Zusammenhang Formularfelder verstanden, die folgendermaßen in HTML abgebildet werden:

	<INPUT TYPE="TEXT"> – einzeiliges Texteingabefeld
	<INPUT TYPE="PASSWORD"> – einzeiliges Paßwortfeld
	<INPUT TYPE="HIDDEN"> – unsichtbares Formularfeld
	<TEXTAREA> – mehrzeiliges Texteingabefeld

In diesem Fall gestaltet sich die Vollständigkeitsabfrage sehr einfach. Wie oben schon ausgeführt, heißt die Eigenschaft, die den Eingabewert im Texteingabefeld enthält, value. Der folgende JavaScript-Code kann also in die Funktion pruefen() eingefügt werden. Er funktioniert folgendermaßen: Ist ein Texteingabefeld nicht ausgefüllt, wird die Funktion mit return false verlassen, was dann zur Folge hat, dass das Formular nicht versandt wird.

if (f.Vorname.value=="")
   return false
if (f.Nachname.value=="")
   return false
if (f.E-Mail.value=="")
   return false

Auf eine Besonderheit bei Texteingabefeldern muss noch hingewiesen werden: Wenn Sie mehrere Texteingabefelder mit identischen NAME-Attributen haben, werden die Werte in einem Array gespeichert. Enthielte das Beispielformular von oben also noch ein Texteingabefeld namens Vorname, so könnte man auf das erste dieser Felder mit f.Vorname[0] zugreifen und auf das zweite Feld mit f.Vorname[1]. Beim Internet Explorer 3 funktioniert das leider nicht, hier müssen Sie über das elements[]-Array auf die Texteingabefelder zugreifen. Aus diesem Grund ein einfacher Tipp: Verwenden Sie stets eindeutige Bezeichnungen für Ihre Formularelemente.

7.1.3 Radiobuttons

Aus einer Gruppe Radiobuttons kann immer nur einer ausgewählt werden. Eine Gruppe von Radiobuttons ist durch ein identisches NAME-Attribut gekennzeichnet. Leider greift man im obigen Beispiel mit f.Geschlecht auf die Gruppe von Radiobuttons mit dem NAME-Attribut Geschlecht zu. Die Eigenschaft value liefert hier nicht das richtige Ergebnis: Es muss auf einen individuellen Radiobutton zugegriffen werden. Das wäre natürlich über das elements[]-Array möglich, aber es gibt einen eleganteren Weg. Analog zu Texteingabefeldern werden gleichnamige Radiobuttons auch in einem Array abgespeichert. Mit der folgenden Schleife werden alle Radiobuttons (in diesem Falle zwei) durchlaufen und es wird überprüft, ob der Button ausgewählt ist (Boolesche Eigenschaft checked). Wenn beide nicht ausgewählt sind, wird pruefen() mit return false verlassen.

var geschlecht_ok = false
for (var i=0; i<f.Geschlecht.length; i++)
   if (f.Geschlecht[i].checked)
      geschlecht_ok = true
if (!geschlecht_ok) return false

Alternativ dazu können Sie eine Variante ohne Schleife benutzen, die etwas kürzer ist:

if (!(f.Geschlecht[0].checked || f.Geschlecht[1].checked))
   return false

7.1.4 Checkboxen

Checkboxen können wie Radiobuttons ausgewählt werden, wobei sich die grafische Darstellung leicht unterscheidet: Checkboxen werden angekreuzt. Da Checkboxen nicht gruppiert sind, also jede Checkbox für sich ausgewählt werden kann (oder auch nicht), ist die Überprüfung auf Ausfüllung nicht weiter schwer. Wieder gibt es eine Boolesche Eigenschaft checked, die angibt, ob eine Checkbox angekreuzt ist oder nicht. Das Formular ist dann unvollständig ausgefüllt, wenn keine der drei Checkboxen angekreuzt worden ist.

if (!f.Flash.checked && !f.JavaScript.checked &&
  !f.InDesign.checked)
   return false

7.1.5 Auswahllisten

Eine HTML-Auswahlliste wird mit dem Tag <SELECT> eingeleitet; es ist sinnvoll, diesem Tag ein aussagekräftiges NAME-Attribut zu geben. Die einzelnen Elemente werden durch den HTML-Tag <OPTION> dargestellt. Dieser Tag hat standardmäßig kein NAME-Attribut; wenn man also dort Informationen unterbringen will, sollte man das VALUE-Attribut besetzen.

In Sachen JavaScript kann auf die Auswahlliste über das NAME-Attribut des <SELECT>-Tags zugegriffen werden. Die einzelnen Optionen sind im Array options[] abgespeichert. Jede Option hat die Boolesche Eigenschaft selected, die angibt, ob die entsprechende Option gerade ausgewählt ist. Mit der Eigenschaft value kann auf das VALUE-Attribut der Option zugegriffen werden.

Im Fragebogen-Beispiel kommt es darauf an, dass nicht die erste Option ausgewählt wird, denn die heißt "Bitte wählen". Ein erster Versuch der Abfrage lautet also folgendermaßen:

if (f.Cover.options[0].selected)
   return false

Wenn festgestellt werden soll, welche der Optionen gerade ausgewählt ist, könnte man auf die Idee kommen, das options[]-Array mit einer Schleife zu durchlaufen, um so den Index der ausgewählten Option herauszubekommen:

for (var i=0; i<f.Cover.options.length; i++)
   if (f.Cover.options[i].selected)
      var Auswahl = i
if (Auswahl==0)
   return false

Diese Arbeit kann man sich jedoch sparen: Auswahllisten haben die Eigenschaft selectedIndex, die den Array-Index der ausgewählten Option angibt. Die Abfrage kann also folgendermaßen vereinfacht werden:

if (f.Cover.selectedIndex==0)
   return false

Es gibt auch Auswahllisten, bei denen mehr als eine Option ausgewählt werden kann. Diese sind in HTML mit <SELECT MULTIPLE> abgebildet. In diesem Fall enthält selectedIndex den Index der obersten ausgewählten Option.

7.1.6 Fehlermeldung ausgeben

Hier wird noch einmal der vollständige Code für die Vollständigkeitsüberprüfung des Formulars wiedergegeben. Es wurden Kommandos hinzugefügt, die eine Warnmeldung ausgeben, sofern das Formular unvollständig ausgefüllt worden ist.

function pruefen(){
var f = document.forms[0]
   var fehler = "" //enthält die Bezeichnungen
                   //der nichtausgefüllten Felder
   // *** Überprüfung auf vollständige Ausfüllung
   if (f.Vorname.value=="")
      fehler += "Vorname "
   if (f.Nachname.value=="")
      fehler += "Nachname "
   if (f.E-Mail.value=="")
      fehler += "E-Mail "
   if (!(f.Geschlecht[0].checked||f.Geschlecht[1].checked))
      fehler += "Geschlecht "
   if (!f.Flash.checked && !f.JavaScript.checked &&
     !f.InDesign.checked)
      fehler += "Lieblingsbuch "
   if (f.Cover.selectedIndex==0)
      fehler += "Cover "
   // *** Gegebenenfalls Fehlermeldung
   if (fehler != ""){
      var fehlertext = "Die folgenden Felder wurden nicht
        vollständig ausgefüllt:\n"
      fehlertext += fehler
      alert(fehlertext)
      return false
   }
   return true
}

Abbildung 7.2  Hinweis auf nicht ausgefüllte Felder

7.1.7 Konstruktive Vorschläge

Anstatt bei Texteingabefeldern eine Fehlermeldung auszugeben, kann man auch die Methode window.prompt() benutzen, um den Benutzer direkt zu einer Texteingabe zu zwingen. Im Kapitel »Fenster I« wurde window.prompt() schon erläutert. Man muss in diesem Beispiel noch zusätzlich beachten, dass man die value-Eigenschaft der Texteingabefelder auch auf den eingegebenen Wert setzt, damit diese Daten auch an das serverseitige Skript übergeben werden können.

Die Funktion pruefen() muss also folgendermaßen abgeändert werden:

function pruefen(){
   var f = document.forms[0]
   var fehler = "" //enthält die Bezeichnungen
                   //der nichtausgefüllten Felder
   // *** Überprüfung auf vollständige Ausfüllung
   while (f.Vorname.value==""){
      var vorname = prompt("Bitte geben Sie Ihren Vornamen ein!")
      if (vorname)
         f.Vorname.value = vorname
   }
   while (f.Nachname.value==""){
      var nachname = prompt("Bitte geben Sie Ihren Nachnamen ein!")
      if (nachname)
         f.Nachname.value = nachname
   }
   while (f.Email.value==""){
      var email = prompt("Bitte geben Sie Ihre E-Mail-Adresse ein!")
      if (email)
         f.Email.value = email
   }
   if (!(f.Geschlecht[0].checked||f.Geschlecht[1].checked))
      fehler += "Geschlecht "
   if (!f.Flash.checked && !f.JavaScript.checked &&
     !f.InDesign.checked)
      fehler += "Lieblingsbuch "
   if (f.Cover.selectedIndex==0)
      fehler += "Cover "
   // *** Gegebenenfalls Fehlermeldung
   if (fehler != ""){
      var fehlertext = "Die folgenden Felder wurden nicht
        vollständig ausgefüllt:\n"
      fehlertext += fehler
      alert(fehlertext)
      return false
   }
   return true
}

Abbildung 7.3  Nicht ausgefüllte Texteingabefelder können direkt korrigiert werden.

Der Benutzer steckt in einer Endlosschleife fest und wird gezwungen, die Angaben zu machen, ansonsten geht es nicht weiter. So ein Abfragefenster wirkt allerdings relativ aufdringlich, und wenn ein Benutzer partout nichts angeben will, dann macht er eben Falschangaben. Sie werden mit diesen Mitteln niemanden dazu bringen, die Wahrheit zu sagen, wenn er nichts über sich preisgeben will. Vergisst aber jemand, ein Mussfeld auszufüllen, bieten Sie ihm eine bequeme Möglichkeit an, dies nachzuholen.

Testen Sie Ihren Code sehr gründlich. Folgender Tippfehler führt dazu, dass der Benutzer in einer Endlosschleife festsitzt, die er nicht mehr verlassen kann:

while (f.Email.value==""){
   var email = prompt("Bitte geben Sie Ihre Email-Adresse ein!")
   if (email)
      f.Nachname.value = email
   }

Dieser Fehler schleicht sich bei der Verwendung von Copy&Paste sehr schnell ein, und er ruiniert das Skript. Nicht das Email-Feld wird aktualisiert, sondern das Nachname-Feld. Außerdem bleibt das Email-Feld immer leer, egal was der Benutzer in das Abfragefenster eingibt. Es geht also an dieser Stelle nicht weiter, und der Benutzer kommt so schnell nicht wieder auf Ihre Seiten.

7.2 Automatische Überprüfung

	Das Skript zur Vollständigkeitsüberprüfung muss für jedes Formular neu geschrieben werden. Zwar können Sie Elemente wiederverwenden, aber etwas zusätzliche Arbeit ist immer nötig. Seit JavaScript Version 1.1 ist es aber möglich, die Überprüfung auch zu automatisieren. Jedes Formularelement besitzt nämlich die Eigenschaft type, die den Typ des Elements – beispielsweise Texteingabefeld, Radiobutton oder Checkbox – angibt. Man kann also den Ansatz verfolgen, in einer Schleife alle Formularelemente durchzugehen und zu überprüfen, ob sie ausgefüllt sind. Die Fehlermeldungen sind dann vielleicht nicht mehr so individuell wie im vorherigen Beispiel, aber Sie ersparen sich eine Menge Tipp- und Denkarbeit.

Im Folgenden sehen Sie das Grundgerüst für die JavaScript 1.1-fähige Version der Funktion pruefen(). Wie Sie schon wissen, wird bei gleichlautenden Funktionsnamen die letzte Funktion ausgeführt. Ältere Browser führen eine eingeschränkte, andere Funktion pruefen() aus, die lediglich durch return true für das Versenden des Formulars sorgt.

<SCRIPT LANGUAGE="JavaScript"><!--
function pruefen(){
   return true
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
function pruefen(f){ //Formular wird als Parameter übergeben
   var fehler = "" //Variable für die Fehlermeldung
   var i //Enthält das jeweilige Formularelement
   for (var j=0; i<f.elements.length; j++){
      i = f.elements[i]
      //kommt noch...
   }
   return true
}
//--></SCRIPT>

7.2.1 Texteingabefelder

Der Wert der type-Eigenschaft eines Texteingabefelds ist bei einem einzeiligen Texteingabefeld "text", "password" bei einem Passwortfeld sowie "textarea" bei einem mehrzeiligen Eingabefeld. In diesem Fall wird die value-Eigenschaft des Formularelements (zur Erinnerung: Es steht in der Variablen i) überprüft. Falls keine Eingabe gemacht erfolgt ist, wird das NAME-Attribut des Eingabefelds (es steht in der Eigenschaft name) dem Fehlerstring hinzugefügt, um wenigstens eine einigermaßen aussagekräftige Fehlermeldung ausgeben zu können.

if (i.type=="text"||i.type=="password"||i.type=="textarea")
   if (i.value=="")
      fehler += i.name + "\n"

7.2.2 Radiobuttons

Für Radiobuttons (erkennbar an der type-Eigenschaft "radio") muss man sich eine besondere Strategie überlegen. Jeder Radiobutton ist ein eigenes Formularelement und muss nicht unbedingt ausgewählt sein. Auf die folgende Art und Weise kommt man dennoch zum Ziel:

	Wenn Sie feststellen, dass das aktuell betrachtete Formularelement ein Radiobutton ist, wird das NAME-Attribut ausgelesen (Eigenschaft name). Dann wird das dazugehörige Array von Radiobuttons durchsucht, ob zumindest einer davon ausgewählt ist. Falls nicht, wird der Fehlerstring um das NAME-Attribut der Gruppe Radiobuttons erweitert.
	Jeder Radiobutton wird als einzelnes Formularelement behandelt. Ist also von einer Gruppe aus fünf Radiobuttons keiner ausgewählt, werden bei der Überprüfung der fünf Radiobuttons insgesamt fünfmal Mängel gefunden – es würde also fünf Fehlermeldungen geben. Aus diesem Grund wird eine weitere Variable, radiocheck, eingeführt (und zwar außerhalb der for-Schleife), in der die NAME-Attribute bereits geprüfter Radio-Buttons, durch Leerzeichen getrennt, eingetragen werden. Bevor ein Radiobutton überprüft wird, muss zuerst nachgeschaut werden, ob schon einmal ein anderer Radiobutton aus dieser Gruppe betrachtet worden ist. Daraus folgt auch eine Einschränkung für das Skript: Die NAME-Attribute der Radiobuttons dürfen keine Leerzeichen enthalten – aber das sollte sich von selbst verstehen, ich verweise auf die Einleitung.
if (i.type=="radio"){

   if (radiocheck.indexOf(i.name+ " "<0){

      radiocheck += i.name + " "

      eval("var radiogroup = f."+i.name)

      var ok = false

      for (var j=0; j<radiogroup.length; j++)

         if (radiogroup[j].checked)

            ok = true

      if (!ok)

         fehler += i.name + "\n"

   }

}

7.2.3 Checkboxen

Bei Checkboxen ist eine allgemeine Überprüfung schlecht möglich. Es ist dem Benutzer ja freigestellt, ob er eine Checkbox ankreuzt oder nicht. Jede Checkbox ist im Grunde genommen eine Ja/Nein-Frage, und somit bedeutet kein Kreuz auch eine Antwort, nämlich Nein. Aus diesem Grund werden Checkboxen (die type-Eigenschaft heißt übrigens "checkbox") nicht überprüft.

7.2.4 Auswahllisten

Auswahllisten erkennt man daran, dass die type-Eigenschaft des Formularelements entweder den Wert "select-one" oder den Wert "select-multiple" hat, je nachdem, ob der HTML-Parameter MULTIPLE gesetzt worden ist oder nicht. Die Eigenschaft selectedIndex muss überprüft werden. Sie muss ungleich 0 sein. Wir nehmen einfach einmal an, dass die oberste Option einer Auswahlliste immer »Bitte wählen Sie« oder ähnlich lautet.

if (i.type=="select-one" || i.type=="select-multiple")
   if (i.selectedIndex == 0)
      fehler += i.name + "\n"

7.2.5 Zusammenfassung

	Im folgenden finden Sie noch einmal den gesamten Code für dieses Beispiel. Mit ihm sind Sie in der Lage, mit JavaScript Version 1.1 jedes Formular auf vollständige Ausfüllung hin zu überprüfen. In der Praxis kommt es aber oft vor, dass nicht alle Felder Pflichtfelder sind. Viele Benutzer sind auch sehr zurückhaltend, wenn sie allzu persönliche Daten wie etwa Geburtsdatum, E-Mail-Adresse, Telefonnummer oder gar ihr Einkommen angeben müssen. Überlegen Sie sich also ganz genau, ob Sie wirklich alle Daten benötigen.

<HTML>
<HEAD>
<TITLE>Formularüberprüfung mit JS 1.1</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function pruefen(){
   return true
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
function pruefen(f){
   var fehler = "" //Variable für die Fehlermeldung
   var radiocheck = "" //Variable für überprüfte Radiobutton
     Gruppen
   i //Enthält das jeweilige Formularelement
   for (var j=0; j<f.elements.length; j++){
      var i = f.elements[j]
      //Texteingabefelder
      if (i.type=="text"||i.type=="password"||i.type=="textarea")
         if (i.value=="")
            fehler += i.name + "\n"
      //Radiobuttons
      if (i.type=="radio"){
         if (radiocheck.indexOf(i.name+ " "<0)){
            radiocheck += i.name + " "
            eval("var radiogroup = f."+i.name)
            var ok = false
            for (var j=0; j<radiogroup.length; j++)
               if (radiogroup[j].checked)
                  ok = true
            if (!ok)
               fehler += i.name + "\n"
         }
      }
      //Auswahllisten
      if (i.type=="select-one" || i.type=="select-multiple")
         if (i.selectedIndex == 0)
            fehler += i.name + "\n"
   }
   //Fehlermeldung
   if (fehler != ""){
      alert("Bitte füllen Sie die folgenden Felder aus:\n" + fehler)
      return false
   }
   return true
}
//--></SCRIPT>
</HEAD>
<BODY>
<FORM onSubmit="return pruefen(this)">
... Formularfelder kommen hierhin ...
</FORM>
</BODY>
</HTML>

7.3 Anwendungsmöglichkeiten für Formulare

Neben einer einfachen Vollständigkeitsüberprüfung von Benutzereingaben können Formulare auch noch anderweitig verwendet werden. In diesem Abschnitt werden einige Anwendungsmöglichkeiten vorgestellt, die Sie vielleicht schon in ähnlicher Form im World Wide Web gesehen haben. Sie können sie direkt auf Ihrer Website einsetzen.

7.3.1 Währungsrechner

Der Kurs D-Mark/Euro ist ja leider nicht exakt 1:2, so dass ein Umrechner ein praktisches Hilfsmittel ist. Das Skript wird folgendermaßen aufgebaut:

	In einem Texteingabefeld gibt der Benutzer den Betrag in einer Währung ein.
	In welche Richtung umgerechnet werden soll, also D-Mark in Euro oder umgekehrt, wird mit Radiobuttons ausgewählt.
	Die Umrechnung wird gestartet, indem eine Schaltfläche gedrückt wird.
	Der umgerechnete Betrag wird in einem neuen Texteingabefeld angezeigt.

Die größte Schwierigkeit besteht darin, die Eingaben des Benutzers eventuell umzuformen. JavaScript verwendet das amerikanische Zahlenformat, und das kennt nur einen Dezimalpunkt, kein Dezimalkomma. Also wird das erste Komma durch einen Punkt ersetzt. Die Umwandlung der Zeichenkette in eine Dezimalzahl geschieht automatisch durch die Multiplikation bzw. Division durch den amtlichen Umrechnungskurs. Andernfalls könnten Sie die Funktionen eval() oder parseFloat() verwenden.

<HTML>
<HEAD>
<TITLE>Euro-Rechner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function umrechnen(f){  //f ist eine Referenz
                        //auf das Formular
   var betrag = f.betrag.value
   if (betrag.indexOf(",")!=-1)
      betrag = betrag.substring(0, betrag.indexOf(",")) + "." +
        betrag.substring(betrag.indexOf(","), betrag.length)
   if (f.umrechnung[0].checked)
      f.ausgabe.value = betrag / 1.95583
   else
      f.ausgabe.value = 1.95583 * betrag
}
//--></SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="TEXT" NAME="betrag"><BR>
<INPUT TYPE="RADIO" NAME="umrechnung" VALUE="DMEUR"> DM nach
  Euro | <INPUT TYPE="RADIO" NAME="umrechnung" VALUE="EURDM">
    Euro nach DM<BR>
<INPUT TYPE="BUTTON" VALUE="Umrechnen!" onClick="umrechnen
  (this.form)"> <INPUT TYPE="TEXT" NAME="ausgabe">
</FORM>
</BODY>
</HTML>

Beachten Sie bei obigem Code den Aufruf umrechnen(this.form). Innerhalb jedes Event-Handlers eines Formularelements bezieht sich this auf das entsprechende Formularelement. Nun haben alle Formularelemente praktischerweise eine Eigenschaft form, die eine Referenz auf das dazugehörige Formular darstellt. Man kann also mit this.form das Formular als Parameter direkt an die Funktion übergeben.

Abbildung 7.4  Der Währungsrechner in Aktion

7.3.2 Währungsrechner Teil 2

Der Währungsrechner lässt sich mit relativ wenig Aufwand so erweitern, dass auch der Euro-Kurs anderer Währungen ermittelt werden kann. Insbesondere bei international ausgerichteten Webseiten ist das ein netter Service. Die Idee dahinter ist die Folgende: Die verschiedenen Währungen stehen alle in einer Auswahlliste. Die beiden Radiobuttons sind mit »nach Euro« und »von Euro« beschriftet. Nach einem Klick auf die Schaltfläche wird zunächst das Umtauschverhältnis zwischen Euro und der ausgewählten Währung ermittelt. Dieser Faktor ist in einem Array abgespeichert worden, sodass der Wert von selectedIndex der Auswahlliste direkt als Arrayindex verwendet werden kann. Je nachdem, welcher Radiobutton angeklickt worden ist, wird der eingegebene Betrag entweder durch den Umrechnungsfaktor geteilt oder damit multipliziert.

<HTML>
<HEAD>
<TITLE>Euro-Rechner Teil 2</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function MakeArray(n){
   this.length = n
   return this
}
var kurs = new MakeArray(3)
kurs[0] = 1.95583
kurs[1] = 6.55957
kurs[2] = 1937.98450
function umrechnen(f){  //f ist eine Referenz
                        //auf das Formular
   var betrag = f.betrag.value
   if (betrag.indexOf(",")!=-1)
      betrag = betrag.substring(0, betrag.indexOf(",")) + "." +
        betrag.substring(betrag.indexOf(","), betrag.length)
  var faktor = kurs[f.Waehrung.selectedIndex]
   if (f.umrechnung[0].checked)
      f.ausgabe.value = betrag / faktor
   else
      f.ausgabe.value = faktor * betrag
}
//--></SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="TEXT" NAME="betrag">
<SELECT NAME="Waehrung">
<OPTION>DM</OPTION>
<OPTION>Franc</OPTION>
<OPTION>Lira</OPTION></SELECT>
<BR>
<INPUT TYPE="RADIO" NAME="umrechnung" VALUE="nachEUR"> nach Euro
 | <INPUT TYPE="RADIO" NAME="umrechnung" VALUE="vonEUR"> von Euro<BR>
<INPUT TYPE="BUTTON" VALUE="Umrechnen!" onClick="umrechnen(this.
  form)"> <INPUT TYPE="TEXT" NAME="ausgabe">
</FORM>
</BODY>
</HTML>

	Natürlich können Sie das Beispiel auch umschreiben, sodass Sie zwischen zwei verschiedenen Währungen umrechnen können, mit dem Euro als Referenzwährung. Wenn Sie andere Währungen mit aufnehmen, beispielsweise den US-Dollar, müssen Sie den Kurs möglichst häufig aktualisieren, da der sich permanent ändert.

7.3.3 Formularfelder für die Textausgabe nutzen

Wenn man Nachrichten für den Benutzer ausgeben will, ist ein Fenster via window.alert() etwas aufdringlich, und auch das Schreiben in die Statuszeile hat so seine Nachteile. Ein Texteingabefeld eignet sich hierfür jedoch wunderbar. Zwar sind auch hier die gestalterischen Möglichkeiten eingeschränkt, aber man muss die Nachteile gegeneinander abwägen. Wie der Lese- und Schreibzugriff auf Texteingabefelder vonstatten geht, haben Sie vorher in diesem Kapitel gesehen, das ist also kein Problem mehr.

	Etwas ärgerlich ist es jedoch, wenn der Benutzer denkt, er müsse in dieses Texteingabefeld etwas schreiben. Aus diesem Grund wäre es wünschenswert, wenn man das Feld mit einem Schreibschutz (für den Benutzer) versehen könnte. Der Internet Explorer (ab Version 4) bietet dafür ein eigenes HTML-Attribut an, aber im Sinne einer allgemeinverträglichen Lösung muss man sich mit JavaScript behelfen.

Texteingabefelder kennen den Event-Handler onFocus, der genau dann aktiv wird, wenn der Fokus auf dem Texteingabefeld landet (in der Regel sieht man, dass hineingeklickt wird und der Cursor blinkt). Das Gegenteil vom Erhalten des Fokus heißt auf englisch »to blur«, und jedes Texteingabefeld besitzt eine Methode namens blur(), die den Fokus entfernt. Durch folgende Zeile wird der Fokus also genau dann von einem Feld weggenommen, wenn es angeklickt wird. Der Benutzer ist also nicht in der Lage, dem Feld permanent den Fokus zu geben und Eingaben zu tätigen.

<INPUT TYPE="TEXT" onFocus="this.blur()">

	Beachten Sie unbedingt die Reihenfolge! Das folgende Kommando würde dafür sorgen, dass ein Feld immer den Fokus erhält, und somit eine weitere Navigation oder Benutzung der Website verhindern. Dem Benutzer würde kaum etwas anderes übrigbleiben, als seinen Browser zu schließen.

<INPUT TYPE="TEXT" onBlur="this.focus()">

Seien Sie ebenfalls vorsichtig, wenn Sie modale Fenster in Verbindung mit onFocus verwenden. Wenn sich ein modales Fenster öffnet, verliert das Texteingabefeld natürlich den Fokus. Es erhält ihn aber wieder, sobald das modale Fenster wieder geschlossen wird. Der folgende Code zwingt den Benutzer wahrscheinlich dazu, den Browser über das System »abzuschießen«, da sich immer wieder ein modales Fenster öffnet:

<INPUT TYPE="TEXT" onFocus="windows.alert('Die Geister, die
  ich rief...')">

7.3.4 Navigation mit Auswahllisten

Links benötigen viel Platz. Eine Auswahlliste ist da sehr sparsam, kann hinter dem sparsamen Äußeren jedoch eine Menge Inhalt verbergen. So ist es schon auf vielen Webseiten üblich, in einer Auswahlliste mehrere Navigationsziele anzugeben. Sobald Sie einen Punkt in der Auswahlliste anklicken, wird die entsprechende Seite aufgerufen.

	Dazu benötigt man einen Event-Handler, der dann aktiv wird, wenn sich die aktuelle Auswahl der Auswahlliste ändert. Dieser Event-Handler heißt onChange und wird im Prinzip von allen Browsern unterstützt. Eine Ausnahme ist die Windows-Version vom Netscape Navigator 2, bei der der Event-Handler erst ausgeführt wird, wenn der Benutzer irgendeinen anderen Teil der Webseite anklickt – beispielsweise einen leeren Bereich der Seite. Aus diesem Grund sollte man für Benutzer dieses Browsers eine weitere Schaltfläche anbieten. Zwar würde es genügen, wenn man diese Schaltfläche mit keiner Aktion hinterlegt – wie gesagt, ein Klick irgendwo andershin genügt –, aber es gibt Berichte, dass auch das mitunter den onSelect-Event-Handler nicht aktiviert. Aus diesem Grund sollte diese Schaltfläche ebenfalls den erforderlichen JavaScript-Code ausführen.
	Im unteren Beispiel wird wieder eine Referenz auf das aktuelle Formular an die JavaScript-Funktion übergeben. Die URLs werden in einem Array gespeichert. Um zum Netscape Navigator 2 kompatibel zu sein, wird dieses Array mit der bekannten MakeArray()-Funktion generiert.

<HTML>
<HEAD>
<TITLE>Navigation mit JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function MakeArray(n){
   this.length = n
   return this
}
var urls = new MakeArray(4)
urls[0] = "" //leere URL für oberste Option
urls[1] = "http://www.netscape.com/de"
urls[2] = "http://www.microsoft.com/germany"
urls[3] = "http://www.opera.com"
function laden(f){
   if (f.auswahl.selectedIndex>0)
      location.href = urls[f.auswahl.selectedIndex]
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Navigation mit JavaScript</H3>
<FORM>
<SELECT NAME="auswahl" onChange="laden(this.form)">
 <OPTION>Bitte wählen</OPTION>
 <OPTION>Netscape</OPTION>
 <OPTION>Microsoft</OPTION>
 <OPTION>Opera</OPTION>
</SELECT>
<INPUT TYPE="BUTTON" VALUE="Laden" onClick="laden(this.form)">
</FORM>
</BODY>
</HTML>

7.4 Fragen & Aufgaben

1.	Schreiben Sie ein Skript, das eine Laufschrift in einem schreibgeschützten Texteingabefeld realisiert.
2.	Erweitern Sie die Laufschrift aus der vorherigen Aufgabe zu einem News-Ticker. Eine bestimmte Anzahl von Hinweistexten wird nacheinander als Laufschrift angezeigt. Wenn der Benutzer in das Texteingabefeld klickt (Event-Handler: onClick), wird die zum Text gehörige URL geladen.
3.	Die universelle Formularüberprüfung scheitert, wenn das name-Attribut der Gruppe aus Radiobuttons Sonderzeichen enthält (z. B. Leerzeichen, Bindestrich). Ändern Sie das Listing so ab, dass dieser Fehler nicht mehr auftritt!
4.	In der Praxis ist nicht jedes Formularfeld ein Pflichtfeld. Wie könnte man in einem Formular ein Pflichtfeld kennzeichnen, aber die Vollständigkeitsüberprüfung trotzdem mit einer universell einsetzbaren Funktion erledigen?
5.	Ändern Sie das Navigationsbeispiel mit der Auswahlbox ab, so dass die Ziel-URLs nicht in einem Array gespeichert werden, sondern im VALUE-Attribut des <OPTION>-Tags.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 8 Fenster II: Frames
			8.1 Mit Frames arbeiten
			8.2 Auf Daten von Frames zugreifen
			8.3 Ein Warenkorb in JavaScript
			8.4 Diashow
			8.5 Fragen & Aufgaben

Kapitel 8 Fenster II: Frames

Fensterln: nachts zu einem Mädchen ans Fenster gehen

[und durchs Fenster zu ihm ins Zimmer klettern]

– Duden in acht Bänden

Das window-Objekt steht in der Objekthierarchie ganz oben. Dies ist verständlich, da alles, was man mit JavaScript anstellen kann, in irgendeiner Art von Fenster dargestellt wird. Wenn also eine Webseite aus mehreren Frames besteht, wird jeder dieser Frames wie ein Fenster behandelt, zumindest im Sinne von JavaScript. Sie sehen, es gibt viele verschiedene Anwendungen für dieses Objekt. Aus diesem Grund wird das Thema in drei Kapiteln behandelt.

In diesem Kapitel werden Sie erfahren, wie man mit JavaScript auf Frames zugreift und damit beispielsweise seine Navigation flexibler gestalten kann. Außerdem wird Schritt für Schritt eine der JavaScript-Standardanwendungen implementiert: eine Warenkorblösung.

8.1 Mit Frames arbeiten

Unter einem Frame versteht man einen Bereich im Browser-Fenster, der – genau wie das Browser-Fenster selbst – einen eigenen Scroll-Balken haben kann und unabhängig vom Rest der Webseite gescrollt werden kann. Frames tauchten das erste Mal im Netscape Navigator 2 auf und wurden sehr schnell von Webdesignern übernommen, erlaubten Frames doch eine bequeme Navigation. Viele Seiten bestanden zunächst aus zwei Frames: Der eine enthielt die Navigationspunkte, der zweite die eigentlichen Inhalte der Seite. Da sich die Navigation in dem Frame befand, musste sie nicht in die Seiten mit dem eigentlichen Inhalt mit eingeschlossen werden, was den Verwaltungsaufwand bei Änderungen verringerte (nur die Seite mit der Navigation musste angepasst werden, jedoch nicht jede einzelne Inhaltsseite). Der Internet Explorer übernahm Frames in der Version 3, und schon begannen die Webdesigner zu fluchen, da die Implementierung von Frames leicht unterschiedlich war (Stichwort: Abstand des Frame-Inhalts vom Frame-Rand). Mittlerweile geht der Trend zu Seiten ohne Frames zurück, auch in Hinblick auf Handhelds, deren eingeschränkte Browser oft mit Frames nichts anfangen können. Dennoch können Sie in Verbindung mit JavaScript mit Frames erstaunliche Dinge machen – Dinge, die ohne Frames nur mit Schwierigkeiten oder gar nicht realisiert werden könnten.

Mit JavaScript ist es möglich, von einem Frame aus Methoden, Eigenschaften und Variablen eines anderen Frames aufzurufen. Im Folgenden erfahren Sie zunächst etwas über den strukturellen Aufbau von Frames, und dann, wie diese Strukturen in JavaScript nachgebildet worden sind.

8.1.1 Frames mit HTML

Eine Frame-Struktur wird immer mit dem HTML-Tag <FRAMESET> eingeleitet. Es wird genau einer der beiden folgenden Parameter erwartet:

	ROWS: Die einzelnen Frames werden untereinander (in Zeilen, engl. rows) angeordnet.
	COLS: Die einzelnen Frames werden nebeneinander (in Spalten, engl. columns) angeordnet.

Als Wert für diesen Parameter werden – durch Kommata getrennt – die Höhen (bei ROWS) oder Breiten (bei COLS) der einzelnen Frames erwartet. Dabei haben Sie die Wahl zwischen drei Optionen:

	Angabe in Pixeln: Lediglich der numerische Wert wird angegeben.
	Angabe in Prozent der Gesamthöhe/-breite des Fensters, welches das <FRAMESET> enthält.
	»Rest«: Wird durch einen Stern (*) symbolisiert.

Diese Möglichkeiten können natürlich miteinander kombiniert werden. Da dieses Buch keine HTML-Einführung sein soll, folgen hier nur ein paar kurze Beispiele:

	<FRAMESET ROWS="100,200,300">: Drei Frames, untereinander angeordnet. Im Idealfall hat der oberste Frame eine Höhe von 100 Pixeln, der mittlere eine von 200 Pixeln, der untere eine von 300 Pixeln. Das ist deswegen ein Idealfall, da das Browser-Fenster wahrscheinlich nicht exakt 600 Pixel hoch ist.
	<FRAMESET COLS="100,50%,*">: Drei Frames, nebeneinander angeordnet. Der mittlere nimmt die halbe Breite ein, der linke ist exakt 100 Pixel breit, und der dritte Frame beansprucht die restliche Breite für sich. Sollte sich also die Breite des Browser-Fensters verändern, ändern gleichzeitig auch der mittlere und rechte Frame ihre Breite, der linke Frame bleibt jedoch in der Größe konstant.

Mit <FRAMESET> wird also die Frame-Struktur festgelegt – über die individuellen Inhalte der Frames wurde damit noch nichts ausgesagt. Hierfür ist der <FRAME>-Tag zuständig, der in seinem SRC-Attribut die URL des Dokuments enthält, das in dem entsprechenden Frame dargestellt werden soll.

Für jeden Frame muss – innerhalb der FRAMESET-Struktur – entweder ein <FRAME>-Tag verwendet werden oder ein weiterer <FRAMESET>-Tag. So können auch mehrere Framesets ineinander verschachtelt werden. In den folgenden Abschnitten wird die folgende Frame-Struktur als Vorbild verwendet:

<HTML>
<HEAD><TITLE>Frames</TITLE></HEAD>
<FRAMESET COLS="150,*">
  <FRAME NAME="A" SRC="a.html">
  <FRAMESET ROWS="100,*">
    <FRAME NAME="B" SRC="b.html">
    <FRAME NAME="C" SRC="c.html">
  </FRAMESET>
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

Abbildung 8.1  Die Beispielseite im Browser

Zur Erläuterung: Das Browser-Fenster wird zunächst vertikal in zwei Bereiche geteilt: Der linke wird mit der Datei a.html gefüllt, der rechte wird horizontal in zwei Frames geteilt, wovon der obere die Datei b.html und der untere die Datei c.html enthält. In Abbildung 8.1 sehen Sie, wie das ganze im Browser aussieht.

8.1.2 Frames mit JavaScript füllen

	Kleines Quiz: Wie bekommt man eine leere Seite in einen Frame? Netscape-Veteranen erinnern sich vielleicht an die Abkürzung about:blank, die seit Version 1 eine leere Seite erzeugt. Der Internet Explorer 3 mag das jedoch gar nicht und gibt eine Fehlermeldung aus (vgl. Abbildung 8.2).
Abbildung 8.2  Fehlermeldung beim Internet Explorer 3

Mit JavaScript ist es jedoch möglich, den Startinhalt eines Frames direkt in der Seite mit dem Frameset festzulegen. Das ist eigentlich gar nichts Neues. Sie wissen ja schon längst, wie man eine JavaScript-Funktion via URL aufrufen kann: mit dem JavaScript-Protokoll. Ganz nebenbei kann man damit auch noch andere Dinge erzeugen als eine leere Seite. Betrachten Sie folgendes Beispiel:

Abbildung 8.3  Mit JavaScript gefüllte Frames

<HTML>
<HEAD><TITLE>Frames</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function tag(s){
  return "<"+s+">"
}
function leer(){
  html = tag("HTML")+tag("BODY")+tag("/BODY")+tag("/HTML")
  return html
}
function voll(s){
  html = tag("HTML")+tag("BODY")
  html += tag("H3")+s+tag("/H3")
  html += tag("/BODY")+tag("/HTML")
  return html
}
//--></SCRIPT>
</HEAD>
<FRAMESET COLS="150,*">
   <FRAME NAME="A" SRC="javascript:top.voll('linker Frame')">
   <FRAMESET ROWS="100,*">
      <FRAME NAME="B" SRC="javascript:top.leer()">
      <FRAME NAME="C" SRC="javascript:top.voll('rechts unten')">
   </FRAMESET>
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

Im Browser sieht diese Seite dann so ähnlich wie in Abbildung 8.3 aus, vorausgesetzt natürlich, Ihr Browser unterstützt JavaScript! Was übrigens das top. vor dem Funktionsnamen bedeutet, erfahren Sie ein paar Abschnitte später.

8.2 Auf Daten von Frames zugreifen

Wie bereits erwähnt, werden Frames in JavaScript wie Fenster behandelt. Mit den Schlüsselworten this und self erhält man also eine Referenz auf den aktuellen Frame – oder eben das aktuelle Fenster, wenn die Seite keine Frames enthält.

Auf sich selbst zuzugreifen ist aber nicht sonderlich interessant, und erst recht nichts Neues. Viel eher ist es wichtig, wie man von einer Webseite aus auf die Unterframes zugreifen kann, und wie man – von einem Frame aus – auf das in der Hierarchie eine Stufe über einem stehende Element zugreifen kann. Um das anhand eines praktischen Beispiels einmal durchzuführen, wird das Standardbeispiel für diesen Abschnitt leicht verändert:

Das Hauptdokument, es heißt in unserem Beispiel frameset.html, hat folgenden Aufbau:

<HTML>
<HEAD><TITLE>Frames</TITLE></HEAD>
<FRAMESET COLS="150,*">
  <FRAME NAME="A" SRC="a.html">
  <FRAME NAME="B" SRC="b.html">
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

Die Datei b.html enthält wiederum ein Frameset:

<HTML>
<HEAD><TITLE>Noch mehr Frames</TITLE></HEAD>
<FRAMESET ROWS="100,*">
    <FRAME NAME="C" SRC="c.html">
    <FRAME NAME="D" SRC="d.html">
  </FRAMESET>
</HTML>

Abbildung 8.4 veranschaulicht noch einmal den Aufbau: Die Hauptseite enthält zwei Frames – links a.html, rechts b.html, welche sich in die zwei Frames mit Inhalt c.html (oben) und d.html (unten) aufteilt.

Abbildung 8.4  Die Beispielseite im Browser

8.2.1 Auf übergeordnete Frames zugreifen

Wenn Sie in HTML codieren wollen, dass sich das Ziel eines Links nicht im aktuellen Frame öffnet, sondern das gesamte Browser-Fenster für sich beansprucht, machen Sie das für gewöhnlich folgendermaßen:

<A HREF="seite.htm" TARGET="_top">Hier klicken</A>

Bei JavaScript heißt das Schlüsselwort ganz ähnlich: top. Hiermit erhalten Sie eine Referenz auf das oberste Fenster in der gesamten Frame-Hierarchie. Egal, ob Sie sich in a.html, c.html oder gar frameset.html befinden – top.location enthält immer "frameset.html" (sowie den Pfad zu dieser Datei).

Oft ist es jedoch von Nutzen, in der Hierarchie nur eine Stufe nach oben zu gelangen, also in unserem Beispiel etwa von c.html eine Referenz auf den Frame mit b.html zu erhalten. Das Schlüsselwort heißt hier parent (dt. »Elternteil«). Wenn Sie sich also in c.html befinden, enthält parent. location "b.html"; von dieser Datei aus wiederum enthält parent.location "frameset.html".

	Mit parent erhält man bildlich betrachtet immer eine Referenz auf das Dokument, die den <FRAMESET>-Tag enthält, der den Frame mit der aufrufenden Datei enthält. Sind in einer Datei also mehrere Framesets ineinander verschachtelt, stehen diese dennoch in der Frame-Hierarchie auf einer Ebene.

Einige Seiten, die ihre Navigation mit Frames erledigen, stellen externe Links in einem ihrer Frames dar, sodass die eigene Navigation immer noch sichtbar bleibt, die fremde Website also in einem Unterframe einer anderen Website dargestellt wird. Das ist zum einen unfreundlich und zum anderen auch schon ein paar Mal erfolgreich an- bzw. abgemahnt worden. Wenn Sie verhindern wollen, dass Ihre Seiten innerhalb eines fremden Framesets dargestellt werden, haben Sie die folgenden Möglichkeiten, die alle auf demselben Prinzip beruhen: Wenn wir uns nicht im obersten Frame in der Hierarchie befinden, dann machen wir uns zum obersten Frame in der Hierarchie!

<SCRIPT LANGUAGE="JavaScript"><!--
if (self != top) top.location = self.location
//--></SCRIPT>

oder

<SCRIPT LANGUAGE="JavaScript"><!--
if (self != parent) top.location = self.location
//--></SCRIPT>

Bauen Sie dieses Skript in all Ihre Webseiten ein, und Sie werden nie wieder von fremden Framesets belästigt werden!

Es gibt jedoch auch noch einen anderen Fall: Ein Besucher Ihrer Webseiten setzt ein Lesezeichen (Bookmark) auf eine Seite in einem Frame. Wenn er jedoch das Lesezeichen wieder aufruft, wird lediglich die eine Seite geladen, nicht jedoch die anderen Frames, die beispielsweise die gesamte Navigation enthalten.

Um das ganze ein wenig anschaulicher zu machen, folgt hier eine Konkretisierung der Aufgabenstellung. Ihre Website besteht aus zwei Frames: Der linke enthält die Navigation, der rechte den Inhalt. Ihre index.html-Datei sieht folgendermaßen aus:

<HTML>
<HEAD><TITLE>Homepage mit Frames</TITLE></HEAD>
<FRAMESET COLS="150,*">
  <FRAME SRC="navigation.html" NAME="Navi">
  <FRAME SRC="inhalt.html" NAME="Inhalt">
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

In allen Unterseiten sollte nun überprüft werden, ob ein Frameset existiert; wenn nicht, soll das Frameset aufgebaut werden. Dies geschieht mit ein wenig JavaScript: Die URL der aktuellen Seite wird über die Kommandozeile an eine Datei frameset.html übergeben, die die Framestruktur erzeugt.

Der folgende Code gehört in alle Unterseiten:

<SCRIPT LANGUAGE="JavaScript"><!--
if (self == top) location.href = "frameset.html?" + location.href
//--></SCRIPT>

Die Datei frameset.html wertet die Kommandozeile aus und baut – mittels document.write() – die Frame-Struktur auf. Beachten Sie, dass Sie das gesamte Frameset mit JavaScript erzeugen müssen, eine Mischung ist nicht möglich (zwar syntaktisch prinzipiell korrekt, die Browser kommen damit aber nicht zurecht).

<HTML>
<HEAD><TITLE>Homepage mit Frame</TITLE></HEAD>
<SCRIPT>
function tag(s) { document.write("<" + s + ">") }
tag('FRAMESET COLS="150,*"')
tag('FRAME SRC="navigation.html" NAME="Navi"')
seite = location.search.substring(1, location.search.length)
   //beginnt mit "?" !
tag("FRAME SRC='" + seite + "' NAME='Inhalt'")
tag("/FRAMESET")
</SCRIPT>
</HTML>

	Denken Sie daran, dass location.search mit einem Fragezeichen beginnt; Sie dürfen daher die Zeichenkette erst ab dem zweiten Zeichen (hat den Index 1) auswerten.

Die mit JavaScript generierten Framesets lassen sich noch weiter verfeinern. Wenn Sie eine größere Website haben, wird sich im (fiktiven) linken Frame nicht immer dieselbe Navigation befinden. Sie können mehrere Frameset-Dateien erstellen und – je nach aufgerufener Unterseite – einen Link auf eine bestimmte dieser Frameset-Seiten setzen. Stellen Sie sich folgende Zuordnungstabelle vor (Tabelle 8.1):

Tabelle 8.1  URLs und zugehörige Frameset-Dateien

URL-Format	Zugehöriger Frameset
/produkte/...	frameset1.html
/investorrelations/...	frameset2.html
Sonstige	frameset3.html

 Der Code könnte hier folgendermaßen aussehen:

<SCRIPT LANGUAGE="JavaScript"><!--
if (self == top) {
if location.href.indexOf("/produkte")>=0
   location.href = "frameset1.htm?" + location.href
if location.href.indexOf("/investorrelations")>=0
   location.href = "frameset2.htm?" + location.href
location.href = "frameset3.htm?" + location.href
}
//--></SCRIPT>

	Bei einem Schreibzugriff auf location.href wird sofort die neue Seite geladen; dahinter folgender JavaScript-Code wird nicht mehr ausgeführt. Sauberer wäre es natürlich, mit else zu arbeiten.
	Der Netscape Navigator 4 hat einen Bug, der dazu führen könnte, dass Seiten nicht mehr korrekt ausgedruckt werden, wenn Sie mit JavaScript auf eine Frameset-Seite umleiten, wenn kein Frameset vorhanden ist. Die Ursache liegt darin, dass der Netscape-Browser vor dem Drucken das Dokument manchmal neu lädt, und zwar unabhängig von anderen Frames. Die JavaScript-Routinen werden ausgeführt, stellen keine Frames fest und wollen daher auf eine andere Seite umleiten – das führt zu Fehlern beim Druck. Sollte dieses Phänomen bei Ihnen auftreten, bieten Sie Ihren Besuchern wenigstens eine druckbare Version Ihrer Seiten an (eine Version der jeweiligen Seite ohne JavaScript).

8.2.2 Auf Daten von Unterframes zugreifen

Referenzen auf die Unterframes eines Fensters werden in dem Array frames[] (um genau zu sein, unter window.frames[] oder self.frames[] oder this.frames[]) gespeichert. Wenn Sie in der Datei frameset.html auf den linken Frame zugreifen wollen, haben Sie folgende Möglichkeiten:

	window.A
	window.frames[0]
	window.frames["A"]

Aber immer der Reihe nach:

	window.A: A ist der Wert des NAME-Attributs des entsprechenden Frames. Zwei Dinge sollten Ihnen hier deutlich werden: Geben Sie jedem Frame einen einprägsamen Namen, und verwenden Sie keine JavaScript-Begriffe (beispielsweise sollten Sie den Frame nicht "location" nennen, Sie können auf ihn dann nicht mit window.location zugreifen).
	window.frames[0]: Wie bereits erwähnt, werden Referenzen auf alle Frames in der jeweiligen HTML-Seite in dem Array frames[] abgespeichert. Wie bei allen JavaScript-Arrays beginnt der Index bei 0, frames[0] bezeichnet also den ersten Frame. Die Frames werden dabei nach dem Vorkommen im HTML-Dokument nummeriert. Mit frames[1] erhält man also eine Referenz auf den zweiten Frame in der Beispielseite (b.html).
	window.frames["A"]: Eine Mischung aus beiden Varianten. Hier kann man auch auf Frames mit speziellen Namen wie etwa "location" zugreifen. Diese Methode bedeutet jedoch recht viel Tipparbeit, und Sie werden sie sehr selten sehen. Je nachdem, wie einprägsam Ihre Frame-Namen sind, sollten Sie eine der beiden ersten Methoden verwenden.

Abbildung 8.5 verdeutlicht die Zugriffsmöglichkeiten auf andere Frames noch einmal.

Abbildung 8.5  Zugriffsmöglichkeiten auf andere Frames

	Mit diesem Wissen können Sie fremden Frames auch noch auf die folgenden Weisen entkommen. Denken Sie daran: Wenn Sie sich im obersten Frame in der Hierarchie befinden, zeigen parent und top auf das aktuelle Fenster:

<SCRIPT LANGUAGE="JavaScript"><!--
if (top.frames.length>0) top.location = self.location
//--></SCRIPT>

oder

<SCRIPT LANGUAGE="JavaScript"><!--
if (parent.frames.length>0) top.location = self.location
//--></SCRIPT>

Sie sehen hieran schon, wie man die beiden Methoden – top und parent bzw. frames[] – miteinander kombinieren kann: Will man auf einen Frame zugreifen, der sich in derselben Hierarchie-Ebene befindet, so greift man mit top oder (ggfs. mehrfacher Anwendung von) parent auf den nächsten gemeinsamen Vorfahren der beiden Frames zu und geht dann über frames[] in der Hierarchie wieder hinab. Um im Beispiel von oben von dem Frame mit der Datei c.html zu dem Frame mit der Datei d.html zu gelangen, gibt es folgende Möglichkeiten:

	parent.D
	top.B.frames[1]
	parent.parent.B.D

Wenn Sie Zugriff auf den Frame haben, können Sie damit auch auf alle Eigenschaften des Frames oder seiner Unterobjekte zugreifen, beispielsweise document, location, oder auch auf globale Variablen im JavaScript-Code des Frames.

8.2.3 Mehrere Frames gleichzeitig ändern

Eine der Fragen, die in Newsgroups am häufigsten gestellt werden, lautet: »Wie kann ich den Inhalt mehrerer Frames gleichzeitig ändern?« Dies ist eine Problemstellung, die tatsächlich häufig vorkommt. Denken Sie an eine der Standardanwendungen für Frames: die Navigation. Wenn Sie einen Punkt in der Navigation auswählen, wird (in einem anderen Frame) die entsprechende Inhaltsseite geladen. Jedoch kann es auch vorkommen, dass sich das Aussehen der Navigation selbst ändern soll (beispielsweise soll der gerade ausgewählte Navigationspunkt hervorgehoben werden, damit der Benutzer weiß, wo er sich befindet).

Dieser Effekt ist sehr einfach umzusetzen. Auf die oben aufgezeigte Art und Weise wird auf die entsprechenden Frames zugegriffen und die Eigenschaft location.href entsprechend verändert. Hier lohnt es sich, eine eigene Funktion zu schreiben, die Sie wieder verwenden können. Als Parameter werden Referenzen auf die Frames sowie die zu ladenden URLs übergeben:

<SCRIPT LANGUAGE="JavaScript"><!--
function ZweiFrames(frame1, url1, frame2, url2){
  frame1.location.href = url1
  frame2.location.href = url2
}
//--></SCRIPT>

Stellen Sie sich vor, im vorherigen Beispiel befinden Sie sich im Frame A und wollen via Link in Frame C die Seite cc.html sowie in Frame D die Seite dd.html laden. Sie können das folgendermaßen tun:

<A HREF="javascript:ZweiFrames(parent.B.C, 'cc.html',
  parent.B.D, 'dd.html')">hier klicken</A>

Sie sollten jedoch immer eine Alternative bereithaben, wenn der Browser des Benutzers kein JavaScript unterstützt. In diesem Fall ist das relativ einfach: Wenn Sie sich die Beispielseite noch einmal anschauen, sehen Sie, dass die Frames C und D in der Datei b.html definiert werden. Sie könnten also alternativ eine Datei bb.html erstellen, die folgendermaßen aussieht:

<HTML>
<HEAD><TITLE>Noch mehr Frames</TITLE></HEAD>
<FRAMESET ROWS="100,*">
    <FRAMESET NAME="C" SRC="cc.html">
    <FRAMESET NAME="D" SRC="dd.html">
  </FRAMESET>
</HTML>

Der Link vereinfacht sich dann zu Folgendem puren HTML:

<A HREF="bb.html" TARGET="B">hier klicken</A>

Überlegen Sie also immer, ob Sie die Aufgabenstellung auch ohne JavaScript lösen können. Sie vergrößern damit das mögliche Publikum für Ihre Webseite.

8.2.4 Gefährliche Fallen

Wenn Sie eine größere Website mit Frames aufgebaut haben und recht viel JavaScript verwenden, lohnt es sich natürlich, oft benutzte Befehle in Funktionen auszulagern und diese Funktionen auf irgendeine Seite in einem der Frames zu schreiben. Mittels top, parent und frames[] kann dann auf diese Funktion zugegriffen werden. Ein nahe liegender Ansatz ist es, die Funktionen in der obersten Seite der Hierarchie, also der Seite mit dem Haupt-Frameset abzulegen. Die Funktionen können dann mit top.funktionsname() aufgerufen werden.

	Dieses Vorgehen hat jedoch einen großen Haken: Manche ältere Versionen des Microsoft Internet Explorer, insbesondere die 16-Bit-Version 3.x, liefern eine Fehlermeldung, wenn Sie versuchen, auf eine JavaScript-Funktion im Hauptdokument zuzugreifen.
	Ein weiterer Bug tritt in alten Versionen des Netscape Navigator (um genau zu sein: Version 2) auf. Wenn Sie von einem Unterframe aus eine Variable im Hauptdokument ändern und das Dokument im Unterframe verschwindet (indem zum Beispiel ein anderes Dokument in diesen Frame geladen wird), passiert es mitunter, dass die Variable ihren Wert unkontrollierbar ändert oder ganz verschwindet.

All diese Effekte lassen sich größtenteils vermeiden, wenn alle JavaScript-Funktionen und globalen Variablen in einem Frame abgelegt werden; idealerweise in einem Frame, der sich nie ändert (beispielsweise ein Navigationsframe). Alternativ dazu können Sie auch auf einen alten HTML-Trick zurückgreifen und einen unsichtbaren Frame verwenden. Der folgende Code erzeugt zwei Frames, wovon der zweite jedoch nicht sichtbar ist, da er nur einen Pixel hoch ist. In diesem Frame lassen sich bequem Funktionen und Variablen ablegen.

<HTML>
<HEAD><TITLE>Unsichtbarer Frame</TITLE></HEAD>
<FRAMESET ROWS="*,1" BORDER=0 CELLSPACING=0 FRAMEBORDER=0>
  <FRAME NAME="sichtbar" SRC="inhalt.htm">
  <FRAME NAME="unsichtbar" SRC="skript.htm">
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

8.3 Ein Warenkorb in JavaScript

E-Commerce ist ein ganz heißes Thema im Web. Anhand von Diskussionen über Hype und Wahrheit in der Fachpresse kann man die Materie wie folgt zusammenfassen: Verkaufen über das Web ist ›in‹. Viele kleinere Firmen haben jedoch ein Problem damit: Sofern man dem Kunden etwas mehr bieten will als ein ordinäres Bestellformular (wobei auch darin ziemlich viel Technik stecken kann, wie Sie bereits gelesen haben), braucht man ein Warenkorbsystem. Die meisten der erhältlichen Systeme sind jedoch serverseitige Lösungen und in Sprachen wie Perl programmiert – was die meisten Hoster nur in ihren teureren Paketen unterstützen. Mit JavaScript ist es jedoch ohne größeren Aufwand möglich, sich selbst eine Warenkorblösung zu bauen. Es existieren im World Wide Web sogar kommerzielle Lösungen, die vollständig oder zum größten Teil in JavaScript programmiert worden sind.

Im Rahmen dieses Kapitels kann nur eine kleinere Lösung entwickelt werden. Für viele Ansprüche genügt diese bereits, und Erweiterungen sind – nach der Lektüre dieses Buchs – kaum Grenzen gesetzt.

Die einfache Lösung, die in den nächsten Abschnitten entwickelt wird, soll Folgendes leisten:

	Speicherung von Anzahl, Preis und Beschreibung der einzelnen Waren
	Ausgabe des Warenkorbs nebst Berechnung der Gesamtsumme
	Änderungen am Warenkorb

Diese drei Punkte werden nacheinander abgearbeitet.

8.3.1 Daten in den Warenkorb eintragen

Die allererste Frage, die man sich stellen sollte, lautet: »Wie speichere ich die Daten?« Es gibt hier mehrere Möglichkeiten:

	Für Anzahl, Preis und Beschreibung wird jeweils ein Array angelegt und bei jedem neuen Artikel, der in den Warenkorb gelegt wird, wird ein neuer Eintrag angefügt. Wie Sie schon erfahren haben, ist das Array-Objekt bei älteren Browser-Versionen nur ungenügend implementiert, weshalb diese Lösung – im Hinblick auf ein möglichst großes Publikum – leider ausscheidet.
	Für Anzahl, Preis und Beschreibung gibt es je eine Variable. Wenn ein weiterer Artikel in den Warenkorb gelegt wird, werden die entsprechenden Werte, durch ein Seperatorzeichen (z. B. »|«) getrennt, an die jeweiligen Variablen angehängt. Wenn Sie also zwei Artikel haben, die 10 beziehungsweise 20 Euro kosten, und Sie davon 3 beziehungsweise 4 Stück in den Warenkorb legen, hat die Anzahlvariable den Wert "3|4|", die Preisvariable "10|20|" und die Beschreibungsvariable sieht ungefähr so aus: "Beschreibung 1|Beschreibung 2|".
	Jeder Wert von Anzahl, Preis und Beschreibung wird in einer eigenen Variablen gespeichert. Diese Methode ist nicht sehr effizient und erfordert den häufigen Einsatz von eval().

Im Folgenden wird die zweite Methode eingesetzt. Der einzige Fallstrick hierbei: Wählen Sie ein Trennzeichen, das auf keinen Fall in der Artikelbeschreibung vorkommt, ansonsten wird es schwierig, am Ende die verschiedenen Daten wieder »auseinander zu fieseln«.

Wir beginnen wird mit dem HTML-Gerüst für die Warenkorbapplikation. Es wird ein unsichtbarer Frame verwendet, der zur Speicherung von Variablen und wichtigen Funktionen benötigt wird:

<HTML>
<HEAD><TITLE>Warenkorb</TITLE></HEAD>
<FRAMESET ROWS="*,1" BORDER=0 CELLSPACING=0 FRAMEBORDER=0>
  <FRAME NAME="inhalt" SRC="inhalt.html">
  <FRAME NAME="korb" SRC="korb.html">
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

Der Plan ist nun Folgender: Wir erstellen eine Funktion einfuegen() und übergeben dieser als Parameter Anzahl, Preis und Beschreibung des betreffenden Artikels. Wie die Funktion dann von einer Seite aus aufgerufen wird, kümmert uns erst später; zunächst kümmern wir uns um die Funktion. Beachten Sie, dass die Variablen für Anzahl, Preis und Beschreibung unbedingt außerhalb der Funktion definiert werden müssen – ansonsten ist die Variable nur lokal gültig, und der Wert geht nach Beendigung der Funktion verloren.

Folgender Code muss also in der Datei korb.html stehen:

<HTML>
<HEAD><TITLE>Warenkorb</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function istZahl(n){
  s = ""+n
  var ziffern = "0123456789"
  for (var i=0; i<s.length; i++)
    if (ziffern.indexOf(s.charAt(i))<0) return false
  return true
}
var anzahl = ""
var preis = ""
var beschreibung = ""
function einfuegen(a, p, b){
  var anz = (istZahl(a) ? a : "0")
  anzahl += anz + "|"
  preis += p + "|"
  beschreibung += b + "|"
}
//--></SCRIPT>
</HEAD>
<BODY></BODY>
</HTML>

In dem oben abgedruckten Code passiert gar nicht so viel: Die drei Variablen anzahl, preis und beschreibung werden in der Funktion einfuegen() einfach die übergebenen Parameter sowie um das Trennzeichen "|" ergänzt. Als einzige Besonderheit wird überprüft, ob die angegebene Anzahl eine natürliche Zahl ist. Das liegt daran, dass Preis und Beschreibung für jeden Artikel fest sind, die Anzahl aber von Hand eingegeben werden soll, sodass auch unsinnige Werte übergeben werden könnten.

Viel interessanter ist es jedoch, wie diese Werte an die Funktion übergeben werden. Dazu stellen Sie sich bitte Folgendes vor: Sie haben mehrere Seiten, auf denen Sie Ihre Produkte vorstellen. Auf jeder dieser Seiten sollte der Benutzer die Möglichkeit haben, den entsprechenden Titel in den Warenkorb einzufügen, und zwar in jeder beliebigen Anzahl. Es bietet sich hier ein kleines Formular an:

<HTML>
<HEAD><TITLE>Beispielartikel für den Warenkorb</TITLE></HEAD>
<BODY>
<H3>M. Proust I</H3>
Das 1. Werk des französischen Autors; 20,55 Euro
<FORM>
<INPUT TYPE="TEXT" NAME="Anzahl" SIZE=2 VALUE="1"> Stück
<INPUT TYPE="BUTTON" VALUE="In den Warenkorb" onClick="">
</FORM>
</BODY>
</HTML>

Abbildung 8.6  Die Warenkorbanwendung

Im Browser sieht das ungefähr so wie in Abbildung 8.6 aus. Fehlt nur noch ein Punkt: Wie muss der onClick-Parameter der Schaltfläche gesetzt werden? Die Funktion einfuegen() muss aufgerufen werden, und als Parameter werden ihr Anzahl, Preis und Beschreibung des Artikels (in dieser Reihenfolge) übergeben. Beachten Sie bitte, dass in JavaScript Dezimalstellen nicht durch ein Komma abgetrennt werden, sondern durch einen Punkt; aus diesem Grund sollte der Preis des Artikels gleich in diesem Format übergeben werden, damit später nicht erst umständlich umgewandelt werden muss. Der onClick-Parameter kann also folgendermaßen gesetzt werden:

onClick="top.korb.einfuegen(this.form.Anzahl.value, '20.55',
'Proust I.')"

Sie können nun mehrere Seiten mit Artikeln erstellen. Wenn Sie in all diese Seiten das Formular von oben einfügen (natürlich angepasst mit den entsprechenden Preisen und Beschreibungen), haben Sie schon einen wunderbar funktionierenden Warenkorb – nur können Sie bis jetzt nur Waren hineinlegen, aber noch nicht nachschauen, was sich denn überhaupt im Warenkorb befindet.

8.3.2 Daten aus dem Warenkorb auslesen

	Für die Anzeige des Warenkorbs müssen die Variablen für Anzahl, Preis und Beschreibung in die Daten für die einzelnen Posten aufgespalten werden. Ab JavaScript 1.1 gibt es die bequeme Methode split() - aber der Warenkorb soll auch unter JavaScript 1.0 laufen, also muss die Methode von Hand programmiert werden.

Im folgenden Programmcode wird in dieser Reihenfolge vorgegangen:

1.	Das nächste Trennzeichen (»|«) wird gesucht; alle Zeichen bis dort hin werden in einer Variablen gespeichert (diese Variable enthält dann also entweder die Anzahl, den Preis oder die Beschreibung des aktuellen Produkts).
2.	Alle Zeichen bis einschließlich des ersten Trennzeichens werden abgeschnitten.
3.	Die Werte, die zuvor in Variablen gespeichert worden sind, werden verwertet (zunächst werden sie lediglich ausgegeben und die Summen addiert).
4.	Wenn die Variable für Anzahl, Preis bzw. Beschreibung noch Zeichen enthält, wird wieder zu Schritt 1 gesprungen.

Die Funktionsweise dieses Algorithmus soll am folgenden Beispiel kurz erklärt werden.

Ausgegangen wird von der Zeichenkette "10|20|", welche die Preise der verschiedenen Posten im Warenkorb darstellt.

1.	Das erste Trennzeichen wird gesucht; die Zeichen davor ("10") in einer Variablen gespeichert.
2.	Alle Zeichen bis einschließlich zum Trennzeichen werden abgeschnitten; übrig bleibt "20|".
3.	Der vorher ermittelte Wert – in diesem Falle "20" – wird ausgegeben.
4.	Die Variable mit den Preisen enthält noch Zeichen, nämlich "20|", es wird also wieder zu Schritt 1 zurückgesprungen. Dort wird dann "20" in einer Variablen gespeichert, alle Zeichen bis zum Trennzeichen werden abgeschnitten, wonach die Preisvariable eine leere Zeichenkette ist und das Programm abgebrochen wird.

Damit der Quellcode etwas übersichtlicher wird, wurden diejenigen Programmstücke, die nach dem nächsten Trennzeichen suchen und die Ausgangsvariablen verkürzen, in Funktionen ausgelagert.

Zuerst schreiben wir die Ausgabeseite, die den Warenkorb anzeigt:

<HTML>
<HEAD><TITLE>Ausgabe des Warenkorbs</TITLE></HEAD>
<BODY>
<H3>Inhalt des Warenkorbs</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
function tag(s){ document.write("<"+s+">") }
tag("TABLE BORDER=1");
tag("TR");
tag("TD"); document.write("Anzahl"); tag("/TD")
tag("TD"); document.write("Beschreibung"); tag("/TD")
tag("TD"); document.write("Einzelpreis"); tag("/TD")
tag("TD"); document.write("Gesamtpreis"); tag("/TD")
tag("/TR")
anzahl="0"
while (anzahl!=""){
  var anzahl = top.korb.naechste_anzahl()
  var preis = top.korb.naechster_preis()
  var beschreibung = top.korb.naechste_beschreibung()
  if (anzahl!=""){
    tag("TR")
    tag("TD"); document.write(anzahl); tag("/TD")
    tag("TD"); document.write(beschreibung); tag("/TD")
    tag("TD"); document.write(preis); tag("/TD")
    tag("TD"); document.write(anzahl*preis); tag("/TD")
    tag("/TR")
  }
}
tag("/TABLE")
//--></SCRIPT>
</BODY>
</HTML>

Folgende Funktionen müssen noch in die Datei korb.html eingefügt werden:

function naechste_anzahl(){
  if (anzahl.indexOf("|")==-1) return ""
  var anz = anzahl.substring(0, anzahl.indexOf("|"))
  anzahl = anzahl.substring(anzahl.indexOf("|")+1)
  return anz
}
function naechster_preis(){
  if (preis.indexOf("|")==-1) return ""
  var pr = preis.substring(0, preis.indexOf("|"))
  preis = preis.substring(preis.indexOf("|")+1)
  return pr
}
function naechste_beschreibung(){
  if (beschreibung.indexOf("|")==-1) return ""
  var bes = beschreibung.substring(0, beschreibung.indexOf("|"))
  beschreibung = beschreibung.substring(beschreibung.indexOf("|")+1)
  return bes
}

Im Browser sieht die Seite dann wie in Abbildung 8.7 aus.

Abbildung 8.7  Die Ausgabeseite der Warenkorbanwendung

8.3.3 Den Warenkorb verändern

Wenn Sie schon einmal online bei Amazon oder ähnlichen Anbietern eingekauft haben, wissen Sie es sicherlich zu schätzen, bei Betrachtung des Warenkorbs die Anzahl der unterschiedlichen Posten ändern zu können und Artikel komplett zu entfernen. Diese Funktionalität soll auch in den einfachen Warenkorb eingebaut werden. Dazu soll Folgendes implementiert werden:

	Wird die Anzahl auf einen Wert ungleich 0 geändert, soll sie auch so im Warenkorb geändert werden.
	Wird die Anzahl jedoch auf den Wert 0 geändert, so wird der Posten aus dem Warenkorb entfernt.

Hierzu müssen zwei Dinge implementiert werden:

	Die Anzahl neben jedem Warenkorbeintrag muss in einem Texteingabefeld stehen.
	Eine Funktion, die am besten im unsichtbaren Frame abgelegt wird, muss die Variablen für Anzahl, Wert und Beschreibung aktualisieren.

Der erste Punkt ist relativ schnell erledigt. Damit die Texteingabefelder später leichter zu identifizieren sind, bekommen sie als Namen "anzahl" sowie die laufende Nummer des Warenkorbpostens, also "anzahl1", "anzahl2" und so weiter. Analog werden der Preis und die Beschreibung in den (unsichtbaren) Feldern "preis1", "preis2" usw. beziehungsweise "beschreibung1", "beschreibung2" usw. festgehalten. Außerdem wird in einem versteckten Formularfeld gespeichert, wie viele Posten der Warenkorb enthält. Das vereinfacht später die Aktualisierung.

Die Ausgabeseite wird folgendermaßen geändert (neuer oder aktualisierter Code ist fett dargestellt).

<HTML>
<HEAD><TITLE>Ausgabe des Warenkorbs</TITLE></HEAD>
<BODY>
<H3>Inhalt des Warenkorbs</H3>
<FORM>
<SCRIPT LANGUAGE="JavaScript"><!--
function tag(s){ document.write("<"+s+">") }
tag("TABLE BORDER=1");
tag("TR");
tag("TD"); document.write("Anzahl"); tag("/TD")
tag("TD"); document.write("Beschreibung"); tag("/TD")
tag("TD"); document.write("Einzelpreis"); tag("/TD")
tag("TD"); document.write("Gesamtpreis"); tag("/TD")
tag("/TR")
posten = 0
anzahl="0"
while (anzahl!=""){
  var anzahl = top.korb.naechste_anzahl()
  var preis = top.korb.naechster_preis()
  var beschreibung = top.korb.naechste_beschreibung()
  if (anzahl!=""){
    posten++
    tag("TR")
    tag("TD");
    tag("INPUT TYPE='TEXT' NAME='anzahl"+posten+"' SIZE=2 VALUE='"
      +anzahl+"'")
   tag("INPUT TYPE='HIDDEN' NAME='preis"+posten+"' VALUE='" +
     preis+"'")
   tag("INPUT TYPE='HIDDEN' NAME='beschreibung"+posten+"' VALUE='" +
     beschreibung+"'")
    tag("/TD")
    tag("TD"); document.write(beschreibung); tag("/TD")
    tag("TD"); document.write(preis); tag("/TD")
    tag("TD"); document.write(anzahl*preis); tag("/TD")
    tag("/TR")
  }
}
tag("/TABLE")
tag("INPUT TYPE='HIDDEN' NAME='posten' VALUE=" + posten)
//--></SCRIPT>
<INPUT TYPE="BUTTON" onClick="top.korb.update(this.form)" VALUE=
  "Aktualisieren">
</FORM>
</BODY>
</HTML>

Abbildung 8.8  Der Inhalt des Warenkorbs kann jetzt auch geändert werden.

Beachten Sie, dass an die Funktion update() – die noch erstellt werden muss – eine Referenz auf das aktuelle Formular übergeben wird; das vereinfacht den Zugriff auf die Formularwerte.

Die Funktion, die den Warenkorb aktualisiert, muss nacheinander Folgendes erledigen:

	Einlesen aller Warenkorbposten
	Sofern die Anzahl eine natürliche Zahl und damit größer als 0 ist, wird der Posten verarbeitet, ansonsten wird er übergangen.
	Aktualisierung der durch "|" getrennten Zeichenketten für Anzahl, Preise und Beschreibungen
	Neudarstellung des Warenkorbs

Die Hauptschwierigkeit ist wohl der erste Punkt, das Einlesen aller Warenkorbposten. Hat man jedoch einmal das Verfahren verstanden, geht der Rest wie von selbst. Die Anzahl der Posten wird aus dem Formular eingelesen; dann werden innerhalb einer Schleife die Felder "anzahl1" bis ("anzahl"+posten) ausgelesen. Wenn f das Warenkorb-Formular bezeichnet, würde man so alle Mengen einlesen:

for (var i=1; i<=1*f.posten.value; i++){
  a = eval("f.anzahl"+i+".value")
  // Code für die Verarbeitung hier einfügen...
}

	Beachten Sie, dass die Anzahl der Posten, die als Formularwert eine Zeichenkette ist, zur Sicherheit durch eine Multiplikation mit 1 in eine natürliche Zahl umgewandelt wird. Alternativ kann auch parseInt() verwendet werden.
	Die Aktualisierung der Zeichenketten für Anzahl, Preise und Beschreibungen erfolgt nach dem Muster von oben; die Funktion einfuegen() kann wieder verwendet werden. Fehlt nur noch die Neuanzeige des Warenkorbs. Leider kann location.reload() nicht verwendet werden – diesen Befehl gibt es erst seit der JavaScript-Version 1.1 – aber ein einfaches location.href=location.href reicht prinzipiell völlig aus (ein history.go(0) würde es auch tun). Denken Sie hierbei daran, dass die Funktion update() selbst im Frame mit den JavaScript-Versionen steht. Obwohl sie vom Frame mit dem Warenkorb ausgeführt wird, liefert ein Aufruf von location.href die URL des unsichtbaren Frames zurück, nicht die des aufrufenden Frames!

function update(f){
  //Warenkorb zurücksetzen
  anzahl=""; preis=""; beschreibung=""
  for (var i=1; i<=1*f.posten.value; i++){
    a = eval("f.anzahl"+i+".value")
    p = eval("f.preis"+i+".value")
    b = eval("f.beschreibung"+i+".value")
    einfuegen(a, p, b)
  }
  parent.inhalt.location.href = parent.inhalt.location.href
}

8.4 Diashow

Als letzte Anwendung dieses Kapitels soll eine Diashow entwickelt werden. Ihre Firma hat eine Firmenpräsentation erstellt. Diese soll nun auch in die Website integriert werden. Da die Präsentation mit einem mittelmäßigen Präsentationsprogramm erstellt worden ist, liegen Ihnen lediglich zehn HTML-Seiten vor, die aber nicht miteinander verlinkt sind. Ziel soll es nun sein, diese zehn HTML-Seiten nacheinander anzuzeigen; alle zehn Sekunden soll die nächste Seite geladen werden. Um dem Besucher der Webseiten wenigstens ein bisschen Interaktivität vorzugaukeln, soll er die Animation anhalten, aber auch eine Seite vor- oder zurückspringen können. Das ist Ihr Pech und mein Glück, denn ohne diese Zusatzbedingung könnte man diese Aufgabe auch mit normalen (HTML-)Mitteln lösen.

8.4.1 Vorbereitungen

Beginnen wir mit der Grundstruktur der Präsentation: Das folgende Frameset teilt das Browser-Fenster in die Präsentationsfläche (oben) und den Navigationsbereich (unten) auf:

<HTML>
<HEAD>
<TITLE>Firmenpräsentation</TITLE>
</HEAD>
<FRAMESET ROWS="*,80">
   <FRAME SRC="tour.html" NAME="Tour">
   <FRAME SRC="nav.html" NAME="Nav">
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nichts anfangen!</BODY>
</NOFRAMES>
</HTML>

Abbildung 8.9  Die Startseite der Diashow

In der Abbildung sehen Sie, wie die Navigationsleiste ungefähr aussehen soll. Als Optionen soll es Start, Stop, Vor, Zurück und Verlassen geben. Wir werden JavaScript-Funkionen mit denselben Namen schreiben. Dazu brauchen wir noch eine Funktion, die die nächste Seite der Animation in den oberen Frame lädt. Außerdem benötigen wir noch globale Variablen. Unter anderem muss jederzeit bekannt sein, welche Seite der Diashow gerade angezeigt wird und ob die Animation gerade läuft oder pausiert.

Neben einigen weiteren Angaben (wie viele Seiten? welche Verzögerung zwischen den Seiten?) benötigen wir noch eine weitere Variable. Da mit setTimeout() gearbeitet werden muss, sollte die zurückgegebene ID in einer Variablen abgespeichert werden.

Im Folgenden sehen Sie das Grundgerüst für die Datei nav.html; in den folgenden Abschnitten werden die Funktionen mit Inhalt gefüllt.

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript"><!--
//globale Variablen
var seiten = 10 //Anzahl der Seiten tourX.htm
var stat = "stop" //Status der Animation:
                  //"stop" oder "start"
var akt = 1 //aktuell angezeigte Seite tourX.htm
var ID = 0 //ID des letzten Timeouts
var delay = 10000 //Verzögerung in Millisekunden
//Funktionen
function start(){
   //Funktion zum Starten/Fortfahren der Diashow
}
function stop(){
   //Funktion zum Anhalten/Pausieren der Diashow
}
function vor(){
   //Funktion zum Vorspringen in der Animation
}
function zurueck(){
   //Funktion zum Zurückspringen in der Animation
}
function verlassen(){
   //Funktion zum Verlassen der Animation
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="start()">
<FORM onSubmit="return false">
<CENTER>
<TABLE BORDER=0 CELLPADDING=10><TR>
<TD><A HREF="javascript:start()">Start</A></TD>
<TD><A HREF="javascript:stop()">Stop</A></TD>
<TD><A HREF="javascript:zurueck()">Zurück</A></TD>
<TD><A HREF="javascript:vor()">Vor</A></TD>
<TD><A HREF="javascript:verlassen()">Verlassen</A></TD>
</TR></TABLE>
</CENTER>
</BODY>
</HTML>

8.4.2 Diashow starten

Wenn der Benutzer auf Start klickt, muss zuerst überprüft werden, ob die Diashow nicht etwa schon läuft (über die Statusvariable stat). Falls doch, muss keine Aktion erfolgen; andernfalls muss der Status geändert und die neue Seite nach Ablauf von zehn Sekunden geladen werden. Das Laden der weiteren Seiten geschieht dann in der Funktion lade(), die sich – mittels Timeout – immer wieder selbst aufruft. Ein besonderer Fall liegt noch vor, wenn die letzte Seite der Diashow angezeigt wird: Dann darf auch keine Aktion erfolgen.

function start(){
   if (stat=="stop"&&akt<seiten){
      stat = "start"
      ID = setTimeout("lade(akt+1)", delay)
   }
}
function lade(nummer){
   parent.Tour.location.href="tour"+nummer+".html"
   akt = nummer
   if (stat=="start"&&akt<seiten)
      ID = setTimeout("lade(akt+1)", delay)
   else if (akt == seiten)
      stat = "stop"
}

8.4.3 Diashow anhalten

Auch das Anhalten der Diashow gestaltet sich nicht weiter schwierig: Die Statusvariable muss angepasst werden, und das Laden der nächsten Seite muss mit clearTimeout() unterbunden werden:

function stop(){
   stat = "stop"
   clearTimeout(ID)
}

8.4.4 Vorwärts und rückwärts springen

Der Wechsel zur vorherigen oder zur nächsten Seite der Diashow ist relativ ähnlich. Zuerst wird überprüft, ob man sich auf der ersten bzw. letzten Seite befindet (dann geschieht nichts); dann wird clearTimeout() und danach lade() aufgerufen. Beachten Sie, dass die vorherige oder nächste Seite sofort aufgerufen werden soll, also wird setTimeout() nicht verwendet.

function vor(){
   if (akt<seiten){
      clearTimeout(ID)
      lade(akt+1)
   }
}
function zurueck(){
if (akt>0){
      clearTimeout(ID)
      lade(akt-1)
   }
}

8.4.5 Diashow verlassen

Der letzte Punkt auf der Aufgabenliste, das Verlassen der Diashow, verdient eigentlich keine eigene Überschrift. Es wird einfach eine andere Seite geladen; als sauberer Programmierer löschen Sie außerdem noch alle Timeouts.

function verlassen(){
   clearTimeout(ID)
   top.location.href="andereseite.html"
}

Beachten Sie, dass in obigem Code die neue URL auf der obersten Ebene der Framehierarchie aufgerufen wird; Sie rufen ja das JavaScript-Kommando in einem Unterframe auf!

8.5 Fragen & Aufgaben

1.	Betrachten Sie folgendes HTML-Dokument:

<HTML>
<FRAMESET ROWS="100,200,*">
   <FRAMESET COLS="200,*,100">
      <FRAME SRC="a.html">
      <FRAME SRC="b.html">
      <FRAMESET ROWS="50,50">
         <FRAME SRC="c.html">
         <FRAME SRC="d.html">
      </FRAMESET>
   </FRAMESET>
   <FRAMESET COLS="200,200">
      <FRAMESET ROWS="50%,50%">
         <FRAME SRC="e.html">
         <FRAME SRC="f.html">
      </FRAMESET>
      <FRAMESET ROWS="33%,67%">
         <FRAME SRC="g.html">
         <FRAME SRC="h.html">
      </FRAMESET>
   </FRAMESET>
   <FRAME SRC="i.html">
</FRAMESET>
</HTML>

Gehen Sie davon aus, dass auf dem Webserver für jeden <FRAMESET>-Tag eine entsprechende Datei liegt, die das Frameset enthält (die obige Auflistung ist also nur eine Zusammenfassung). Die Hauptseite wird im Webbrowser aufgerufen, mitunter auch in einem Unterframe. Ihre Aufgabe soll es nun sein, von einem Unterframe auf einen anderen zuzugreifen. Wie lautet der entsprechende JavaScript-Code?

		Vom Frame mit c.html auf den Frame mit h.html und umgekehrt
		Vom Frame mit a.html auf i.html
2.	Schreiben Sie eine Funktion subframes(frameref), die die Anzahl der Unterframes des Frames mit der Referenz frameref ermittelt. Als Unterframes zählen hierbei jedoch nur Frames, die ein Dokument ohne weiteres Frameset enthalten.
3.	Wenn die Diashow nach drei Sekunden angehalten und dann wieder gestartet wird, sollte die nächste Seite eigentlich nach sieben Sekunden angezeigt werden. Sie erscheint aber erst nach zehn Sekunden. Korrigieren Sie das Skript dementsprechend. (Tipp: Sie benötigen eine weitere Timeout-ID und eine Funktion, die die Sekunden herunterzählt.)
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 9 Images
			9.1 Bildlein-Wechsle-Dich
			9.2 Animierte JPEGs
			9.3 Animierte Navigation
			9.4 Erweiterung der Navigation
			9.5 Tipps aus der Praxis
			9.6 Fragen & Aufgaben

Kapitel 9 Images

Es gibt Maler, die die Sonne in einen gelben Fleck verwandeln. Es gibt aber andere, die dank ihrer Kunst und Intelligenz einen gelben Fleck in die Sonne verwandeln.

– Pablo Picasso

Einer der beliebtesten JavaScript-Effekte im World Wide Web – und wahrscheinlich der Effekt, der am häufigsten falsch eingesetzt wird. In diesem Kapitel erfahren Sie, wie es richtig funktioniert.

Das Image-Objekt tauchte zum ersten Mal in einer Beta-Version des Netscape Navigator 3 auf. Damit war es erstmals möglich, mit JavaScript einzelne Grafiken eines HTML-Dokuments anzusprechen. Besonders pfiffig – und praktisch – war die Möglichkeit, Grafiken auszutauschen, was Animationen und andere grafische Effekte ermöglicht.

Zu ungefähr derselben Zeit wurde die Version 3 des Microsoft Internet Explorer veröffentlicht. Da sich das Konkurrenzprodukt aus dem Hause Netscape noch in der Beta-Testphase befand, wurde das Image-Objekt nicht mehr in den JavaScript-Funktionsumfang des Internet Explorer übernommen. Dies ist übrigens die Hauptursache für unsaubere Umsetzungen im World Wide Web. Die Macintosh-Variante des »IE3« kam etwas später als das Windows-Pendant heraus, und da sich das Image-Objekt bei Webdesignern großer Beliebtheit erfreute, wurde eine rudimentäre Unterstützung für den flotten Bildertausch in den Browser integriert. Ab Version 4 unterstützt der Internet Explorer übrigens auf allen Plattformen das Image-Objekt, und zwar vollständig.

9.1 Bildlein-Wechsle-Dich

Doch was war es, das den Webdesignern so gut am Image-Objekt gefiel? JavaScript wurde bis dato hauptsächlich für Laufschriften und für Formulare benutzt. Hier war es zum erstenmal auch möglich, mit JavaScript grafische Effekte zu schaffen. Eine der Hauptanwendungen wird lapidar mit »Mouseovers« bezeichnet. Fährt die Maus über eine Grafik, so ändert diese ihre Gestalt; befindet sich die Maus dann nicht mehr über der Grafik, nimmt diese wieder ihre ursprüngliche Gestalt an.

Zwar ist es nicht möglich, eine Grafik zu manipulieren (etwa die Farbpalette zu verändern o. ä.), aber man kann die Grafik einfach austauschen. In Abbildung 9.1 sehen Sie zwei Grafiken, galileo_over.gif und galileo_ out.gif. Unser Ziel ist es nun, die Grafik galileo_out.gif anzuzeigen. Nur wenn sich der Mauszeiger über der Grafik befindet, soll die Grafik galileo_over.gif angezeigt werden.

Abbildung 9.1  Die beiden Grafiken für den Mouseover-Effekt

Der folgende Code erfüllt die Anforderungen; eine Erläuterung folgt anschließend.

<HTML>
<HEAD>
<TITLE>Bildlein-Wechsle-Dich</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function over(){
   if (document.images)
      document.grafik.src = "galileo_over.gif"
}
function out(){
   if (document.images)
      document.grafik.src = "galileo_out.gif"
}
//--></SCRIPT>
</HEAD>
<BODY>
<A HREF="http://www.galileo-press.de">
   <IMG SRC="galileo_out.gif" NAME="grafik"
   onMouseover="over()" onMouseout="out()">
</A>
</BODY>
</HTML>

9.1.1 Zugriff auf Grafiken

Es gibt mehrere Möglichkeiten, auf Grafiken in einem HTML-Dokument zuzugreifen:

	document.grafikname
	document.images[grafikname]
	document.images[grafiknummer]

Hierbei steht grafikname für den Wert des NAME-Attributs der jeweiligen Grafik und grafiknummer für die laufende Nummer der Grafik im HTML-Dokument. Da alle Grafiken im Array document.images[] gespeichert werden, beginnt die Zählung bei 0.

Im Beispielcode von oben kann man also die Grafik folgendermaßen ansprechen:

	document.grafik
	document.images["grafik"]
	document.images[0]

In der Regel entscheidet man sich für die erste Methode; achten Sie also darauf, Ihren Grafiken eindeutige und einprägsame NAME-Attribute zu geben, und verwenden Sie dabei keine gefährlichen Zeichen wie etwa Punkte (dann müsste man Methode 2 oder 3 zum Ansprechen der Grafik verwenden).

Die interessanteste und auch wichtigste Eigenschaft des Image-Objekts ist src: das ist die URL der Grafik. Mit JavaScript hat man sowohl Lese- als auch Schreibzugriff auf diese Eigenschaft – ändert man also ihren Wert, wird die neue Grafik geladen. Das Thema »Dynamisches HTML« ist allerdings erst in einem späteren Kapitel an der Reihe. Sie können so nur eine Grafik durch eine andere austauschen; Rahmenparameter wie etwa Breite, Höhe und Position der Grafik können nicht verändert werden. Sie sollten also stets gleich große Grafiken verwenden; andernfalls wird die neue Grafik gestaucht oder gestreckt dargestellt.

Somit sind zwei Zeilen des obigen Codes erklärt: Mit document.grafik.src="galileo_over.gif" wird die Grafik galileo_over.gif anstelle der alten Grafik geladen und dargestellt; analog erklärt sich die Wirkungsweise von document.grafik.src="galileo_out.gif".

Die beiden Funktionen over() und out() werden durch die Event-Handler onMouseover und onMouseout aufgerufen. Sie erinnern sich: Wie der Name schon andeutet, wird der erste Event-Handler tätig, wenn die Maus über das Objekt (hier: den Link) fährt, und onMouseout tritt in Aktion, wenn die Maus das Objekt (den Link) wieder verlässt.

	Nur der Internet Explorer (ab Version 4) unterstützt die Event-Handler onMouseover und onMouseout beim <IMG>-Tag; wenn also nicht verlinkte Grafiken mit einem Mouseover-Effekt versehen werden sollen, muss um die Grafik ein Link (etwa mit HREF="#") herum gebaut werden.

9.1.2 Prüfungen auf Kompatibilität

	Kommen wir zu einem der Hauptprobleme beim Einsatz des Image-Objekts im World Wide Web. Der Microsoft Internet Explorer 3 unterstützt dieses Objekt nicht (nur die Macintosh-Version, wie oben erwähnt), der Netscape Navigator 2 ebenfalls nicht. Das ist ein Problem, denn manche Webdesigner scheren sich nicht um die alten Browser und nehmen Fehlermeldungen bei manchen Nutzern in Kauf. Der Netscape Navigator 2 ist inzwischen kaum mehr verbreitet, aber der Internet Explorer 3 wird mit Windows 95 ausgeliefert und ist auch Bestandteil älterer Versionen der AOL-Zugangssoftware und damit durchaus noch weit verbreitet.

Sie haben am obigen Codebeispiel schon gesehen, dass es recht viel Tipparbeit ist, die Funktionen für den Mouseover-Effekt zu programmieren (obwohl Sie ja noch gar nicht wissen, was die noch nicht erklärten Zeilen überhaupt sollen). Viel einfacher wäre doch ein Vorgehen wie folgt:

<A HREF="http://www.galileo-press.de"
   onMouseover="document.grafik.src='galileo_over.gif'"
   onMouseout="document.grafik.src='galileo_out.gif'">
   <IMG SRC="galileo_out.gif" NAME="grafik">
</A>

Abbildung 9.2  Die Fehlermeldung eines Internet Explorer 3

Das bedeutet wenig Tipparbeit, aber viel Ärger, da es bei älteren Browsern eine Fehlermeldung gibt. Noch vor einem Jahr war ein Fehler dieser Machart auf erschreckend vielen Webseiten verbreitet, inzwischen hat das zum Glück abgenommen.

Nach und nach begannen die größeren Agenturen, Abfragen zu entwickeln, die überprüfen sollten, ob das Image-Objekt unterstützt wird. Eine erste Variante bestand darin, explizit zu prüfen, ob der Netscape Navigator 3 verwendet wird. Tolle Idee – aber dann tut sich beim Netscape Navigator 4 nichts.

Eine weitere Methode bestand darin, zu prüfen, ob der Netscape Navigator 3 oder 4, eventuell auch ob der Internet Explorer 4 zum Einsatz kommt. Folgender Code stammt – nur leicht abgewandelt – von einer bekannteren Website:

if (navigator.appName.indexOf("Netscape")!=-1){ //Netscape-Browser
   nn3 =  (navigator.userAgent.indexOf("Mozilla/3.0") != -1)
   nn4 = (navigator.userAgent.indexOf("Mozilla/4.0") != -1)
   if (nn3||nn4){
      //JavaScript-Code mit Image-Objekt
   }
}

Das war schon besser, aber der Internet Explorer-Teil wurde oft vergessen, und an die Macintosh-Version des Internet Explorer 3 wurde sowieso nicht gedacht. Besonders schlimm wurde es jedoch, als Netscape die Version 4.5 veröffentlichte: navigator.userAgent enthielt nun die Zeichenfolge "Mozilla/4.5", und damit bekamen ausgerechnet die Anwender mit dem neuesten Browser den grafischen Effekt überhaupt nicht zu sehen.

Mit etwas Aufwand kann man eine etwas kompatiblere Abfrage programmieren – beispielsweise die Versionsnummer auslesen, und beim Netscape auf »größer oder gleich 3« sowie beim Internet Explorer auf »Macintosh und größer oder gleich 3 oder andere Plattform und größer oder gleich 4« prüfen. Aber es gibt ja noch den Opera-Browser, den Webbrowser in Star Office 5, den HotJava-Browser von Sun ...

Eine Methode kommt unserem Ziel schon recht nahe. Das Image-Objekt ist Teil des JavaScript-1.1-Sprachschatzes; man könnte also folgendes schreiben:

<SCRIPT LANGUAGE="JavaScript"><!--
function over() {} //Dummy-Funktion für alte Browser
function out() {}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
function over(){
   document.grafik.src = "galileo_over.gif"
}
function out(){
   document.grafik.src = "galileo_out.gif"
}
//--></SCRIPT>

Diesen Trick kennen Sie schon von früher – Browser, die nur JavaScript 1.0 unterstützen, führen die leeren Dummy-Funktionen over() und out() aus, tun also effektiv nichts. Browser, die jedoch auch JavaScript 1.1 unterstützen, sehen beide Versionen der Funktionen – und führen die jeweils letzte Version aus. Das funktioniert sehr gut, nur eben beim Internet Explorer 3 für Macintosh nicht.

Es gibt jedoch noch eine Methode. Sie erinnern sich vielleicht an die Überprüfung, ob ein Fenster die Methode focus() besitzt (ab JavaScript 1.1 nämlich: if (window.focus) { ... }. Hierbei werden Objekte und Methoden, die es gibt, in einer if-Abfrage als true ausgewertet, ansonsten als false. Erinnern Sie sich noch an die beiden anderen Möglichkeiten, auf eine Grafik im HTML-Dokument zuzugreifen? Über das Array document.images[] ist das recht einfach möglich. Es liegt also nahe, folgende Abfrage zu verwenden:

if (document.images){
   //JavaScript-Code mit Image-Objekt
}

Diese Methode hat sich mittlerweile durchgesetzt – hat auch lange genug gedauert – und sie ist zudem fast perfekt. Fast perfekt nur deswegen, weil ältere Versionen vom Opera-Browser (bis etwa 3.21) document.images in einer if-Abfrage als false auswerten, obwohl der norwegische Mini-Browser das Image-Objekt vollständig unterstützt. Hierfür aber noch eine weitere Abfrage zu programmieren ist wirklich zu viel des Guten.

9.2 Animierte JPEGs

Sie kennen sicherlich die Basis aller nervenden Werbebanner im World Wide Web – animierte GIF-Grafiken. Als das Grafikformat 1987 bzw. 1989 im Auftrag der Firma CompuServe entwickelt wurde, dachte noch niemand daran, dass dieses geheime Feature – nämlich die Integration mehrerer Einzelgrafiken in eine GIF-Datei – später einmal Furore machen sollte. Leider ist das nur mit GIF-Grafiken möglich, die ja auf nur 256 Farben beschränkt sind. Fotorealistische Animationen sind damit nicht möglich oder nur in sehr schlechter Qualität.

Mit JavaScript kann dieser Missstand behoben werden, und zwar mit dem Image-Objekt. Nach Ablauf einer bestimmten Zeitdauer wird einfach das nächste Bild der Animation eingeblendet. Nachfolgend finden Sie den Code, der die Animation mit einer Verzögerung von einer Sekunde zwischen den Einzelbildern auf den Bildschirm bringt.

<HTML>
<HEAD>
<TITLE>JPEG-Animation</TITLE>
</HEAD>
<SCRIPT LANGUAGE="JavaScript"><!--
if (document.images)
   var bilder = new Array("ani1.jpg", "ani2.jpg", "ani3.jpg",
     "ani4.jpg")
var naechstesBild = 0 //Array-Index der nächsten Bildes
var verzoegerung = 1000 //Verzögerung in Millisekunden
function animation(){
   document.ani.src = bilder[naechstesBild]
   naechstesBild++
   if (naechstesBild==bilder.length)
      naechstesBild = 0
   setTimeout("animation()", verzoegerung)
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="if (document.images) animation()">
<H3>Animation</H3>
<IMG SRC="ani1.jpg" NAME="ani">
</BODY>
</HTML>

9.2.1 Eine Animation mit JavaScript

Für das Skript werden ein paar globale Variablen benötigt:

if (document.images)
   var bilder = new Array("ani1.jpg", "ani2.jpg", "ani3.jpg",
     "ani4.jpg")
var naechstesBild = 0 //Array-Index der nächsten Bildes
var verzoegerung = 1000 //Verzögerung in Millisekunden

Beachten Sie, dass der (für Netscape 2) kritische Befehl, nämlich der Zugriff auf das Array-Objekt, mit if (document.images) eingeschlossen wird. Das Array wird nur benötigt, wenn der Browser das Image-Objekt unterstützt (und dann kann er auch JavaScript-Arrays erzeugen). In dem Array bilder stehen die Dateinamen der einzelnen Grafiken der JPEG-Animation. In der Variablen naechstesBild wird der Array-Index des nächsten Bildes der Animation gespeichert. Angefangen wird beim ersten Bild. Es besitzt den Index 0, also enthält die Variable den Startwert 0. Die letzte Variable, die die Verzögerung in Millisekunden zwischen den einzelnen Animationsschritten enthält, müsste eigentlich nicht als global deklariert werden. Behalten Sie aber immer im Hinterkopf, dass Ihre Skripten von Leuten bearbeitet werden könnten, die sich nicht so gut in JavaScript auskennen. In so einem Fall ist es gut, wenn wichtige Parameter für das Skript an markanter Stelle stehen, so dass dort auch unbedarftere Kollegen Änderungen vornehmen können, ohne gleich den gesamten Programmcode zu ruinieren.

Fehlt nur noch die Funktion animation(), die das nächste Bild der Animation anzeigt (der Index wird aus der Variablen naechstesBild gewonnen) und sich selbst nach einiger Zeit (diese steht in verzoegerung) wieder aufruft. Davor muss natürlich noch die Nummer des nächsten Bildes um eins erhöht werden. Sollte man beim letzten Bild angekommen sein, so soll die Animation wieder von vorn beginnen, naechstesBild wird also auf 0 gesetzt.

function animation(){
   document.ani.src = bilder[naechstesBild]
   naechstesBild++
   if (naechstesBild==bilder.length)
      naechstesBild = 0
   setTimeout("animation()", verzoegerung)
}

Sie fragen sich, wo die Abfrage bleibt, ob der Browser das Image-Objekt überhaupt unterstützt? Der Trick besteht hier darin, dass die Funktion animation() ja erst einmal aufgerufen werden muss – und zwar mit dem onLoad-Event-Handler des <BODY>-Tags. Dort wird auch geprüft, ob der Bildertausch unterstützt wird:

<BODY onLoad="if (document.images) animation()">

9.2.2 Bilder in den Cache laden

Wenn Sie dieses oder das letzte Beispiel auf der heimischen Festplatte oder auf dem lokalen Webserver ausprobieren, funktioniert alles wunderbar. Sobald Sie die Seiten aber in das World Wide Web stellen, werden Sie wahrscheinlich eine üble Überraschung überlegen: Es dauert unter Umständen mehrere Sekunden, bis die neue Grafik erscheint. Der Grund dafür ist schnell gefunden: Die neuen Grafiken müssen ja erst einmal vom Browser angefordert und über das Internet übertragen werden. Je nach Qualität der Verbindung kann das schon seine Zeit dauern. Zwar können Sie mit JavaScript die Ladegeschwindigkeit des Browsers nicht verbessern, aber Sie können wenigstens so tun. Ist eine Grafik nämlich einmal geladen, so liegt sie im Speicher- oder Festplattencache des Browsers. Der Trick ist nun, die Grafiken nicht erst zu laden, wenn sie angezeigt werden sollen, sondern schon vorher. Das ist sogar in HTML möglich, man muss nur darauf achten, dass die Grafiken nicht optisch stören. Der erste Versuch, Höhe und Breite der Grafik auf 0 zu setzen, schlägt fehl, da die meisten Browser das ignorieren. Also muss man das nächstkleinere Maß nehmen: 1 x 1 Pixel.

<IMG SRC="ani2.jpg" WIDTH=1 HEIGHT=1>
<IMG SRC="ani3.jpg" WIDTH=1 HEIGHT=1>
<IMG SRC="ani4.jpg" WIDTH=1 HEIGHT=1>

Wollen Sie komplett vermeiden, dass die Grafiken sichtbar oder erahnbar sind, müssen Sie in die JavaScript-Trickkiste greifen. Das Image-Objekt hilft Ihnen hierbei. Mit dem folgenden Befehl wird ein Image-Objekt erzeugt, dessen src-Eigenschaft auf "ani2.jpg" gesetzt wird. Der besondere Effekt hierbei: Die Grafik wird vom Browser im Hintergrund geladen und liegt damit im Cache.

var img = new Image()
img.src = "ani2.jpg"

Wenn man ganz sauber programmieren will, gibt man dem Konstruktor des Image-Objekts noch die Breite und Höhe der Grafik mit, was aber in der Praxis überhaupt keine Auswirkungen hat:

var img = new Image(breite, hoehe)
img.src = "ani2.jpg"

Die Instanz des Image-Objekts befindet sich nun im Speicher, und die Grafik wird vom Webserver angefordert, aber noch gar nicht angezeigt. Umgangssprachlich spricht man hier vom Vorladen oder Preloading. Zuerst wird das Beispiel aus dem vorherigen Abschnitt umgearbeitet:

<HTML>
<HEAD>
<TITLE>Bildlein-Wechsle-Dich</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!-
function preload(){
   img_over = new Image()
   img_over.src = "galileo_over.src"
}
function over(){
   if (document.images)
      document.grafik.src = img_over.src
}
function out(){
   if (document.images)
      document.grafik.src = "galileo_out.gif"
}
preload()
//--></SCRIPT>
</HEAD>
<BODY>
<A HREF="http://www.galileo-press.de">
   <IMG SRC="galileo_out.gif" NAME="grafik">
</A>
</BODY>
</HTML>

Beim Laden des HTML-Dokuments wird die JavaScript-Funktion preload() aufgerufen, die die Grafik galileo_over.gif in den Cache des Browsers lädt. Die Grafik galileo_out.gif muss nicht extra geladen werden, sie wird ja im HTML-Dokument schon angezeigt.

Beachten Sie auch die folgende neue Zeile in der Funktion over():

document.grafik.src = img_over.src

Die src-Eigenschaft der Grafik mit dem NAME-Attribut "grafik" wird also auf die src-Eigenschaft der Variablen img_over gesetzt. Das bringt zwar in diesem Beispiel keine Vorteile, aber man sollte das Verfahren einmal gesehen haben. Wenn die Grafikabteilung Ihrer Firma mal wieder besonders kreative Dateinamen gewählt hat, kann dieses Vorgehen durchaus nützlich sein, indem Sie dann wenigstens brauchbare Variablennamen vergeben können.

Die Animation kann ebenso schnell angepasst werden. Da aber schöner Code herauskommen soll, wird hier ein wenig mehr Aufwand getrieben. Die Namen und auch die URLs der einzelnen Grafiken sollen in Variablen gespeichert werden. Dies hat wieder den Vorteil, dass ein größerer Personenkreis das Skript bearbeiten kann, indem einfach die Werte der globalen Variablen geändert werden.

Im ersten Schritt soll eine Funktion geschrieben werden, die eine Reihe von Grafiken in den Cache lädt. Die URLs der Grafiken werden dabei als Parameter an die Funktion übergeben. Wie man die Anzahl der übergebenen Parameter ermittelt, haben Sie ja schon am Beispiel von Make Array() gesehen. Der Rest ist schnell geschrieben:

function preload(){
   var img
   for (var i=0; i<preload.arguments.length; i++)
      img = new Image()
      i.src = preload.arguments[i]
   }
}

Diese Funktion lädt alle übergebenen Grafiken in den Cache. Leider kann man nicht über den Variablennamen auf die Grafik zugreifen, da lediglich eine Variable verwendet wird. Ohne Fleiß kein Preis: In diesem Beispiel sollen die Image-Variablen für die Animation auch in einem Array gespeichert werden. Diese Variablen sollen auch von anderen Funktionen aus angesprochen werden können, müssen also als global definiert werden.

var bildvariablen = new Array()
function preload(){
   var img
   for (var i=0; i<preload.arguments.length; i++){
      img = new Image()
      img.src = preload.arguments[i]
      bildvariablen[i] = img
   }
}

Schließlich muss nur noch die Funktion animation() angepasst werden – hier wird auf die Variablen der Grafiken zugegriffen und nicht direkt auf deren URL.

function animation(){
   document.ani.src = bildvariablen[naechstesBild]
   naechstesBild++
   if (naechstesBild==bilder.length)
      naechstesBild = 0
   setTimeout("animation()", verzoegerung)
}

9.3 Animierte Navigation

Der letzte Teil dieses Kapitels ist einem etwas umfangreicheren Beispiel gewidmet: einer animierten Navigation. Die Kernidee besteht hierbei darin, dass der Benutzer wie beim Menü eines Browsers die Oberbegriffe oder Kategorien angezeigt bekommt. Fährt er mit der Maus über einen der Begriffe, klappt das Menü nach unten aus, und er kann einen der Menüpunkte auswählen. In Abbildung 9.3 sehen Sie, wie das Beispielmenü aussieht, wenn alle Kategorien ausgeklappt sind; in Abbildung 9.4 sehen Sie, wie das Menü in nichtausgeklapptem Zustand aussieht. Wie Sie ja bereits wissen, lässt sich (mit den bisher bekannten JavaScript-Mitteln) keine Grafik irgendwo auf einer HTML-Seite platzieren. Sie müssen also für jede Stelle des ausgeklappten Menüs eine Füllgrafik (am besten als transparentes GIF) verwenden.

Abbildung 9.3  Das vollständig ausgeklappte Menü

Abbildung 9.4

Das vollständig eingeklappte Menü

Folgende Punkte sind nun nacheinander abzuarbeiten:

	Fährt der Benutzer mit der Maus über eine Kategorie, so muss diese ausgeklappt werden (und natürlich eventuell ausgeklappte Kategorien wieder eingeklappt werden).
	Klickt der Benutzer auf einen einzelnen Menüpunkt, so soll die entsprechende HTML-Seite aufgerufen werden. Dazu muss natürlich überprüft werden, ob die entsprechende Kategorie überhaupt ausgeklappt ist. Denken Sie daran, dass der HTML-Link vorhanden ist, egal ob gerade ein Menüpunkt angezeigt wird oder statt dessen nur die transparente Füllgrafik erscheint.

9.3.1 Vorüberlegungen

Den kompletten HTML- und JavaScript-Code für dieses Beispiel finden Sie am Ende dieses Kapitels. Im Folgenden werden nur die wesentlichen Elemente vorgestellt. Bevor Sie sich ans Programmieren machen, sollten Sie sich Gedanken über Konventionen für die Dateinamen und NAME-Attribute der Grafiken machen; dann sparen Sie sich später einiges an Programmieraufwand. Auch die Namen der JavaScript-Funktionen sollten wohlüberlegt sein. Folgenden Vorschlag kann ich Ihnen anbieten:

	In diesem Beispiel gibt es zwei Kategorien, die erste mit drei Unterpunkten, die zweite mit vier Unterpunkten. Die Menügrafiken haben den Namen menu_X_Y.gif und das NAME-Attribut menu_X_Y, wobei X die Nummer der Kategorie ist (also 1 oder 2), und Y ist die Nummer des Unterpunkts (von 1 bis 3 bzw. von 1 bis 4). Die transparente Grafik (am besten 1 x 1 Pixel groß, dann ist sie kleiner) heißt leer.gif. Die Oberbegriffe der Kategorien haben den Namen menu_X, wobei X wiederum die Nummer der Kategorie ist.
	Wenn die Maus über einen Kategorienamen fährt, wird die JavaScript-Funktion klapp_auf(X) aufgerufen; wenn der Mauszeiger die Grafik wieder verläßt, wird klapp_zu(X) aufgerufen. Auch hier bezeichnet X wieder die Nummer der Kategorie.
	Wenn die Maus über einen einzelnen Menüpunkt fährt, wird die JavaScript-Funktion menue_in(X, Y) aufgerufen, beim Verlassen menue_out (X, Y). Wenn der Benutzer auf einen Menüpunkt klickt, wird die Funktion click(X, Y) aufgerufen. X und Y stehen – erraten – für die Kategorienummer und die Menüpunktnummer.

In globalen Variablen werden die folgenden Werte gespeichert:

	Die Nummer der aktuell ausgeklappten Kategorie
	Die URLs, auf die die einzelnen Menüpunkte weisen
	Außerdem noch eine ID, die – der aufmerksame Leser wird es wissen – auf die Verwendung von Timeouts hindeutet

Die globalen Informationen sollten wieder in einem exponierten Block des Dokuments abgelegt werden, damit auch andere Programmierer diese verändern können.

Beginnen wir also mit den globalen Variablen:

if (document.images){
var urls = new Array(
   new Array("seite1-1.htm", "seite1-2.htm", "seite1-3.htm"),
   new Array("seite2-1.htm", "seite2-2.htm", "seite2-3.htm",
     "seite2-4.htm")
)
var ausgeklappt = 0 //Startwert für ausgeklappte Rubrik
var ID
}

9.3.2 Auf- und Zuklappen

Die Kernfunktion dieses Programms besteht im Auf- und Zuklappen der einzelnen Kategorien. Das ist jedoch gar nicht so schwer. Das Zuklappen ist hierbei besonders einfach: Jede der Kategoriegrafiken wird durch eine Füllgrafik ersetzt. Erinnern Sie sich daran, dass die NAME-Attribute der Menüpunkte das Format menu_X_Y haben, wobei X die Kategorienummer und Y die Menüpunktnummer ist. Die Anzahl der einzelnen Menüpunkte bekommt man aus dem Array urls[]; bedenken Sie hierbei, dass man auf urls[1] zugreifen muss, wenn man sich mit der zweiten Kategorie beschäftigen will.

function klapp_zu(X){
   if (document.images){
      ausgeklappt = 0 //globale Variable zurücksetzen
      for (var i=1; i<=urls[X-1].length; i++)  //alle Menüpunkte
         eval("document.menu_"+X+"_"+i+".src = 'leer.gif'")
   }
}

Beim Aufklappen muss man einige kleine Hürden umgehen. Als Erstes muss die gerade aufgeklappte Kategorie wieder zugeklappt werden, und dann müssen die einzelnen Grafiken an die richtige Stelle gesetzt werden.

function klapp_auf(X){
   if (document.images){
      if (ausgeklappt !=0 && ausgeklappt!=X)
         klapp_zu(ausgeklappt)
      ausgeklappt = X //erst jetzt, nach dem Zuklappen, setzen!
      for (var i=1; i<=urls[X-1].length; i++)
         eval("document.menu_"+X+"_"+i+".src = 'menu_"+X+"_"+
           i+".gif'")
   }
}

9.3.3 Die einzelnen Menüpunkte

Was passiert, wenn sich die Maus über einem Menüpunkt befindet, und was passiert vor allem, wenn die Maus den Menüpunkt wieder verlässt? Im Gegensatz zu den meisten Menüs einer grafischen Benutzeroberfläche sollte das Menü wieder eingeklappt werden, wenn die Maus das Menü verlässt. Da man (zumindest mit den bisher bekannten Mitteln) nicht feststellen kann, ob der Benutzer den Menüpunkt nach oben verlässt (dann kann das Menü natürlich aufgeklappt bleiben) oder nach links oder rechts, sollte es zuklappen. Aus diesem Grund ist folgendes Vorgehen empfehlenswert: Wenn der Benutzer einen Menüpunkt verlässt, wird die Funktion klapp_zu() aufgerufen. Um aber zu verhindern, dass das Menü auch zugeklappt wird, wenn die Maus nach oben oder unten fährt, wird via Timeout diese Funktion erst nach einer kurzen Zeitspanne (etwa 50-100 Millisekunden) aufgerufen. Wenn die Maus über einen Menüpunkt fährt, wird dieser Timeout wieder eliminiert. Beachten Sie, dass die Funktion klapp_auf() auch abgeändert wird, da die Funktion auch gegebenenfalls eine andere aktive Sektion zuklappt.

	Ein wichtiger Hinweis noch, der vor allem bei älteren Browsern1  und manchen Beta-Versionen von Browsern beachtet werden sollte: Wenn innerhalb von kurzer Zeit zwei verschiedene Event-Handler aktiv werden (in diesem Fall etwa onMouseout bei den vorherigen Menüpunkten und onMouseover bei dem neuen Menüpunkt), ist es hin und wieder vorgekommen, dass einer der beiden Event-Handler (zumeist der zuerst aktive, also onMouseout) verschluckt wurde. Aus diesem Grund empfiehlt es sich, auch bei onMouseover die alte Sektion zuzuklappen.

Fassen wir diese Punkte zusammen:

	In der Funktion menue_in() wird der Timeout gelöscht und gegebenenfalls die vorherige Rubrik zugeklappt
	In der Funktion menue_out() wird ein Timeout gesetzt, der die Sektion zuklappt.
	In der (bereits programmierten) Funktion klapp_auf() muss der Timeout ebenfalls gelöscht werden.

function menue_in(X, Y){
   if (document.images){
      clearTimeout(ID)
      if (X!=ausgeklappt)
         klapp_zu(X)
   }
}
function menue_out(X, Y){
   if (document.images)
      eval("ID = setTimeout('klapp_zu("+X+")', 50)")
}
function klapp_auf(X){
   if (document.images){
   clearTimeout(ID)
      if (ausgeklappt !=0 && ausgeklappt!=X)
         klapp_zu(ausgeklappt)
      ausgeklappt = X //erst jetzt, nach dem Zuklappen, setzen!
      for (var i=1; i<=urls[X-1].length; i++)
         eval("document.menu_"+X+"_"+i+".src = 'menu_"+X+"_"+i+
           ".gif'")
   }
}

9.3.4 Verlinkung der Menüpunkte

Dieser Punkt ist wohl der einfachste in diesem Beispiel, man muss nur beachten, dass der Array-Index bei 0 beginnt, die Kategorien jedoch bei 1 beginnen. Ebenso muss der Menüpunkt natürlich eingeblendet sein, damit der Link aktiv ist.

function click(X, Y){
   if (X==ausgeklappt)
      window.location.href = (urls[X-1])[Y-1]
}

9.3.5 Einbau in die HTML-Datei

So schön das Beispiel (hoffentlich) auch bei Ihnen funktionieren wird, so schlecht sieht es aus, wenn Sie einen älteren Browser verwenden oder JavaScript deaktivieren. Aus diesem Grund folgt hier eine Strategie, wie man ein möglichst großes Publikum bedient. Natürlich könnten Sie eine JavaScript-Version und eine HTML-Version der Navigation erstellen, aber in diesem Fall lohnt es sich, alles auf einer Seite zu halten.

	Im HTML-Dokument selbst sind alle Kategorien ausgeklappt. Damit werden zum einen alle Grafiken schon einmal in den Cache geladen, und zum anderen bekommen auch ältere Browser alles zu sehen.
	Nach dem Laden des Dokuments wird versucht, alle Kategorien zuzuklappen. Dies wird nur von Browsern erledigt, die JavaScript aktiviert haben und das Image-Objekt auch unterstützen. Der entsprechende Code sieht folgendermaßen aus:
<BODY onLoad="for (var i=1;i<=urls.length;i++) klapp_zu(i)">

	Die einzelnen Menüpunkte benutzen nicht das JavaScript-Pseudoprotokoll, um die Funktion click() aufzurufen, sondern den Event-Handler onClick. Das HREF-Attribut wird auf die korrekte (HTML-)Zieladresse gesetzt. Damit aber neuere Browser nicht die HTML-Seite aufrufen, endet der onClick-Event-Handler mit return false, wenn der Browser das Image-Objekt kennt. Sie wissen schon aus vorherigen Kapiteln, dass dann der HTML-Link nicht ausgeführt wird. Dies ist mit einem relativ langen Event-Handler zu erledigen; um sich aber Schreibarbeit zu sparen, sollte der onClick-Event-Handler auf return img() enden. Die Funktion img() sieht folgendermaßen aus:
function img(){

   return (document.images) ? false : true

}

9.4 Erweiterung der Navigation

Die Navigation funktioniert ja schon ganz gut, aber ganz zufrieden sind wir noch nicht. Zum einen soll die Navigation auch auf Unterseiten verwendet werden; der Link der betreffenden Unterseite auf sich selbst sollte dann natürlich inaktiv sein. Aber ein kleiner Effekt soll zusätzlich noch eingebaut werden: Fährt der Benutzer mit der Maus über einen Menüpunkt, so soll dieser fett dargestellt werden. Der Menüpunkt, der die gerade aktive Seite bezeichnet, soll von vornherein fett sein.

9.4.1 Vorbereitungen

Was muss geändert werden, damit das so funktioniert?

	Die Funktion menue_in() muss dahingehend geändert werden, dass der aktive Menüpunkt in fetter Schrift dargestellt wird. Ist der aktive Menüpunkt gleichzeitig der geladene Menüpunkt, so muss keine Aktion erfolgen (wir wollen ja effizient programmieren).
	Die Funktion menue_out() muss dahingehend geändert werden, dass der zuvor aktive Menüpunkt wieder normal dargestellt wird – außer natürlich, es handelt sich um den aktiven Menüpunkt, der muss fett bleiben.
	Die Funktion klapp_auf() muss dahingehend geändert werden, dass der geladene Menüpunkt auch fett dargestellt wird.
	Die Funktion click() muss dahingehend geändert werden, dass beim Klicken auf der gerade aktiven Menüpunkt nichts passiert.

Auch hierzu sind ein paar Vorbereitungen notwendig. Da die Menüpunkte Grafiken sind, handelt es sich bei den in fetter Schrift dargestellten Menüpunkten ebenfalls um Grafiken. Diese haben folgende Namenskonvention: Der fette Menüpunkt in Kategorie Nummer X und (innerhalb dieser Kategorie) Nummer Y hat den Grafiknamen menu_X_Y_f.gif (f steht für fett).

Schließlich werden zwei weitere globale Variablen eingeführt, die dann auch von anderen Leuten geändert werden können: die Nummer der Kategorie und die Nummer des Menüpunkts, der gerade geladen ist. Auf jeder Unterseite können und müssen diese Nummern individuell angepasst werden. Es ist aber einfacher, zwei Zahlenwerte zu ändern, als irgendwelche Parameter innerhalb der JavaScript-Funktionen. Folgendermaßen würde es aussehen, wenn der zweite Menüpunkt der ersten Kategorie geladen ist:

var kategorie = 1
var menuepunkt = 2

9.4.2 Leichte Änderungen

Der letzte Punkt unserer To-Do-Liste – der inaktive Link – ist auch gleichzeitig der einfachste. Es wird einfach überprüft, ob der entsprechende Menüpunkt angeklickt worden ist, und falls ja, passiert eben nichts.

function click(X, Y){
   if (X==ausgeklappt && (X!=kategorie||Y!=menuepunkt))
      window.location.href = (urls[X-1])[Y-1]
}

Beim Ausklappen ist auch eine Kleinigkeit zu beachten: Beim geladenen Menüpunkt muss die fette Variante der Grafik angezeigt werden. Das war dann aber auch schon alles, worüber man stolpern könnte. Unter der lokalen Variablen suffix wird gespeichert, was an den Grafiknamen angehängt werden muss. Das ist "_f", wenn es sich um den geladenen Menüpunkt handelt, ansonsten nichts.

function klapp_auf(X){
   if (document.images){
      clearTimeout(ID)
      if (ausgeklappt !=0 && ausgeklappt!=X)
         klapp_zu(ausgeklappt)
      ausgeklappt = X //erst jetzt, nach dem Zuklappen, setzen!
      for (var i=1; i<=urls[X-1].length; i++){
         suffix = (X==kategorie&&i==menuepunkt) ? "_f" : ""
         eval("document.menu_"+X+"_"+i+".src = 'menu_"+X+"_"+i+
           suffix+".gif'")
      }
   }
}

9.4.3 Doppeltes Mouseover

Die Funktion menue_in() wird folgendermaßen geändert: Ist der aktive Menüpunkt gleichzeitig der geladene Menüpunkt, findet kein Mouseover statt; ansonsten wird die fette Variante des aktiven Menüpunkts dargestellt.

function menue_in(X, Y){
   if (document.images){
      clearTimeout(ID)
      if (X!=ausgeklappt)
         klapp_zu(X)
      else
         if (X!=kategorie||Y!=menuepunkt)
            eval("document.menu_"+X+"_"+Y+".src = 'menu_"+X+"_"+Y+
              "_f.gif'")
   }
}

In der Funktion menue_out() wird statt der fetten nun die normale Variante des Menüpunktes angezeigt, außer es handelt sich um den geladenen Menüpunkt.

Abbildung 9.5  Die erweiterte Version: Der aktuelle Menüpunkt wird fett dargestellt.

function menue_out(X, Y){
   if (document.images){
      if (X!=kategorie||Y!=menuepunkt)
         eval("document.menu_"+X+"_"+Y+".src = 'menu_"+X+"_"+Y+
           ".gif'")
      eval("ID = setTimeout('klapp_zu("+X+")', 50)")
   }
}

9.4.4 Das komplette Beispiel im Überblick

Auf der Buch-CD finden Sie die gesamte Datei im Überblick, einschließlich des beispielhaften HTML-Codes. So können Sie sich einiges an Tipparbeit sparen.

9.5 Tipps aus der Praxis

In diesem letzten Abschnitt dieses Kapitels über das Image-Objekt möchte ich Ihnen noch ein paar Tipps aus der Praxis geben, damit Sie Fehlermeldungen vermeiden oder Ihre Seiten mit noch mehr Funktionalität versehen können. Das Image-Objekt wird sehr gerne eingesetzt, und ein paar Fehler werden immer wieder gemacht, ein paar Fragen werden immer wieder gestellt. Die folgenden zwei Abschnitte beantworten hoffentlich Ihre offenen Fragen.

9.5.1 Vorladen – aber richtig

Sie haben sich vielleicht gefragt, warum beim Beispiel zum Vorladen die Funktion preload() nicht mittels <BODY onLoad="preload()"> aufgerufen worden ist, sondern noch im <HEAD>-Abschnitt des HTML-Dokuments. Das hat einen einfachen Grund. Gehen Sie von einer langsameren Verbindung oder von einem umfangreichen Dokument aus. Ein Teil des HTML-Dokuments wurde schon übertragen und ist auch schon vom Browser dargestellt worden. Hier ist besonders der Internet Explorer sehr schnell, während der Netscape Navigator Tabellen erst dann anzeigt, wenn sie vollständig übertragen worden sind. Aber zurück zum Beispiel: Ein Teil der Seite ist also schon geladen, wird dargestellt – und die Event-Handler in diesem Teil sind natürlich aktiv. Wie es der Zufall so will, fährt der Benutzer jetzt schon über eine mit Mouseover versehene Grafik. Im Beispiel von oben würde nun die folgende Funktion aufgerufen werden:

function over(){
   if (document.images)
      document.grafik.src = img_over.src
}

Die Variable img_over wird aber erst in der Funktion preload() korrekt gesetzt. Das ist schlecht, wenn die Funktion erst mit dem onLoad-Event-Handler aufgerufen wird; wie Sie sich erinnern, tritt dieser erst in Aktion, wenn das gesamte HTML-Dokument übertragen worden ist. Es gäbe also in diesem Fall unter Umständen eine Fehlermeldung. Um dies zu vermeiden, rufen Sie Ihre Vorladefunktion noch vor dem ersten <IMG>-Tag auf!

9.5.2 Ladestand einer Grafik

	JavaScript Version 1.1 bietet dem Benutzer eine bequeme Möglichkeit festzustellen, wie weit eine Grafik schon geladen ist. Interessant wird das beispielsweise bei der Diashow aus dem Kapitel »Fenster II«. Wenn Sie die Diashow über eine langsame Netzwerkverbindung abspielen, kann es sein, dass umfangreiche Grafiken auf den einzelnen Seiten der Show noch nicht vollständig geladen sind, bevor die nächste Seite der Show schon angezeigt wird. Es wäre hier also praktisch, wenn die Grafiken alle schon vorher im Browser-Cache wären. Auch beim Beispiel mit der JPEG-Animation aus diesem Kapitel ist das wünschenswert. Wir wollen für das letztere Beispiel eine Lösung konstruieren, die analog auch für das Diashow-Beispiel eingesetzt werden kann.

Der Trick besteht darin, eine Einstiegsseite zu programmieren, auf der alle Grafiken schon einmal geladen werden. Nun könnte man einerseits den Benutzer nach Ablauf einer gewissen Zeitspanne auf die nächste Seite weiterleiten, aber das ist keine sehr flexible Lösung. Bei einer langsamen Verbindung reicht die Zeit nicht aus, und bei einer schnellen Verbindung dauert sie zu lange.

Ein erster Ansatz besteht darin, den Event-Handler onLoad zu benutzen. Den gibt es auch bei Grafiken. Sobald bei jeder Grafik der onLoad-Event-Handler ausgeführt worden ist, kann auf die nächste Seite weiterverzweigt werden. Zudem sollte man nach einer bestimmten Zeit eh zur nächsten Seite übergehen, um die Geduld des Benutzers nicht allzu sehr zu strapazieren.

<HTML>
<HEAD>
<META HTTP-EQUIV="refresh" CONTENT="30;url=animation.html">
<!-- nach 30 Sekunden wird die Seite animation.html geladen -->
<TITLE>Animation vorbereiten</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var geladen = 0 //Anzahl der fertig geladenen Grafiken
function fertig(){
   geladen++
   if (geladen==4) //wenn alle Grafiken geladen sind
      location.href = "animation.html"
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Animation lädt... Bitte warten...</H3>
<IMG SRC="ani1.jpg" onLoad="fertig()" WIDTH=1 HEIGHT=1>
<IMG SRC="ani2.jpg" onLoad="fertig()" WIDTH=1 HEIGHT=1>
<IMG SRC="ani3.jpg" onLoad="fertig()" WIDTH=1 HEIGHT=1>
<IMG SRC="ani4.jpg" onLoad="fertig()" WIDTH=1 HEIGHT=1>
</HTML>

Jedes Mal, wenn eine Grafik fertig geladen worden ist, wird ein Zähler um eins erhöht, und es wird überprüft, ob damit die magische Zahl 4 (die Anzahl der Grafiken) erreicht worden ist.

Dieses Vorgehen funktioniert unter gewissen Umständen nicht – vor allem auf älteren Rechnern mit wenig Speicher. Wenn zwei Grafiken quasi gleichzeitig vollständig geladen worden sind und dadurch die Funktion fertig() zweimal aufgerufen wird, kann es vorkommen, dass einer der Aufrufe verschluckt wird. Wie gesagt, das kommt ganz selten vor, aber es gibt Zeugen ...

Hier hilft Ihnen vielleicht das Attribut complete eines Image-Objekts. Dieses gibt an, ob eine Grafik vollständig geladen worden ist (true) oder nicht (false). In der Funktion fertig() wird also jetzt kein Zähler erhöht, sondern überprüft, ob alle Grafiken vollständig geladen worden sind. Falls ja, wird zur Animationsseite übergegangen.

Im folgenden Listing lernen Sie außerdem noch eine Anwendungsmethode für die Event-Handler onAbort und onError kennen. Ersterer tritt dann in Aktion, wenn der Benutzer das Laden mit der Schaltfläche Stop abbricht; Letzterer wird aktiv, wenn ein Fehler bei der Übertragung auftritt (beispielsweise, wenn die Grafikdatei nicht existiert).

<HTML>
<HEAD>
<META HTTP-EQUIV="refresh" CONTENT="30;url=animation.html">
<!-- nach 30 Sekunden wird die Seite animation.htm geladen -->
<TITLE>Animation vorbereiten</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function fertig(){
   if (document.images[0].complete && document.images[1].complete &&
     document.images[2].complete && document.images[3].complete)
      location.href = "animation.html"
}
function abbruch(){
   alert("Sie wollen das Laden abbrechen? Na gut, wir leiten Sie
     weiter...")
   location.href="animation.html"
}
function fehler(){
   alert("Beim Laden einer der Grafiken ist ein Fehler aufgetreten.
     Wir leiten Sie trotzdem weiter...")
   location.href="animation.html"
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Animation lädt... Bitte warten...</H3>
<IMG SRC="ani1.jpg" onLoad="fertig()" onAbort="abbruch()"
  onError="fehler()" WIDTH=1 HEIGHT=1>
<IMG SRC="ani2.jpg" onLoad="fertig()" onAbort="abbruch()"
  onError="fehler()" WIDTH=1 HEIGHT=1>
<IMG SRC="ani3.jpg" onLoad="fertig()" onAbort="abbruch()"
  onError="fehler()" WIDTH=1 HEIGHT=1>
<IMG SRC="ani4.jpg" onLoad="fertig()" onAbort="abbruch()"
  onError="fehler()" WIDTH=1 HEIGHT=1>
</HTML>

Leider wird onError nicht mitgeteilt, welche der Grafiken beim Laden einen Fehler hatte. Man könnte diese Information aber als Parameter an die Funktion fehler() übergeben.

Abbildung 9.6  Die Meldung, die erscheint, wenn eine der Grafiken nicht existiert

9.6 Fragen & Aufgaben

1.	Schreiben Sie eine Seite, die mit dem Benutzer Katz und Maus spielt. Auf der Seite gibt es eine Grafik; wenn der Benutzer jedoch mit der Maus darüber fährt, verschwindet die Grafik und taucht an einer anderen Stelle wieder auf.
2.	Schreiben Sie das Programm aus Aufgabe 1 so um, dass der Benutzer etwas Zeit hat, die Grafik zu erwischen. Dafür verschwindet die Grafik zusätzlich nach einer Sekunde automatisch und taucht an einer anderen Stelle wieder auf.
3.	Die Navigation aus diesem Kapitel soll weiter vereinfacht und für andere leichter bearbeitbar gemacht werden. Dazu ist der HTML-Code für die Navigation auf jeder Seite, auch auf Unterseiten, identisch. Wie können Sie dieselbe Funktionalität wie zuvor sicherstellen?
4.	Schreiben Sie das letzte Beispiel aus diesem Kapitel so um, dass Sie den onLoad-Event-Handler nicht benötigen.

1    Netscape Navigator 2, Internet Explorer 3 scheiden hier beide glücklicherweise aus, da sie mit dem Image-Objekt nichts anfangen können.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 10 Fenster III
			10.1 Ein neues Fenster öffnen
			10.2 10.2 Fernsteuerung
			10.3 Fenster schließen
			10.4 Fenster in den Vordergrund holen
			10.5 Fenster bewegen mit JavaScript
			10.6 Fragen & Aufgaben

Kapitel 10 Fenster III

Sie hätte keinen anderen bei sich nicht fensterln und kammerln lassen, und überhaupt sei der Loisl ihr erster gewesen.

– Mostar, Unschuldig

Man kann nicht nur den Inhalt bestehender Fenster verändern, man kann auch gleich neue Fenster erstellen. Das kann sowohl zum Nutzen als auch sehr zum Ärger des Benutzers sein. In diesem Kapitel sehen Sie beides.

Früher war es noch fast unbezahlbar, eine .de-Domain zu registrieren, so dass man schon erwägen musste, eine vergleichsweise günstige .com-Domain zu erwerben. Heutzutage hat sich das umgekehrt: Mehrere Firmen buhlen um Kundschaft und unterbieten sich gegenseitig mit den Preisen. Für den geringen Preis gibt es jedoch oft auch nur geringe Leistungen. Manche Anbieter sind auf die Idee gekommen, als Gegenleistung für den Kampfpreis ein Werbebanner auf den Seiten einzublenden. Damit man das Banner auch besonders gut sieht, wird es in einem eigenen, neuen Fenster angezeigt. Bei Seiten mit besonders zwielichtigem Inhalt wird das auf die Spitze getrieben und es werden sogar mehrere neue Fenster geöffnet, was ich natürlich nur vom Hörensagen weiß.

10.1 Ein neues Fenster öffnen

Die Methode zum Öffnen eines neuen Fensters heißt window.open(). Dieser Methode werden bis zu drei Parameter übergeben, mindestens jedoch einer.

10.1.1 Ein Fenster öffnen und füllen

var fenster = window.open(URL, Fenstername, Optionen)

Der erste Parameter, URL, enthält die URL der Seite, die in das neue Fenster geladen werden soll. Ist URL eine leere Zeichenkette, so wird das Fenster zwar geöffnet, aber es wird keine Seite hineingeladen.

Die Position des neuen Fensters lässt sich nur ab Netscape Navigator 4 bestimmen; ansonsten hängt sie vom Browser ab. Die Größe hängt auch vom Browser ab, kann jedoch auch eingestellt werden (siehe weiter unten).

Mit dem folgenden Code wird die Homepage des Galileo Verlags in ein neues Fenster geladen:

var fenster = window.open("http://www.galileo-press.de/")

	Verwenden Sie stets window.open(), nicht bloß open().

Die Variable fenster ist eine Referenz auf das neue Fenster. Somit kann auf Eigenschaften des Fensters zugegriffen werden, beispielsweise auf das Objekt location oder auf das Objekt document. Letzteres ist besonders interessant, kann man doch so (mittels write()) den Inhalt des Fensters komplett mit JavaScript erzeugen. Die folgende Funktion öffnet ein neues Fenster und erzeugt in diesem eine HTML-Seite, die den übergebenen Parameter ausgibt.

function tag(s){ return "<"+s+">" }
function neuesfenster(text){
   var fenster = window.open("")
   if (fenster!=null){ //Hat das Öffnen des Fensters geklappt?
      fenster.document.open() //Öffnen für Schreibzugriff, notwendig!
      fenster.document.write(tag("HTML")+tag("BODY"))
      fenster.document.write(tag("H1") + text + tag("/H1"))
      fenster.document.write(tag("/BODY")+tag("/HTML"))
      fenster.document.close() //Schreibzugriff beenden, notwendig!
   }
}

Wie Sie sehen, können Sie mit document.open(), write() und close() rein theoretisch in jedem Fenster jeden beliebigen HTML-Code erzeugen; Anhängen geht nicht, aber Überschreiben ist möglich. Einige Leute haben das recht trickreich ausgenutzt und beispielsweise die Login-Masken mancher Webmail-Dienste mit dieser Methode überschrieben, wodurch sie die Passwörter von ahnungslosen Benutzern ausspionieren konnten. Aus diesem Grund erlauben die neueren Versionen aller Browser nur noch das Überschreiben von Fenstern, deren aktuelle URL von derselben Domain stammt wie das Fenster mit dem Skript.

	Einzige Ausnahme: Wird ein Fenster mit window.open("") geöffnet, so kann es vom selben Skript aus mit document.write() beschrieben werden. Die 16-Bit-Version Version 3.03 SP1 des Microsoft Internet Explorer jedoch enthält ein besonderes »Sicherheitsfeature«: Sie können mit window.open("") erzeugte Fenster so nicht mehr verändern; es erscheint dann eine Fehlermeldung! Sie müssen sich hier mit einem kleinen Trick behelfen: Verwenden Sie window.open("http://www.ihrserver.de/leer. html"), und fahren Sie dann wie oben beschrieben fort. Die Datei leer.html kann beliebigen Inhalt haben – der wird ja sowieso überschrieben – aber Sie sollten sich auf ein Standard-HTML-Gerüst beschränken:

<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
</BODY>
<HTML>

10.1.2 Ein Fenster öffnen und verlinken

Der zweite Parameter von window.open() gibt den Namen des neuen Fensters an. Man kann diesen Namen – genauso wie bei Frames – als Wert des TARGET-Attributs eines HTML-Links angeben, und das Ziel des Links wird in dem neuen Fenster geöffnet und nicht im aktuellen Fenster. Wenn Sie window.open() zweimal verwenden und dabei einen identischen zweiten Parameter angeben, wird nur ein Fenster geöffnet.

Die folgende Seite öffnet beim Laden ein neues Fenster mit der Homepage des Galileo Verlags. Die anderen Links auf der HTML-Seite öffnen die Homepages einiger Browser-Hersteller – in dem neuen Fenster.

<HTML>
<HEAD>
<TITLE>Neue Fenster</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function neuesfenster(){
  var fenster = window.open("http://www.galileo-press.de", "neu")
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="neuesfenster()">
<H3>Hier einige Links...</H3>
<UL>
<LI><A HREF="http://www.microsoft.com" TARGET="neu">Microsoft</A>
<LI><A HREF="http://www.netscape.com" TARGET="neu">Netscape</A>
<LI><A HREF="http://www.opera.com" TARGET="neu">Opera</A>
</UL>
</BODY>
</HTML>

Abbildung 10.1  Alle Links werden im neuen Fenster geöffnet.

10.1.3 Ein Fenster öffnen und anpassen

Der letzte Parameter ist gleichzeitig der interessanteste. Hier kann man das Aussehen des neuen Browser-Fensters etwas genauer anpassen. Neben der Höhe und Breite des Fensters kann man auch die meisten Leisten ein- und ausschalten. Es gibt hier zwei Arten von Parametern:

	Numerische Werte: Beispielsweise Höhe oder Breite; diese haben das Format height=400.
	Ja/Nein-Werte: Beispielsweise Statuszeile einblenden ja/nein. Die Werte yes und 1 oder die bloße Erwähnung der Option bedeuten ja, no und 0 bedeuten nein. Beispiel: status=yes,toolbar=no,menubar.

Sie können natürlich mehrere Parameter zusammen verwenden. Sie müssen diese dazu durch Kommata voneinander trennen, und Sie dürfen keine Leerzeichen verwenden! Der folgende Befehl öffnet ein Fenster, das 400 Pixel breit ist und eine Statuszeile hat:

var fenster = window.open("", "neu", "width=400,status=1")

In Tabelle 10.1 finden Sie die wichtigsten möglichen Parameter. Eine vollständige Auflistung befindet sich in der Referenz.

Tabelle 10.1  Eine Auswahl der Fensteroptionen

Option	Typ	Beschreibung
dependent	Ja/Nein	Das neue Fenster wird vom aufrufenden Fenster »abhängig«, d. h., beim Schließen des aufrufenden Fensters wird das neue Fenster auch geschlossen.
directories	Ja/Nein	Nur Netscape: Die Schaltflächen What’s new, What’s cool werden ein- oder ausgeblendet.
height	numerisch	Höhe des Fensters in Pixeln
innerHeight	numerisch	NN4: Höhe des Fensterinhalts in Pixeln (aktiver Bereich, vgl. height)
innerWidth	numerisch	NN4: Breite des Fensterinhalts in Pixeln (aktiver Bereich, vgl. width)
left	numerisch	IE4: Abstand vom linken Bildschirmrand in Pixeln
menubar	Ja/Nein	Menüleiste wird ein- bzw. ausgeblendet.
outerHeight	numerisch	NN4: Gesamthöhe des Fensters (inkl. Titelleiste, Scrollbalken, Rahmen etc.) in Pixeln
outerWidth	numerisch	NN4: Gesamtbreite des Fensters (inkl. Titelleiste, Scrollbalken, Rahmen etc.) in Pixeln
screenX	numerisch	NN4: Abstand vom linken Bildschirmrand in _Pixeln
screenY	numerisch	NN4: Abstand vom oberen Bildschirmrand in _Pixeln
scrollbars	Ja/Nein	Scrollbalken am rechten und/oder unteren Rand des Browser-Fensters werden angezeigt/unterbunden.
status	Ja/Nein	Die Statuszeile wird ein- oder ausgeblendet.
toolbar	Ja/Nein	Die Navigationsleiste (mit den Schaltflächen für Vor/Zurück/Neu laden etc.) wird ein- oder ausgeblendet.
top	numerisch	IE4: Abstand vom oberen Bildschirmrand in Pixeln
width	numerisch	Breite des Fensters in Pixeln

Wenn einer dieser Parameter nicht angegeben wird, nimmt der JavaScript-Interpreter an, er wäre auf no bzw. 0 gesetzt worden. Der folgende Aufruf erzeugt also ein ganz mageres Fenster:

var fenster = window.open("", "neu", "")

Wie Sie bei den vorherigen Beispielen gesehen haben, fehlt der dritte Parameter komplett, so sieht das neue Fenster gemäß den Standardwerten des Browsers aus. Beim Netscape Navigator beispielsweise entsprechen die Ausmaße und angezeigten Leisten denen des zuletzt aktiven Browser-Fensters.

Kommen wir zu einer der eingangs erwähnten Anwendungsmöglichkeiten zurück: zur Anzeige eines nervigen Werbebanners. Wenn Ihr Werbebanner eine Breite von 200 x 100 Pixeln hat, könnte Ihr Aufruf folgendermaßen aussehen:

<HTML>
<HEAD>
<TITLE>Werbebanner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function werbebanner(){
   var fenster = window.open("banner.html", "neu", "width=210,
     height=110")
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="werbebanner">
<H1>Werbebanner wird geladen...</H1>
</BODY>
</HTML>

	Unter UNIX kann die Größe eines Fensters über X-Ressourcen bestimmt werden, die immer Priorität haben.

Die Datei banner.html kann folgendermaßen aussehen:

<HTML>
<HEAD>
<TITLE>Banner</TITLE>
</HEAD>
<BODY TOPMARGIN=0 LEFTMARGIN=0 MARGINWIDTH=0 MARGINHEIGHT=0>
<!-- kein Abstand zum Fensterrand -->
<A HREF="http://www.ihranzeigenkunde.de" TARGET="_blank">
<IMG SRC="banner.gif" WIDTH=200 HEIGHT=100 BORDER=0>
</A>
</BODY>
</HTML>

	Aus Sicherheitsgründen muss ein mit JavaScript geöffnetes Fenster mindestens 100 Pixel hoch und 100 Pixel breit sein. Wenn Sie also für Höhe oder Breite einen Wert kleiner hundert angeben, wird das Fenster trotzdem 100 Pixel breit oder hoch dargestellt. Mit dem Netscape Navigator 4 lässt sich das umgehen, indem man signierte Skripten nutzt. Ebenso können Sie (mit screenX/screenY) ein Fenster nicht aus dem sichtbaren Bereich hinaus verschieben, wenn Sie kein signiertes Skript verwenden.

Mit der folgenden HTML-Seite können Sie einige Parameter für das Aussehen des neuen Fensters anpassen:

<HTML>
<HEAD>
<TITLE>Fenster-Test</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function neuesfenster(formular){
   var optionen="width=400,height=300"
   for (var i=0; i<formular.elements.length; i++){
      if (formular.elements[i].checked)
         optionen += "," + formular.elements[i].name
   }
   var fenster = window.open("", "neu", optionen)
   if (fenster != null){
      with (fenster.document){
         open()
         write("<"+"HTML"+">"+"<"+"BODY"+">")
         write("Neues Fenster mit folgenden Optionen: "+optionen)
         write("<"+"HR"+">")
         write("<"+"A HREF='javascript:window.close()'"+">")
         write("Fenster schließen"+"<"+"/A"+">")
         write("<"+"/BODY"+">"+"<"+"/HTML"+">")
         close()
      }
   }
}
//--></SCRIPT>
</HEAD>
<BODY>
<H1>Fenster-Optionen auswählen</H1>
<FORM>
<INPUT TYPE="CHECKBOX" NAME="dependent"> dependent<BR>
<INPUT TYPE="CHECKBOX" NAME="directories"> directories<BR>
<INPUT TYPE="CHECKBOX" NAME="hotkeys"> hotkeys<BR>
<INPUT TYPE="CHECKBOX" NAME="location"> location<BR>
<INPUT TYPE="CHECKBOX" NAME="menubar"> menubar<BR>
<INPUT TYPE="CHECKBOX" NAME="scrollbars"> scrollbars<BR>
<INPUT TYPE="CHECKBOX" NAME="status"> status<BR>
<INPUT TYPE="CHECKBOX" NAME="toolbar"> toolbar<BR>
</FORM>
<A HREF="javascript:neuesfenster(document.forms[0])">Fenster
  erzeugen</A>
</BODY>
</HTML>

Abbildung 10.2  Die verschiedenen Fenstereigenschaften können direkt ausprobiert werden.

Beachten Sie bei dem Listing, dass in das neue Fenster neben den Optionen auch ein Link zum Schließen des Fensters geschrieben wird:

<A HREF="javascript:window.close()">Fenster schließen</A>

Das Fenster kann natürlich auch vom aufrufenden Skript aus geschlossen werden; verwenden Sie dazu die Referenz auf das neue Fenster, die von window.open() zurückgegeben wird, in unserem Beispiel also fenster. close().

Ein kurzes Wort noch zu der Zeile if (fenster != null): Es kann sein, dass das Öffnen des neuen Fensters nicht funktioniert hat; insbesondere der Internet Explorer gibt bei wenig Speicher gern eine Fehlermeldung aus und öffnet das Fenster dann nicht.

Anwendungen für die neuen JavaScript-Fenster gibt es viele: Beispielsweise könnten Sie auf Ihren Webseiten eine Hilfefunktion anbieten. Der Hilfetext kann dann in einem neuen Fenster (ohne platzraubende Symbolleisten) dargestellt werden; dies ist insofern praktisch, da der Benutzer nicht auf die Zurück-Schaltfläche seines Browsers klicken muss, um wieder zu der Seite zurückzukehren, auf der er die Hilfe in Anspruch nehmen wollte.

10.1.4 Modale Fenster

Ein sogenanntes modales Fenster ist die gierige Variante von neuen Fenstern. Das aufrufende Fenster ist praktisch inaktiv, Sie können darauf erst wieder zugreifen, wenn das neue, modale Fenster wieder geschlossen worden ist. Sie haben diese Art von Fenstern schon kennen gelernt, sie werden beispielsweise durch window.alert(), window.confirm() und window.prompt() erzeugt. Die Gestaltungsmöglichkeit dieser Fenster war ja relativ gering, aber ab Browsern der Versionsnummer 4 gibt es Alternativen.

Für den Netscape Navigator gibt es die Fenstereigenschaft alwaysRaised, aber die funktioniert nur in Zusammenarbeit mit so genannten Signierten Skripten (siehe dazu auch das gleich lautende Kapitel). Ab dem Internet Explorer 4 gibt es für Benutzer des Microsoft-Browsers die Möglichkeiten, ein modales Fenster zu erzeugen. Die dazugehörige Methode des Fenster-Objekts heißt showModalDialog(), und in Tabelle 10.2 sehen Sie die dazugehörigen Fenstereigenschaften:

Tabelle 10.2  Fensteroptionen für modale Fenster

Option	Typ	Beschreibung
Center	Ja/Nein	Das neue Fenster wird zentriert dargestellt (Standard).
dialogHeight	numerisch	Höhe des Fensters in Pixeln
dialogLeft	numerisch	Abstand vom linken Bildschirmrand in Pixeln
dialogTop	numerisch	Abstand vom oberen Bildschirmrand in Pixeln
dialogWidth	numerisch	Breite des Fensters in Pixeln
help	Ja/Nein	Hilfesymbol (Fragezeichen) wird angezeigt (Standard)/nicht angezeigt.
status	Ja/Nein	Die Statuszeile wird ein- (Standard) oder ausgeblendet.
resizeable	Ja/Nein	Die Größe des Fensters kann vom Benutzer geändert/nicht geändert (Standard) werden.

Der folgende Code öffnet also ein modales Fenster im Internet Explorer. Sie können dort beispielsweise einen Hilfetext anzeigen. Wie immer der Warnhinweis: Da dieser Code nur mit dem Internet Explorer funktioniert, sollten Sie darauf achten, dass Ihre Seiten auch ohne die modalen Fenster navigierbar bleiben – außer natürlich, Sie operieren in einem Intranet, und die Firmenpolitik verbietet Netscape-Browser (solche Firmen gibt es tatsächlich).

<SCRIPT LANGUAGE="JavaScript"><!--
var fenster = window.showModalDialog("", "Modal", "dialogHeight=300,
  dialogWidth=400,status=no,resizeable")
//--></SCRIPT>

In Abschnitt 10.4 finden Sie übrigens ein paar Tipps, wie Sie auch unter anderen Browsern eine Art von modalem Fenster erzeugen können.

10.2 10.2 Fernsteuerung

	Wie Sie vom ausrufenden Fenster aus auf das neue Fenster zugreifen können, wissen Sie jetzt. In die andere Richtung ist das leider nicht so einfach, insbesondere, wenn man auch ältere Browser unterstützen will.

Mit JavaScript 1.1 wurde die Fenster-Eigenschaft opener eingeführt, die eine Referenz auf das öffnende Fenster darstellt; auch der Internet Explorer 3 hat diese Eigenschaft übernommen. Mit JavaScript 1.0 kann man sie jedoch relativ einfach nachbilden. In diesem Falle ist die Eigenschaft opener des neuen Fensters gleich null, und man kann sie auf das aktuelle Fenster (also self) setzen:

<SCRIPT LANGUAGE="JavaScript"><!--
var fenster = window.open("seite.htm", "neu")
if (fenster.opener==null)
   fenster.opener = self
//--></SCRIPT>

10.2.1 Links mit JavaScript

Über die Methode opener ist es möglich, auf das ursprüngliche Fenster zuzugreifen. Im Folgenden soll eine Fernsteuerung entwickelt werden. Ausgangspunkt ist folgendes Frameset:

<HTML>
<HEAD>
<TITLE>Fernsteuerung</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function inhalt(){ return "<"+"HTML"+">"+"<"+"/HTML"+">" }
//--></SCRIPT>
</HEAD>
<FRAMESET ROWS="100,*">
   <FRAME SRC="navi.html" NAME="navigation">
   <FRAME SRC="javascript:top.inhalt()">
</FRAMESET>
<NOFRAMES>
<BODY>Ihr Browser kann mit Frames nicht anfangen!</BODY>
</NOFRAMES>
</HTML>

Die Datei navi.html sieht folgendermaßen aus:

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript"><!--
function fernsteuerung(){
   var fenster = window.open("remote.html", "fern", "height=200,
     width=400,status=1")
   if (fenster.opener == null)
      fenster.opener = self
}
//--></SCRIPT>
<BODY>
<A HREF="javascript:fernsteuerung()">Fernsteuerung öffnen</A>
</BODY>
</HTML>

Es passiert also nichts Weltbewegendes: Durch den Klick auf den Link wird ein neues Fenster mit der Datei remote.html geladen. Diese sieht folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>Fernsteuerung</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function lade(seite){
   //kommt noch...
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Meine Lieblingslinks</H3>
<UL>
<LI><A HREF="javascript:lade('http://www.microsoft.com')">Microsoft</A>
<LI><A HREF="javascript:lade('http://www.netscape.com')">
  Netscape</A>
<LI><A HREF="javascript:lade('http://www.opera.com')">Opera</A>
</UL>
<A HREF="javascript:window.close()">Fenster schließen</A>
</BODY>
</HTML>

In der Funktion lade() muss die übergebene URL in den unteren Frame der Beispielsseite geladen werden. Mit der Eigenschaft window.opener hat man eine Referenz auf den oberen Frame, und – wie im Kapitel »Fenster II« gezeigt – kann man dann auf den unteren Frame zugreifen:

function lade(seite){
   if (window.opener!=null)
      window.opener.parent.frames[1].location.href = seite
}

10.2.2 Links ohne JavaScript

Eigentlich ist dieses Vorgehen zu umständlich. Man kann auch mit ordinären HTML-Links arbeiten. Als TARGET-Attribut gibt man den Namen des Frames bzw. des Fensters an, in den bzw. das die neue Seite geladen werden soll.

Im obigen Beispiel wurde jedoch aus Versehen kein Name für den Frame angegeben; bei Fenstern haben Sie ja ohnehin standardmäßig keinen Namen. Mit JavaScript lässt sich dieser Name jedoch ganz einfach vergeben; die entsprechende Eigenschaft heißt name.

Ändern Sie also die Funktion fernsteuerung() folgendermaßen ab:

function fernsteuerung(){
   var fenster = window.open("remote.html", "fern", "height=200,
     width=400,status=1")
   self.name = "Ziel"
   if (fenster.opener == null)
      fenster.opener = self
}

Die Fernsteuerung besteht dann aus (beinahe) reinem HTML-Code:

<HTML>
<HEAD>
<TITLE>Fernsteuerung</TITLE>
</HEAD>
<BODY>
<H3>Meine Lieblingslinks</H3>
<UL>
<LI><A HREF="http://www.microsoft.com" TARGET="Ziel">Microsoft</A>
<LI><A HREF="http://www.netscape.com" TARGET="Ziel">Netscape</A>
<LI><A HREF="http://www.opera.com" TARGET="Ziel">Opera</A>
</UL>
<A HREF="javascript:window.close()">Fenster schließen</A>
</BODY>
</HTML>

10.3 Fenster schließen

Wie Sie bereits gesehen haben, kann ein Fenster mit Fensterreferenz.close() geschlossen werden. Es gibt jedoch eine Einschränkung: Laden Sie doch einmal folgende HTML-Seite in Ihren Browser:

<HTML>
<HEAD>
<TITLE>window.close()</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript"><!--
window.close()
</SCRIPT>
</BODY>
</HTML>

	Sie sollten eine Warnung erhalten (zumindest ab Netscape Navigator 3 bzw. Internet Explorer 4). Das wäre ja auch noch schöner, wenn man mit JavaScript jedes beliebige Fenster schließen könnte. Fenster, die mit JavaScript geöffnet wurden, können jedoch problemlos geschlossen werden, wie Sie im vorherigen Abschnitt ja schon gesehen haben.
Abbildung 10.3  Warnmeldung beim Schließen eines Fensters,

das nicht mit JavaScript geöffnet worden ist

10.3.1 Andere Fenster schließen

Etwas komplizierter ist es jedoch, wenn ein anderes Fenster geschlossen werden soll. Angenommen, der Benutzer schließt das Fenster mit der systemspezifischen Tastenkombination (unter Windows beispielsweise mit (Alt)+(F4)). Die Variable, in der eine Referenz auf das Fenster abgespeichert ist, verschwindet dadurch ja nicht. Ist das Fenster also schon geschlossen, würde Fensterreferenz.close() eine Fehlermeldung ausspucken.

	Die Fernsteuerung soll so abgeändert werden, dass sie von der Hauptseite aus wieder geschlossen werden kann. Ab Netscape Navigator 3 gibt es die Fenstereigenschaft closed, einen Booleschen Wert, der angibt, ob das Fenster noch offen ist oder nicht. Somit kann die Datei navi.html folgendermaßen geändert werden, damit die gewünschte Funktionalität sichergestellt wird:

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript"><!--
var fenster //Variable muss global sein!
function fernsteuerung(){
   fenster = window.open("remote.html", "fern", "height=200,
     width=400,status=1")
   self.name = "Ziel"
   if (fenster.opener == null)
      fenster.opener = self
}
function schliessen(){
   if (fenster && !fenster.closed)
      fenster.close()
}
//--></SCRIPT>
<BODY>
<A HREF="javascript:fernsteuerung()">Fernsteuerung öffnen</A><BR>
<A HREF="javascript:schliessen()">Fernsteuerung schließen</A>
</BODY>
</HTML>

Das Kernstück ist die Abfrage if (fenster && !fenster.closed). Wie Sie bereits wissen, werden Boolesche Ausdrücke in JavaScript von links nach rechts ausgewertet. Wurde also noch kein Fenster geöffnet, wird der rechte Teil der Bedingung gar nicht mehr überprüft, und es kommt auch keine Fehlermeldung. Falls schon einmal ein Fenster geöffnet wurde, wird der rechte Teil überprüft. Ist die Eigenschaft fenster.closed gleich false, muss das Fenster noch offen sein, also wird es geschlossen.

10.3.2 Lösung für ältere Browser

	Für Internet Explorer 3 und Netscape Navigator 2 muss man sich etwas besonderes einfallen lassen. Eine zuverlässige Lösung ist folgende: Bevor versucht wird, das Fenster zu schließen, wird es noch einmal geöffnet, und zwar mit demselben zweiten Parameter (Fensternamen) wie zuvor. Wie Sie bereits wissen, wird genau dann kein neues Fenster geöffnet, wenn das alte noch offen ist. Das Ergebnis dieser Aktion ist aber klar: Es existiert auf jeden Fall ein (offenes) Fenster, das dann geschlossen werden kann.

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript"><!--
var fenster //Variable muss global sein!
function fernsteuerung(){
   fenster = window.open("remote.html", "fern", "height=200,
     width=400,status=1")
   self.name = "Ziel"
   if (fenster.opener == null)
      fenster.opener = self
}
function schliessen(){
   fenster = window.open("", "remote", "height=200,width=400")
   if (fenster)
      fenster.close()
}
//--></SCRIPT>
<BODY>
<A HREF="javascript:fernsteuerung()">Fernsteuerung öffnen</A><BR>
<A HREF="javascript:schliessen()">Fernsteuerung schließen</A>
</BODY>
</HTML>

Einen kleinen Preis muss man jedoch zahlen: Man sieht ein kurzes Flackern des Fensters. Es wäre also effizienter, nur beim Netscape Navigator 2 und beim Internet Explorer 3 das Fenster (evtl. erneut) zu öffnen. Der Code wird dadurch zwar ein wenig hässlicher, aber bei einer Großzahl von Nutzern wird das Fenster ohne Störungen geschlossen.

function schliessen(){
   NN2 = (navigator.userAgent.indexOf("mozilla")!=
-1&&parseInt(navigator.appVersion)==2)
   IE3 = (navigator.userAgent.indexOf("msie")!=
-1&&parseInt(navigator.appVersion)<4)
   if (NN2||IE3)
      fenster = window.open("", "remote", "height=200,width=400")
   if (fenster && !fenster.closed)
      fenster.close()
}

10.4 Fenster in den Vordergrund holen

Mit der Fensteroption alwaysRaised kann man im Netscape Navigator ab Version 4 einstellen, dass das neue Fenster immer vor allen anderen Browser-Fenstern erscheinen soll – aber das geht wie gesagt nur beim Netscape Navigator, und außerdem braucht man ein signiertes Skript. Man kann diesen Effekt jedoch relativ leicht nachbilden. Sie erinnern sich vielleicht an das Kapitel über Formularfelder (»Formulare I«). Dort stand folgender Code in einem Texteingabefeld, das schreibgeschützt werden sollte: onFocus="this.blur()". In unserem Fall wird genau das Gegenteil benötigt: Wenn das Fenster den Focus verliert, soll es ihn wieder erhalten!

Es reicht natürlich beinahe, einfach die beiden Begriffe auszutauschen:

<BODY onBlur="if (window.focus) window.focus()">

Die Abfrage hat folgenden Hintergrund: window.focus() gibt es erst ab Netscape Navigator 3 und Internet Explorer 4. Bei älteren Browsern kann man die Fehlermeldung aber ganz einfach abfangen: window.focus (ohne Klammern!) gibt dann false zurück.

Bevor Sie dieses Skript jedoch exzessiv einsetzen, denken Sie zweimal nach. Wenn sich ein Fenster stets in den Vordergrund drängt, wird es ganz schnell abgeschossen (sprich: geschlossen). Es gibt kaum eine Anwendung, in der so ein Fensterverhalten angebracht wäre.

Der Sinn des ganzen Exkurses: Ihnen ist vielleicht aufgefallen, dass die Fernsteuerung natürlich nicht mehrmals geöffnet wird, wenn Sie mehrmals auf den Fernsteuerungslink klicken (warum?); aber sie verschwindet beim zweiten Öffnen in den Hintergrund bzw. kommt nicht in den Vordergrund wie beim ersten Öffnen. In diesem Fall kann window.focus() wirklich sinnvoll eingesetzt werden. Ändern Sie die Funktion fernsteuerung() folgendermaßen ab:

function fernsteuerung(){
   (if !fenster && fenster.closed){
      fenster = window.open("remote.htm", "fern", "height=200,
        width=400,status=1")
      self.name = "Ziel"
      if (fenster.opener == null)
         fenster.opener = self
} else {
   if (fenster.focus) fenster.focus()
}

10.5 Fenster bewegen mit JavaScript

Prinzipiell gibt es zwei Möglichkeiten, ein Fenster zu bewegen, und das ist reine Definitionssache. Entweder wollen Sie das gesamte Fenster irgendwo hinbewegen, oder Sie wollen den Inhalt des Fensters scrollen. Beides ist mit neueren Browsern möglich und wird an dieser Stelle kurz vorgestellt.

10.5.1 Fenster verschieben

Eine häufig gestellte Frage lautet: Wie kann ich das Browser-Fenster zentrieren? Andere Leute wiederum möchten, dass das Browser-Fenster maximiert oder minimiert wird (soviel vorweg, das ist nicht möglich), oder sich am oberen Bildschirmrand befindet. Dies ist kein aufwendiges Verfahren, es müssen einfach entsprechende Eigenschaften des window-Objekts gesetzt oder ausgelesen oder Methoden aufgerufen werden. Übertreiben Sie es jedoch nicht mit diesen Effekten. Viele Webbesucher reagieren ziemlich giftig, wenn man ihnen vorschreiben will, wo sich ein Fenster befindet.

Der Netscape Navigator (ab Version 4) kann ein Fenster verschieben, und zwar sowohl an eine bestimmte Position als auch um einen gewissen Wert. Dazu gibt es zwei Methoden:

	window.moveTo(x, y): Verschiebt das Fenster so, dass die linke obere Ecke die Koordinaten (x, y) hat. Es handelt sich hier um eine absolute Verschiebung. Sie können das Fenster damit nicht aus dem sichtbaren Bereich hinaus verschieben, außer Sie verwenden signierte Skripten (die werden gegen Ende des Buches vorgestellt).
	window.moveBy(x, y): Verschiebt das Fenster horizontal um x Pixel, vertikal um y Pixel, also eine relative Verschiebung. Auch hier kann das Fenster nicht aus dem sichtbaren Bereich hinaus verschoben werden.

Erinnern Sie sich noch an die Auflistung der Parameter für window. open()? All diese Parameter sind auch gleichzeitig Eigenschaften für das window-Objekt. Somit werden beispielsweise mit window.outerHeight und window.outerWidth die Ausmaße des Browser-Fensters angegeben.

Um nun die Maximierung eines Fensters zu simulieren (man führt damit nicht die API-Funktion für die Fenstermaximierung aus, sondern vergrößert das Fenster nur entsprechend), muss man noch die Ausmaße des Bildschirms bestimmen. Seit JavaScript 1.2 kann man diese Werte aus dem screen-Objekt erhalten:

	screen.availWidth enthält die Bildschirmbreite.
	screen.availHeight enthält die Bildschirmhöhe.

Eine Funktion zum Maximieren des Fensters sieht also folgendermaßen aus. Die linke obere Ecke des Fensters wird zunächst an die linke obere Ecke des Bildschirms gesetzt, und dann wird das Fenster entsprechend vergrößert.

function maximieren(){
   window.moveTo(0, 0)
   window.outerHeight = screen.availHeight
   window.outerWidth = screen.availWidth
}

10.5.2 Fensterinhalt scrollen

Schon mit JavaScript Version 1.1 wurden Methoden zum Scrollen des Fensterinhalts eingeführt. Die dazugehörige Methode heißt window. scroll(x, y). Sie scrollt den Fensterinhalt an die angegebenen Koordinaten. Es ist eigentlich unlogisch, dass das Scrollen eine Methode des window-Objekts ist, da ja nicht das Fenster gescrollt wird, sondern das Dokument, das sich darin befindet. Auch hier gilt: Übertreiben Sie es nicht. Der Benutzer ärgert sich immer, wenn er das Gefühl hat, nicht die Kontrolle über ein Fenster zu besitzen. Scrollen Sie also nur dann, wenn es wirklich Sinn macht.

Eine der möglichen Anwendungen besteht darin, nach oben zu scrollen. Auf vielen, längeren Webseiten finden Sie einen Link, der nach oben scrollt – Sie ersparen Ihren Benutzern so die Mühe, mit der Maus den Scrollbalken zu treffen. Dieser Effekt wird meistens so angeboten:

<A HREF="#top">nach oben</A>

Am Anfang des Dokuments befindet sich dann eine Textmarke namens "top", zu der dann gescrollt wird. Das ist ein netter Effekt, vor allem bei längeren Dokumenten. Zum einen jedoch ändert sich die URL – was Neulinge immer stark irritiert, man glaubt es kaum – und zum anderen ist es bei komplexeren Dokumenten nicht immer möglich, ganz oben eine Textmarke unterzubringen, Wenn beispielsweise direkt nach dem <BODY>-Tag ein Werbebanner eingefügt wird (das hat der Gratis-Hoster Hypermart früher so gemacht), kann man nie nach ganz oben scrollen.

Mit JavaScript 1.1 geht das Scrollen an den Dokumentenanfang ganz bequem. Es muss einfach zu den Koordinaten (0, 0) gescrollt werden. Damit es bei älteren Browsern keine Fehlermeldung gibt, kann man beispielsweise Folgendes versuchen:

<A HREF="javascript:if (window.scroll)
window.scroll(0, 0)">nach oben</A>

Dann wäre der Link jedoch inaktiv, wenn der Benutzer einen älteren Browser (zum Beispiel Internet Explorer 3) verwendet. Aus diesem Grund sollte man hier den Link mit document.write() erzeugen.

<SCRIPT LANGUAGE="JavaScript1.1"><!--
function tag(s) { return "<"+s+">" }
document.write(tag("A HREF='javascript:window.scroll(0, 0)'")+
  "nach oben"+tag("/A"))
//--></SCRIPT>

Wie bereits erwähnt, verbietet sich das jedoch innerhalb einer Tabellenzelle. So ist die folgende Lösung wohl die optimale: Es existiert auch eine Textmarke, aber wenn der Browser die scroll-Methode unterstützt, wird diese verwendet:

<A HREF="#top" onClick="if (window.scroll) {window.scroll(0, 0);
  return false}">nach oben</A>

Netscape hat mit JavaScript 1.2 bzw. seiner Version 4 zwei neue Methoden eingeführt. Dabei verhält sich window.scrollTo(x, y) identisch zu window.scroll(x, y), während window.scrollBy(x, y) neu ist: Genau so wie bei window.moveBy(x, y) wird hier relativ gescrollt.

Die Methoden zum Scrollen werden im Zusammenhang mit der exakten Positionierung von HTML-Dokumenten bei DHTML noch interessant werden; fürs erste aber sollte dieser Einblick genügen.

10.6 Fragen & Aufgaben

1.	Erstellen Sie eine HTML-Seite mit drei Textmarken. Mit einer Fernsteuerung in einem neuen Fenster soll jede dieser Marken angesprungen werden können.
2.	Erstellen Sie (für Netscape Navigator 4) eine Funktion center(), die das aktuelle Fenster auf dem Bildschirm zentriert.
3.	Wie könnte man an das Ende eines Dokuments scrollen?
4.	Öffnen Sie ein neues Fenster, das sich in der linken oberen Bildschirmecke befindet. Achten Sie darauf, dass das sowohl mit dem Netscape Navigator als auch mit dem Internet Explorer funktioniert!
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 11 Cookies
			11.1 Was ist ein Cookie?
			11.2 Wie sieht ein Cookie aus?
			11.3 Cookies mit JavaScript
			11.4 Informationen behalten ohne Cookies
			11.5 Fragen & Aufgaben

Kapitel 11 Cookies

250 g Mehl, 150 g Butter oder Margarine, 60 g Zucker,

1 Ei oder 1 Eigelb, 2 EL kaltes Wasser, 1 Prise Salz.

– Zutatenliste für Plätzchenteig, aus: Sybil Gräfin Schönfeldt, Kochbuch für Kinder

Cookies sind böse. Man kann damit den Benutzer ausspionieren, seine E–Mail-Adresse und alle seine Passwörter herausbekommen. Über Cookies erhält eine Webseite Lese- und Schreibzugriff auf die lokale Festplatte des Benutzers. Cookies sind primär ein Ärgernis, und sie sollten permanent ausgeschaltet werden. Es gibt keine nützliche Anwendung. Hat man viele Cookies, so hat man automatisch auch viele kleine Dateien auf der Festplatte, und diese wird auf diese Weise zugemüllt, wertvoller Speicherplatz geht verloren. Andererseits sind Cookies eigentlich richtige Programme, Spionageprogramme, um genau zu sein. Der Papst ist evangelisch, und der Bär wohnt nicht im Wald.

Der letzte Satz ist frei erfunden, die Aussagen zuvor stammen jedoch allesamt aus der Presse, teilweise sogar aus der so genannten Fachpresse. An einigen der Aussagen ist entfernt etwas Wahres dran, manche sind bedingt gültig. Man kann jedoch Cookies nicht global als böse abkanzeln. In diesem Kapitel wird beschrieben, was ein Cookie wirklich ist, welche Möglichkeiten und welche Einschränkungen es gibt, und wie man sie mit JavaScript erstellen und nutzen kann.

11.1 Was ist ein Cookie?

HTTP wird als stateless protocol (zustandsloses Protokoll) bezeichnet: Die Verbindung zum Server wird geöffnet, Browser und Server senden Daten (der Browser eine HTTP-Anfrage, der Server ein Dokument, eine Datei o. Ä.), und dann wird die Verbindung wieder gekappt. Es ist somit praktisch unmöglich, einen Benutzer auf mehreren Seiten einer Website zu verfolgen. Sieht man von einer Logdatei-Analyse ab, ist es bei mehreren parallelen Zugriffen praktisch unmöglich festzustellen, welche Anfrage von welchem Benutzer kam.

Dies ist nicht nur ein herber Schlag für eine ganze Berufgruppe, die Marketing-Leute, sondern auch für andere Bereiche ist es interessant, den Benutzer zu kennen. In einem virtuellen Kaufhaus muss auf jeder Seite der Kunde bekannt sein, oder zumindest muss die Applikation wissen, welche Artikel dieser Kunde in seiner Datenbank hat. In dem Kapitel »Fenster I« wurde eine Warenkorbanwendung mit Frames vorgestellt, aber Frames sind nicht jedermanns Sache. In diesem Kapitel wird noch eine weitere Lösung vorgestellt, die jedoch auch ihre Nachteile aufweist.

Cookies sind manchmal das geringste Übel. Ein Cookie ist prinzipiell eine Textinformation, die auf der Festplatte des Benutzers gespeichert wird. Bei jeder HTTP-Anfrage werden bestimmte Cookies des Benutzers mitgeschickt (dazu später mehr), und bei der HTTP-Antwort des Webservers können ebenfalls Cookies mitgeschickt werden. Der Netscape Navigator speichert Cookies zeilenweise in der Datei cookies.txt im jeweiligen Benutzerverzeichnis im Netscape Navigator, während die Datei beim Macintosh MagicCookie heißt. Der Microsoft Internet Explorer verwendet für jeden einzelnen Cookie eine einzelne Textdatei, außer bei manchen Versionen wie etwa 3.x für Windows 3.11, dort befinden sich die Cookies auch insgesamt in einer Datei.

	Netscape selbst hat noch zu Zeiten der Version 1.1 Cookies vorgeschlagen (implementiert wurden sie jedoch erst in Version 2.0). Die Spezifikation, damals wie heute gleich, finden Sie unter http://www.netscape.com/ newsref/std/cookie_spec.html. Cookies werden vom Internet Explorer ab Version 3 unterstützt – mit JavaScript im lokalen Gebrauch jedoch erst ab Version 4 (auf einem Webserver schon ab Version 3). Es gibt einige, von Netscape aufgelegte Einschränkungen bei Cookies, die zum Großteil auch nur für den Netscape Navigator gelten. Um die Browserkompatibilität zu wahren, sollte man sich jedoch generell daran halten. Ein Cookie darf höchstens 4 KB an Daten enthalten (in der Realität sind es jedoch nur etwa 2 000 Zeichen), und der Browser kann nur 300 Cookies verwalten. Sobald der Benutzer den 301. Cookie enthält, wird dafür ein anderer (in der Regel der älteste) gelöscht. Cookies werden, wie bereits erwähnt, vom Browser gespeichert und verwaltet; wenn Sie mehrere Browser benutzen, speichert jeder seine eigenen Cookies, Sie können Cookies also nicht browser-übergreifend verwenden.

11.2 Wie sieht ein Cookie aus?

Ein Cookie erinnert an den Versand eines Formulars via GET. Jeder Cookie hat als Hauptkomponente (mindestens) ein Name-Wert-Paar1 . Auch hier gelten wieder die üblichen Regeln der URL-Codierung, also heißt es Autor=Christian+Wenz oder Autor=Christian%20Wenz, weil das Plus-Zeichen oder hexadezimal 20 (dezimal 32) das Leerzeichen ersetzt. Außerdem hat ein Cookie noch die folgenden weiteren, optionalen Parameter in Form von Name-Wert-Paaren:

	domain  Dieser Parameter bezeichnet die Domain des Servers, der den Cookie lesen darf. Standardmäßig ist das der Server-Anteil der URL der Seite, die den Cookie setzt. Dieses Attribut wird jedoch unter bestimmten Umständen anders gesetzt. Angenommen, eine Firma hat mehrere Webserver, server1.firma.de, server2.firma.de und www.firma.de. Von jedem dieser Server aus soll ein Cookie gelesen werden können. Standardmäßig wäre der domain-Wert des Cookies, wenn er auf www.firma.de/cookie.htm gesetzt worden ist, www.firma.de; als direkte Konsequenz hätten server1.firma.de und server2.firma.de keinen Zugriff auf diesen Cookie. Um dies zu vermeiden, kann das domain-Attribut gesetzt werden. Es würde in diesem Fall auf .firma.de gesetzt, wodurch jeder Server, dessen Name auf .firma.de endet, den Cookie lesen kann. Ein Domainname muss hier mindestens zwei Punkte enthalten, deswegen steht ein Punkt vor firma.de. Einige Leute sind auf die Idee gekommen, einfach die Cookies mehrerer (unterschiedlicher) Seiten auf einem zentralen Cookie-Server zu speichern. Beim Netscape Navigator gibt es eine Option, die dies vereitelt (Bearbeiten/Einstellungen/Erweitert/Nur an den ursprünglichen Server zurückgesendete Cookies akzeptieren). Pro Domain werden übrigens nur 20 Cookies akzeptiert, danach werden alte Cookies gelöscht bzw. überschrieben.
	expires  Jeder Cookie hat ein Ablaufdatum, nach dem er gelöscht wird. Manche Seiten setzen dieses Datum auf das Jahr 2037, und so lange wird die Festplatte des Benutzers sicher nicht halten – es sind also (beinahe) unendlich lange gültige Cookies möglich. Eine Sicherheit, dass der Cookie tatsächlich so lange hält, hat man indes nicht, da Cookies manuell oder durch Überschreitung der 300er-Grenze vom Netscape Navigator gelöscht werden können. Wird kein Ablaufdatum angegeben, so wird der Cookie gelöscht, sobald der Browser beendet wird. Man spricht hier von einem Session-Cookie oder einem temporären Cookie; Cookies mit gesetztem Ablaufdatum nennt man permanente Cookies. Das Ablaufdatum sollte im GMT-Format angegeben werden; in JavaScript ist das ein Fall für die toGMTString()-Methode.
	path  Wie oben ausgeführt, kann ein Cookie von demjenigen Server ausgelesen werden, der in der domain-Eigenschaft angegeben ist. Wenn wichtige Daten in Cookies gespeichert werden, gibt es jedoch unter Umständen ein Problem. Wenn Sie bei Ihrem ISP eine Website hosten lassen, haben Sie oft eine URL der Bauart mitglied.isp.de/mitgliedsname. Die Seite des Konkurrenten, die auch bei diesem ISP gehostet wird, hat die URL mitglied.isp.de/nocheinmitglied. Die Domain ist jedoch in beiden Fällen mitglied.isp.de – und damit kann die Website Ihres Konkurrenten die Cookies lesen, die Ihre Seite bei dem Benutzer gesetzt hat (wenn der Benutzer zuerst Ihre Seiten und dann die der Konkurrenz besucht). Aus diesem Grund kann man noch einen Pfad setzen. Nur Webseiten, die in diesem Pfad auf dem entsprechenden Server liegen (Unterverzeichnisse eingeschlossen), können den Cookie lesen. In diesem Falll sollten Sie also den Pfad Ihrer Cookies auf /mitgliedsname setzen, um böse Überraschungen zu vermeiden. Ein weiteres Beispiel: Der Standardwert von path ist das Verzeichnis der Datei auf dem Webserver, die den Cookie setzt. Wenn Sie den Cookie aber auf jeder anderen Seite, auch in anderen Verzeichnissen, lesen wollen, sollten Sie den Wert von path auf / setzen.
	secure  Diese Eigenschaft muss nur angegeben werden, hier liegt kein Name-Wert-Paar vor. Ist die Eigenschaft gesetzt, so darf der Cookie nur gelesen werden, wenn man mit einer HTTPS-Verbindung, also mit einer »sicheren«, verschlüsselten Verbindung mit der Webseite verbunden ist.

Die Parameter bzw. Name-Wert-Paare werden durch Semikolon und Leerzeichen voneinander getrennt. Ein typischer Cookie sieht also folgendermaßen aus:

Autor=Christian+Wenz; domain=.galileo-press.de;
expires=Sat, 01-Mon-2000 12:00:00 GMT; path=/; secure

Der Name des Cookies ist gleichzeitig der Identifikator, es darf also nicht zwei Cookies mit demselben Namen geben. Wird ein Cookie gesetzt, den es (vom Namen her) schon gibt, wird der alte durch die neuen Daten überschrieben. Nur wenn der Pfad unterschiedlich ist, kann man denselben Namen öfter verwenden. Dieses Vorgehen ist jedoch nicht empfehlenswert – und auch mit JavaScript schwer zu fassen. Das Setzen ist einfach, aber das Lesen gestaltet sich schwierig.

11.3 Cookies mit JavaScript

Cookies werden mit JavaScript in der Eigenschaft cookie des document-Objekts gespeichert, und zwar als Zeichenkette. Das impliziert, dass man auf Cookies nicht wie auf Objekte mit Eigenschaften und Methoden zugreifen kann. Beim Setzen des Cookies ist das kein weiteres Problem, da denkt der JavaScript-Interpreter mit. Wenn der Wert von document.cookie beispielsweise

"Autor=Christian+Wenz"

ist, und der Befehl

document.cookie = "Verlag=Galileo"

ausgeführt wird, lautet der Wert von document.cookie danach folgendermaßen:

Autor=Christian+Wenz; Verlag=Galileo

Der JavaScript-Interpreter passt den Wert des Cookies also automatisch an. Das gilt auch, wenn der Wert eines Cookies geändert wird. Nach der Ausführung des Befehls

document.cookie="Verlag=Galileo-Press"

wird der Wert von document.cookie in

Autor=Christian+Wenz; Verlag=Galileo-Press

geändert.

11.3.1 Cookies setzen

Es bietet sich an, zum Setzen eines Cookies eine Funktion zu schreiben, an die die einzelnen Parameter des Cookies als Funktionsparameter übergeben werden. Im Folgenden ist so eine Funktion aufgeführt: Es wird überprüft, ob der jeweilige Parameter den Wert null hat (also nicht angegeben worden ist), und dementsprechend wird der Cookie angepasst.

function setCookie(name, wert, domain, expires, path, secure){
   var cook = "name="+unescape(wert)
   cook += (domain) ? "; domain="+ domain : ""
   cook += (expires) ? "; expires="+expires : ""
   cook += (path) ? "; path="+path : ""
   cook += (secure) ? "; secure"
   document.cookie = cook
}

Der Beispielaufruf

setCookie("Autor", "Christian Wenz", null, ((new Date()).
  getTime()+1000*3600*24).toGMTString())

setzt einen Cookie Autor=Christian+Wenz, der einen Tag lang gültig ist (1000 Millisekunden pro Sekunde, 3600 Sekunden pro Stunde, 24 Stunden pro Tag).

11.3.2 Cookies löschen

Das Löschen von Cookies ist auch sehr bequem. Man versetzt hierbei das Ablaufdatum in die Vergangenheit. Damit wird der Cookie danach sofort ungültig und gelöscht. Zwar könnte man das aktuelle Datum nehmen, und einen Tag oder gar nur eine Sekunde davon abziehen, aber in der Regel setzt man das Ablaufdatum auf die frühestmögliche Zeit unter JavaScript, den 1. Januar 1970, eine Sekunde nach Mitternacht (hat unter anderem den Grund, dass Netscape 2 Cookies, deren Ablaufdatum nur eine Millisekunde zurückgesetzt worden ist, nicht gelöscht hat). In GMT-Schreibweise sieht das so aus:

Thu, 01-Jan-70 00:00:01 GMT

Beim Schreiben einer Funktion sollte man die Parameter für die Domain und den Pfad ebenfalls mit angeben können, um gegebenenfalls den richtigen Cookie zu löschen:

function eraseCookie(name, domain, path){
   var cook="name=; expires=Thu, 01-Jan-70 00:00:01 GMT"
   cook += (domain) ? "domain="+domain : ""
   cook += (path) ? "path="+path : ""
   document.cookie = cook
}

11.3.3 Cookies lesen

Kommen wir zum schwierigsten Teil: den Wert eines Cookies wieder zu lesen. Wie bereits zuvor angedeutet, wird der Sonderfall zweier gleichnamiger Cookies mit unterschiedlicher Pfadangabe hier nicht berücksichtigt, weil der Aufwand unverhältnismäßig steigt. Statt dessen wird der zu schreibenden Funktion, die den Wert eines Cookies zurückgeben soll, nur der Name des Cookies übergeben, sonst nichts. Der erste Cookie, der dann gefunden wird, wird angezeigt.

Bei dieser Aufgabenstellung sieht man erst den Nachteil, dass man auf Cookies nicht als Objekte zugreifen kann. Der Wert des Cookies muss mit profanen Stringfunktionen herausgefunden werden. Das ist aber recht einfach: Zuerst wird nach der Zeichenkette "name=" gesucht, wobei name den Namen des Cookies angibt. Dahinter steht dann der Wert des Cookies. Sobald man auf ein Semikolon oder das Ende der Zeichenkette stößt, hat man den gesamten Wert, und kann ihn (aus der URL-Schreibweise wieder zurückcodiert) zurückgeben.

function getCookie(name){
   var i=0  //Suchposition im Cookie
   var suche = name+"="
   while (i<document.cookie.length){
      if (document.cookie.substring(i, i+suche.length)==suche){
         var ende = document.cookie.indexOf(";", i+suche.length)
         ende = (ende>-1) ? ende : document.cookie.length
         var cook = document.cookie.substring(i+suche.length, ende)
         return unescape(cook)
      }
      i++
   }
   return null
}

11.3.4 Cookie-Unterstützung überprüfen

Aufgrund der eingangs angedeuteten Paranoia bezüglich Cookies haben viele Benutzer die Verwendung von Cookies abgeschaltet, oder sie lassen ein Warnfenster ausgeben, sobald ein Cookie vom Server (oder hier vom Browser selbst) geschickt wird.

Abbildung 11.1  Die Cookie-Warnung des Netscape Navigator

Aus diesem Grund sollte man – zumindest am Anfang einer auf Cookies basierenden Applikation – prüfen, ob Cookies unterstützt werden. An vielen Stellen wurde vorgeschlagen, folgende Überprüfung vorzunehmen:

if (document.cookie){
   // Cookie-Code
}

Prinzipiell ist der Ansatz gar nicht schlecht, aber oft wurde einfach behauptet, so werde überprüft, ob das Cookie-Objekt unterstützt wird.

Das ist leider völlig falsch, denn document.cookie ist kein Objekt, sondern einfach eine (sehr funktionsfähige, man denke an die Zuweisungen) Zeichenkette. Aus diesem Grund ist hier die if-Abfrage nur eine Abkürzung für folgenden Code:

if (document.cookie.length>0){
   // Cookie-Code
}

Der Grund, warum die erstere Variante recht verbreitet ist, besteht darin, dass es vielleicht einmal Browser gibt, bei denen document.cookie gleich null ist – und dann führt ein Zugriff auf die Eigenschaft length zu einem Fehler.

Aber zurück zum Thema. Die obigen Abfragen überprüfen, ob document.cookie mindestens ein Zeichen enthält. Aus diesem Grund kann man mit obiger Methode also nicht testen, ob der Browser Cookies unterstützt, sondern nur, ob schon ein Cookie gesetzt worden ist. Sie müssen also einen Cookie setzen, um herauszufinden, ob der Browser ihn annimmt.2

Eine Funktion, die überprüft, ob der Benutzer Cookies überhaupt akzeptiert, ist Folgende:

function checkCookie(){
   setCookie("CookieTest", "OK")
   if (!getCookie("CookieTest"))
      return false
   else{
      eraseCookie("CookieTest")
      return true
   }
}

Hier sehen Sie einen Vorteil von JavaScript gegenüber serverseitigen Programmiersprachen: Bei der zuletzt dargestellten Vorgehensweise kann man nur übermittelte Cookies auslesen und dann neue Cookies setzen. Um aber nach dem Setzen zu überprüfen, ob das auch funktioniert hat, muss man eine neue Seite aufrufen bzw. ein neues Skript ausführen.

Diese Funktion sollten Sie jedoch nicht allzu oft ausführen. Viele Benutzer lassen sich einfach eine Warnmeldung anzeigen, um beispielsweise zu sehen, was in dem Cookie steht. Auf vielen Seiten benötigen Sie zwar beispielsweise den Cookie der Site selbst (beispielsweise Ihre Kundennummer), nicht aber den Cookie des Werbebanners auf derselben Site. Wenn Sie nun diese Funktion auf jeder Seite ausprobieren, ärgern sich die Benutzer über die vielen Warnmeldungen.

Abbildung 11.2  Der Internet Explorer 5 bietet detaillierte

Einstellungsmöglichkeiten für Cookies

	In diesem Zusammenhang ein kleiner Hinweis: Paranoia hin oder her, die Spionagegefahr bei temporären Cookies ist wirklich gering. Außerdem benötigt beispielsweise Hotmail unbedingt temporäre Cookies, um zu funktionieren (Yahoo! Mail erforderte zeitweise sogar permanente Cookies, inzwischen benötigt man nur noch temporäre Cookies). Der Internet Explorer 5 unterscheidet zwischen diesen beiden Arten von Cookies, und eine empfehlenswerte Einstellung ist, temporäre Cookies immer anzunehmen, bei permanenten Cookies jedoch nachzufragen.

11.3.5 Warenkorb mit Cookies

Um das Überprüfen auf und den Einsatz von Cookies einmal an einem praktischen Beispiel vorzuführen, soll das Beispiel mit dem Warenkorb auf Cookies umgestellt werden. Das Frameset wird komplett aufgelöst, es gibt nur noch eine Hauptseite. Auf jeder Artikelseite wird dann ein Link auf den Warenkorb angelegt. Die Formular-Übergabe an den Warenkorb sieht folgendermaßen aus:

<HTML>
<HEAD><TITLE>Beispielsartikel für den Warenkorb</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
/***
   Hier alle Cookie-Funktionen von oben einfügen
***/
function istZahl(n){
  s = ""+n
  var ziffern = "0123456789"
  for (var i=0; i<s.length; i++)
    if (ziffern.indexOf(s.charAt(i))<0) return false
  return true
}
function einfuegen(a, p, b){
   var anz = (istZahl(a) ? a : "0")
   var anzahl = getCookie("Anzahl") + anz + "|"
   var preis = getCookie("Preis") + p+ "|"
   var beschreibung = getCookie("Beschreibung") + b + "|"
   setCookie("Anzahl", anzahl)
   setCookie("Preis", preis)
   setCookie("Beschreibung", beschreibung)
   if (!document.cookie)
      alert("Aktivieren Sie Cookies in Ihrem Browser!")
   else
      alert("Artikel in Warenkorb eingefügt")
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>M. Proust I</H3>
Das 1. Werk des französischen Autors; 20,55 Euro
<FORM>
<INPUT TYPE="Anzahl" SIZE=2 VALUE="1"> Stück
<INPUT TYPE="BUTTON" VALUE="In den Warenkorb" onClick=" einfuegen
  (this.form.Anzahl.value, '20.55', 'Proust I.')">
</FORM>
</BODY>
</HTML>

Die Seite, die den Warenkorb ausgibt, ändert sich folgendermaßen:

<HTML>
<HEAD><TITLE>Ausgabe des Warenkorbs</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
/***
   Hier alle Cookie-Funktionen von oben einfügen
***/
var a = getCookie("Anzahl") + ""
var p = getCookie("Preis") + ""
var b = getCookie("Beschreibung") + ""
function naechste_anzahl(){
   if (a.indexOf("|")==-1) return ""
   var anz = a.substring(0, a.indexOf("|"))
   a = a.substring(a.indexOf("|")+1)
   return anz
}
function naechster_preis(){
   if (p.indexOf("|")==-1) return ""
   var pr = p.substring(0, p.indexOf("|"))
   p = p.substring(p.indexOf("|")+1)
   return pr
}
function naechste_beschreibung(){
   if (b.indexOf("|")==-1) return ""
   var bes = b.substring(0, b.indexOf("|"))
   b = b.substring(b.indexOf("|")+1)
   return bes
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Inhalt des Warenkorbs</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
function tag(s){ document.write("<"+s+">") }
tag("TABLE BORDER=1");
tag("TR");
tag("TD"); document.write("Anzahl"); tag("/TD")
tag("TD"); document.write("Beschreibung"); tag("/TD")
tag("TD"); document.write("Einzelpreis"); tag("/TD")
tag("TD"); document.write("Gesamtpreis"); tag("/TD")
tag("/TR")
anzahl="0"
while (anzahl!=""){
  var anzahl = naechste_anzahl()
  var preis = naechster_preis()
  var beschreibung = naechste_beschreibung()
  if (anzahl!=""){
    tag("TR")
    tag("TD"); document.write(anzahl); tag("/TD")
    tag("TD"); document.write(beschreibung); tag("/TD")
    tag("TD"); document.write(preis); tag("/TD")
    tag("TD"); document.write(anzahl*preis); tag("/TD")
    tag("/TR")
  }
}
tag("/TABLE")
//--></SCRIPT>
</BODY>
</HTML>

Sie sehen zum einen, dass sich die Änderungen im überschaubaren Rahmen halten. Sie sehen jedoch auch zum anderen, dass recht viel JavaScript-Code verwendet wird, insbesondere auf allen Artikelseiten. Dies lässt sich jedoch durch die Verwendung von Server Side Includes (SSI) vermeiden, oder – wenn es die Browser-Ausstattung Ihres Publikums erlaubt, aber wirklich nur dann – durch <SCRIPT SRC="...">.

Wenn man keine serverseitige Programmiersprachen-Unterstützung zur Verfügung hat, kann man über Cookies den Inhalt des Warenkorbs speichern. Die meisten Online-Shops, inklusive Amazon, speichern zumindest die User-ID des Benutzers in einem Cookie. Bei Amazon ist das optional3 , bei My-World beispielsweise geht es nicht ohne.

Andere Shops jedoch, beispielsweise Primus-Online, kommen vollständig ohne Cookies aus. Wie das möglich ist, und wie das Warenkorbbeispiel entsprechend umgeschrieben werden kann, zeigt der nächste Abschnitt.

11.4 Informationen behalten ohne Cookies

Wenn man sowohl auf Frames als auch auf die Verwendung von Cookies als auch auf andere, eher exotische Methoden der Datenhaltung4  verzichten will, hat man noch eine Möglichkeit, um Informationen zwischen HTML-Seiten zu übergeben. Der Query-String einer URL, also die Zeichenkette hinter dem Fragezeichen, ist bei statischen Seiten völlig unerheblich, man kann also (fast) alles angeben, was man will. Unser Ziel soll es sein, in dieser Zeichenkette alle notwendigen Informationen zu übergeben. Diese Vorgehensweise hat jedoch – zum Teil besonders im vorliegenden Beispiel – drei Nachteile:

	Jeder einzelne Link muss angepasst werden. Sollte der Benutzer auf einen Link klicken, der unvollständig ist (also ohne Query-String), sind alle Informationen verloren; auch beim Betätigen der Zurück-Schaltfläche im Browser ist das der Fall (war es bei der Frames-Lösung für den Warenkorb jedoch auch).
	Die Kommandozeile ist – je nach Browser, Betriebssystem und Version – auf etwa 1 000 Zeichen begrenzt.
	Der Query-String steht in location.search, und diese Eigenschaft wird im Internet Explorer erst ab Version 4 bei lokalem Zugriff unterstützt, beim IE3 nur dann, wenn die Website auf einem Webserver und nicht auf der heimischen Festplatte liegt. Beachten Sie das beim Testen!

Bei einigen Anwendungen ist das nicht weiter tragisch. Stellen Sie sich vor, ein Benutzer muss ein längeres (Bestell-)Formular ausfüllen, und bekommt nach dem Abschicken des Formulars einen grafisch leicht aufbereiteten Bestellschein, der nur noch gedruckt und gefaxt oder eingeschickt werden muss. Hier sind Cookies oder Frames, sofern sie nicht eh schon im Site-Design vorhanden sind, zu viel des Guten; die Kommandozeile tut es auch.

Eine Artikelseite unseres kleinen Kaufhauses sieht – bei Verwendung der URL als Übergabe für die Artikel – folgendermaßen aus:

<HTML>
<HEAD><TITLE>Beispielartikel für den Warenkorb</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!-
function goto(url){
   //generiert geeigneten Link
}
function getValue(name){
  //gibt den Wert der Variablen "name" in der URL zurück
}
function istZahl(n){
  s = ""+n
  var ziffern = "0123456789"
  for (var i=0; i<s.length; i++)
    if (ziffern.indexOf(s.charAt(i))<0) return false
  return true
}
function einfuegen(a, p, b){
   var anz = (istZahl(a) ? a : "0")
   var anzahl = getValue("Anzahl") + anz + "|"
   var preis = getValue("Preis") + p+ "|"
   var beschreibung = getValue("Beschreibung") + b + "|"
   var seite = "bestaetigung.html?"
   seite += "anzahl="+encode(anzahl)
   seite += "&preis="+encode(preis)
   seite += "&beschreibung="+encode(beschreibung)
   location.href = seite
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>M. Proust I</H3>
Das 1. Werk des französischen Autors; 20,55 Euro
<FORM>
<INPUT TYPE="Anzahl" SIZE=2 VALUE="1"> Stück
<INPUT TYPE="BUTTON" VALUE="In den Warenkorb" onClick=" einfuegen
  (this.form.Anzahl.value, '20.55', 'Proust I.')">
</FORM>
</BODY>
</HTML>

Die Datei bestaetigung.html gibt eine Bestätigung aus und bietet einige Links zu weiteren Artikeln an.

<HTML>
<HEAD><TITLE>Warenkorb</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function goto(url){
   //generiert geeigneten Link
}
//-->
</HEAD>
<BODY>
<H3>Artikel ist im Warenkorb eingetragen!</H3>
<A HREF="javascript:goto('artikel1.html')">Noch ein Artikel</A><BR>
<A HREF="javascript:goto('artikel2.html')">Ein weiterer Artikel</A>
</BODY>
</HTML>

Die Ausgabeseite liest schließlich aus der URL die einzelnen Werte aus und verfährt ansonsten wie gehabt:

<HTML>
<HEAD><TITLE>Ausgabe des Warenkorbs</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function getValue(name){
   //gibt den Wert der Variablen "name" in der URL zurück
}
var a = getValue("Anzahl")
var p = getValue("Preis")
var b = getValue("Beschreibung")
function naechste_anzahl(){
   if (a.indexOf("|")==-1) return ""
   var anz = a.substring(0, a.indexOf("|"))
   a = a.substring(a.indexOf("|")+1)
   return anz
}
function naechster_preis(){
   if (p.indexOf("|")==-1) return ""
   var pr = p.substring(0, p.indexOf("|"))
   p = p.substring(p.indexOf("|")+1)
   return pr
}
function naechste_beschreibung(){
   if (b.indexOf("|")==-1) return ""
   var bes = b.substring(0, b.indexOf("|"))
   b = b.substring(b.indexOf("|")+1)
   return bes
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Inhalt des Warenkorbs</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
function tag(s){ document.write("<"+s+">") }
tag("TABLE BORDER=1");
tag("TR");
tag("TD"); document.write("Anzahl"); tag("/TD")
tag("TD"); document.write("Beschreibung"); tag("/TD")
tag("TD"); document.write("Einzelpreis"); tag("/TD")
tag("TD"); document.write("Gesamtpreis"); tag("/TD")
tag("/TR")
anzahl="0"
while (anzahl!=""){
  var anzahl = naechste_anzahl()
  var preis = naechster_preis()
  var beschreibung = naechste_beschreibung()
  if (anzahl!=""){
    tag("TR")
    tag("TD"); document.write(anzahl); tag("/TD")
    tag("TD"); document.write(beschreibung); tag("/TD")
    tag("TD"); document.write(preis); tag("/TD")
    tag("TD"); document.write(anzahl*preis); tag("/TD")
    tag("/TR")
  }
}
tag("/TABLE")
//--></SCRIPT>
</BODY>
</HTML>

Damit das Beispiel funktioniert, fehlen noch zwei Funktionen, die gemeinerweise in den obigen Listings immer nur leer angegeben wurden:

	goto(url): Die Seite, deren Adresse im Parameter url steht, wird aufgerufen. Alle Links innerhalb der Warenkorbapplikation müssen über diese Funktion laufen!
	getValue(name): Der Wert der Variablen name in der URL wird ausgelesen und zurückgegeben.

Von der Implementierung her ist goto() die einfachere Funktion. Es muss die neue Seite aufgerufen, dabei aber unbedingt die Kommandozeile beibehalten werden. Das erreicht man im Allgemeinen durch das Anhängen von location.search an die URL. Sollte die URL der neuen Seite jedoch schon ein Fragezeichen enthalten, so wird das erste Zeichen von location.search, das Fragezeichen, abgetrennt und der Rest mit einem kaufmännischen Und (&) an die URL angehängt. Dieser Fall tritt in unserem Beispiel nicht auf, aber es kann ja sein, dass Sie in der Kommandozeile weitere Informationen weitergeben – und diese auf analoge Art und Weise verwerten – wollen.

function goto(url){
   if (url.indexOf("?")<0)
      location.href = url + location.search
   else {
      var parameter = location.search.substring(1,
        location.search.length)
      location.href = url + "&" + parameter
   }
}

Die Programmierung der Funktion getValue() sieht auf den ersten Blick etwas schwieriger aus, aber von der Vorgehensweise ist sie mit der Funktion getCookie() vergleichbar. In diesem Fall ist das Trennzeichen nicht das Semikolon, sondern das kaufmännische Und. Das war dann aber auch der einzige Unterschied; ansonsten muss praktisch nur noch document.cookie durch location.search ersetzt werden.

function getValue(name){
   var i=1  //Suchposition in der URL
   var suche = name+"="
   while (i<location.search.length){
      if (location.search.substring(i, i+suche.length)==suche){
         var ende = location.search.indexOf("&", i+suche.length)
         ende = (ende>-1) ? ende : location.search.length
         var loca = location.search.substring(i+suche.length, ende)
         return unescape(loca)
      }
      i++
   }
   return ""
}

11.5 Fragen & Aufgaben

1.	Wie werden Cookies prinzipiell eingeteilt?
2.	Erzeugen Sie – sofern möglich – eine Seite, die angibt, wie oft der Benutzer mit dem jeweiligen Browser schon auf der Seite war.
3.	Erzeugen Sie – sofern möglich – eine Seite, die angibt, wie oft der Benutzer mit irgendeinem Browser schon auf der Seite war.
4.	Ein Benutzer kann die Unterstützung von Cookies entweder ausschalten, eine Warnmeldung einblenden lassen oder Cookies prinzipiell annehmen. Wie könnte man mit JavaScript feststellen, welche dieser drei Möglichkeiten der Benutzer gewählt hat? Setzen Sie Ihre Idee in Code um.
5.	Schreiben Sie das erste Beispielformular aus »Formulare I« folgendermaßen um: Das Formular wird ohne Vollständigkeitsüberprüfung via GET abgeschickt. Auf der nächsten Seite erhält der Benutzer, wenn das Formular nicht vollständig ausgefüllt worden ist, einen Link zurück auf das Formular, wobei der Query-String beibehalten wird. Das Formular aus der vorherigen Aufgabe soll, wenn der Benutzer auf den besonderen Link klickt, vorausgefüllt sein, und zwar mit den Angaben, die der Benutzers bei seinem ersten Versuch eingegeben hat. Außerdem sollen die Namen der fehlenden Felder ausgegeben werden.

1    Im englischen geläufiger Begriff: name-value-pair

2    Das nennt man auch Trial and Error.

3    Das muss auch so sein, da der Kundenkreis so groß ist, dass man sich Arroganz bei den Software-Voraussetzungen nicht erlauben kann.

4    Etwa als Variablen in einem anderen oder neuen Fenster; das fällt technisch unter die Kategorie der URLs.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 12 Formulare II
			12.1 Daten behalten
			12.2 Dynamische Auswahllisten
			12.3 Überprüfungsfunktionen
			12.4 Reguläre Ausdrücke
			12.5 Fragen & Aufgaben

Kapitel 12 Formulare II

Der Bürokrat tut seine Pflicht

von neun bis eins,

Mehr tut er nicht

– Carl Zeller

Im Kapitel »Formulare I« haben Sie gelernt, wie man mit JavaScript allgemein auf Formulardaten zugreifen kann. In diesem Kapitel werden einige fortgeschrittenere Techniken dargestellt, wie man Formulare sinnvoll nutzen kann. Neben neuen Möglichkeiten der Formularüberprüfung mit Browsern der Version 4 erfahren Sie hier auch einige Tricks und Kniffe, die in der täglichen Praxis von Nutzen sein können. Spätestens hier sind die Möglichkeiten von JavaScript 1.0 oft begrenzt, was Sie immer im Hinterkopf behalten sollten.

12.1 Daten behalten

Im vorangegangenen Kapitel haben Sie gesehen, wie man Daten in Cookies speichern kann und somit beispielsweise einen JavaScript-Warenkorb ohne Frames realisieren kann. Der Nachteil wurde auch nicht verschwiegen: Während die meisten Benutzer JavaScript nicht deaktivieren, schalten viele User die Verwendung von Cookies aus, natürlich auch bedingt durch Horrormeldungen in der Presse. Es gibt jedoch auch Möglichkeiten, ohne Cookies Daten von einer HTML-Seite zur nächsten zu übernehmen. Eine der Alternativen besteht in der Verwendung von Frames und der Datenspeicherung in einem davon; hier sei auf Kapitel »Fenster II« verwiesen. In diesem Abschnitt wird eine weitere Möglichkeit vorgestellt.

Ein virtueller Geschäftsmann will den Besuchern seiner Website Bücher in elektronischer Form zum Download anbieten. Er hat eine ganze Reihe davon, und so soll der Benutzer in einem Formular die für ihn interessanten Programme auswählen können. Nach Absenden des Formulars erhält er Links auf die ausgewählten Programme. Bevor Sie das Beispiel eins zu eins kopieren, sollten Sie allerdings die Copyright-Fragen klären.

12.1.1 Das Eingabeformular

Das Formular selbst ist schnell erstellt; als zusätzlicher Bonus werden dem Benutzer zu jedem Programm Hintergrundinformationen zu jedem Produkt in einem neuen Fenster angezeigt. Wie das prinzipiell funktioniert, wurde schon im Kapitel »Fenster III« gezeigt. Beachten Sie im folgenden, dass jeder Checkbox konsistent das VALUE-Attribut "on" zugewiesen worden ist. Der Sinn dieser Maßnahme wird weiter unten klar.

Abbildung 12.1  Das HTML-Formular

<HTML>
<HEAD>
<TITLE>Bücher-Download</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function hilfe(seite){
   window.open(seite, "hilfefenster","height=300,width=400")
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Wählen Sie hier Ihre Bücher aus!</H3>
<FORM METHOD="GET" ACTION="download.html">
<INPUT TYPE="CHECKBOX" NAME="sommer" VALUE="on">
 <A HREF="javascript:hilfe('sommer.html')">Sommernachtstraum</A><BR>
<INPUT TYPE="CHECKBOX" NAME="othello" VALUE="on">
 <A HREF="javascript:hilfe('othello.html')">Othello<</A>BR>
<INPUT TYPE="CHECKBOX" NAME="venedig" VALUE="on">
 <A HREF="javascript:hilfe('venedig.html')">Der Kaufmann von
   Venedig</A><BR>
...<BR>
<INPUT TYPE="SUBMIT" VALUE="Zum Download">
</FORM>
</BODY>
</HTML>

12.1.2 Die Ausgabeseite

Wenn Sie das Formular auf der vorherigen Seite genauer betrachtet haben, wird Ihnen folgende Zeile nicht entgangen sein:

<FORM METHOD="GET" ACTION="download.html">

Zum einen ist das ACTION-Attribut unüblich – seit wann übergibt man Formularwerte an eine HTML-Seite? Zum anderen ist METHOD auf "GET" gesetzt. Dazu ein kleiner Exkurs: Mit METHOD wird die Versendemethode des Formulars angegeben. Standardmäßig, also auch, wenn nichts angegeben wird, wird die Methode POST verwendet. In diesem Fall werden die Formulareingaben als eigener Teil des HTTP-Headers bei der Anforderung der Zielseite versandt. Die entsprechende HTTP-Anforderung des Webbrowsers an den Webserver sieht ungefähr folgendermaßen aus:

POST /download.html HTTP/1.1
Content-type: application/x-www-form-urlencoded
Accept: text/plain
Content-length: 21
othello=on&venedig=on

Sie sehen, dass die einzelnen (angekreuzten) Checkboxen im Formular NAME=VALUE übergeben und voneinander mit dem kaufmännischen Und (&) getrennt werden.

Wenn wie im obigen Beispiel die Methode GET verwendet wird, sieht die Sache anders aus: Hier werden nämlich die Formulardaten als Teil der URL übergeben, es würde folgende Seite aufgerufen werden:

download.html?othello=on&venedig=on

Diese Daten kann man mit JavaScript abfragen. Wie Sie sich vielleicht erinnern, erhält man mit location.search den Teil der URL ab dem Fragezeichen, in diesem Fall also ?othello=on&venedig=on. Mit JavaScript können diese Daten zerlegt werden, um die Ausgabeseite zu generieren.

Um die ganze Sache ein wenig zu vereinfachen, gehen wir davon aus, dass alle Bücher im Verzeichnis download liegen, die Dateiendung .zip haben und sich der Teil vor der Endung aus dem NAME-Attribut der zugehörigen Checkbox ergibt. Der Programmierer muss also nur noch folgende Aufgaben erledigen:

	Er muss die Eigenschaft location.search auslesen und das erste Zeichen (das Fragezeichen) abschneiden.
	Er muss die übrigbleibende Zeichenkette an den kaufmännischen Unds aufteilen. Die einzelnen Teile haben dann den Aufbau buchname=on, und wenn man das =on entfernt, hat man den Dateinamen ohne die Endung.

Man kann den Algorithmus ein wenig vereinfachen, indem man einfach nach dem nächsten Vorkommen von & sucht, außerdem nach dem nächsten Vorkommen von =on und dann die Zeichenkette dazwischen betrachtet. Die Zeichenkette =on kann übrigens an keiner anderen Stelle (also zum Beispiel links vom Gleichheitszeichen) in der URL erscheinen. Der Grund dafür ist, dass Sonderzeichen in ein URL-konformes, hexadezimales Format umgewandelt werden. Aus einem Leerzeichen wird %20, und aus einem Gleichheitszeichen wird %3D. 3D ist nämlich die hexadezimale Darstellung der Dezimalzahl 62, und im ASCII-Zeichensatz hat das Gleichheitszeichen den Code 62. Der ASCII-Code des Leerzeichens ist 32, und die hexadezimale Darstellung ist 20. Die Umwandlung in dieses URL-Format geschieht automatisch; die Rückverwandlung erfolgt mit der JavaScript-Funktion unescape(). So liefert beispielsweise unescape("%3D") das Ergebnis "=" zurück. Die Umwandlung ist im übrigen auch mit JavaScript möglich, escape("=") liefert "%3D".

Der Internet Explorer 5.5 bietet hierzu übrigens ein paar neue Funktionen an, die eine URI (Unified Ressource Identificator, eine Art Obermenge von URL) erzeugen können. Die Funktion encodeURI() wandelt den übergebenen Parameter in eine URL um, also liefert beispielsweise encodeURI (»meine Webseite.html#oben«) als Ergebnis meine%20Webseite.html#oben zurück. Sie sehen hier, dass das Doppelkreuz als Abtrennungszeichen für einen HTML-Anker interpretiert worden ist, also insbesondere nicht in die hexadezimale Form %23 umgewandelt wurde. Wenn Sie auch das möchten (beispielsweise, wenn Sie die obige URL als Parameter an ein CGI-Skript übergeben möchten), müssen Sie encodeURIComponent() verwenden. Dies liefert das gewünschte Ergebnis, encodeURIComponent(»meine Webseite.html#oben«) gibt meine%20Webseite.html%23oben zurück.

Die entsprechenden Funktionen, die eine kodierte URL wieder entschlüsseln, heißen decodeURI() und decodeURIComponent(). Und wie erwartet gibt decodeURI(»meine%20Webseite.html#oben«) als Ergebnis meineWebseite.html#oben zurück, decodeURIComponent(»meine%20 Webseite.html %23oben«) liefert ebenfalls meine Webseite.html#oben.

Aus den vielzitierten Gründen der Abwärtskompatibilität müssen Sie jedoch noch eine ganze Weile auf den Einsatz dieser Funktionen verzichten, wenn Sie möglichst viele Browser unterstützen wollen.

Zurück zur Aufgabenstellung: Der folgende Code (zu speichern als download.html) liest die übergebenen Daten aus und generiert die Ausgabeseite.

<HTML>
<HEAD>
<TITLE>Download Seite 2</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function tag(s){ return("<"+s+">") }
function ausgabe(){
   var ls = location.search
   var txt = (ls.length>1) ? "Sie können die Bücher nun
     herunterladen" : "Keine Bücher ausgewählt"
   document.write(txt + tag("BR"))
   if (ls.length<=1)  //Funktion verlassen, falls
                      //nichts ausgewählt wurde
      return false
   ls = "&" + ls.substring(1, ls.length)
      //Fragezeichen entfernen, "&" vorne anhängen
   var pos = 0 //aktuelle Suchposition in location.search
   while (pos==0||ls.indexOf("&", pos) != -1){
      start = ls.indexOf("&", pos)+1
      ende = ls.indexOf("=on", pos)
      buch = unescape(ls.substring(start, ende))
      document.write(tag("A HREF='download/"+buch+".zip'"))
      document.write(buch)
      document.write(tag("/A")+tag("BR"))
      pos = ende + 2
   }
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Bücher-Download</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
ausgabe()
//--></SCRIPT>
<NOSCRIPT>
Ihr Browser unterstützt kein JavaScript!
</NOSCRIPT>
</BODY>
</HTML>

Abbildung 12.2  Die Download-Seite

12.2 Dynamische Auswahllisten

Erinnern Sie sich noch an die Navigation aus dem Kapitel »Images«? Dort gab es mehrere Kategorien, die aufgrund einer Mausbewegung ausklappen und Unterpunkte freigeben. Dies lässt sich sehr platzsparend auch in einem Formular realisieren. Es ist insbesondere möglich, via JavaScript einzelne Punkte in den Auswahllisten zu ändern, zu löschen und neue Punkte hinzuzufügen. Allerdings muss der Browser die JavaScript-Version 1.1 unterstützen. Sie müssen also den Netscape Navigator ab Version 3 bzw. den Internet Explorer ab Version 4 benutzen.

12.2.1 Ein erster Ansatz

Wie Sie wissen, werden die einzelnen Optionen einer Auswahlliste im Array options[] gespeichert. Jede einzelne dieser Optionen hat die Eigenschaft text, die den im Browser angezeigten Text angibt. Wie gesagt, diese Eigenschaft kann erst ab JavaScript 1.1 modifiziert werden.

Das ist an sich kein Problem, aber nicht alle Kategorien haben die gleiche Anzahl von Unterpunkten. Da jedoch die einzelnen Optionen in einem Array gespeichert werden, liegt es nahe, die Eigenschaft length dieses Arrays zu ändern. Ein erster Ansatz für die Navigation finden Sie im nachfolgenden Listing. Die linke Auswahlliste enthält die Kategorien, und wenn eine davon ausgewählt wird (Event-Handler: onChange), werden die Untermenüpunkte in der rechten Auswahlliste angezeigt. Sobald dort ein Punkt ausgewählt wird, kann die entsprechende Webseite geladen werden. Wie im Beispiel aus dem Kapitel »Images«, stehen die wichtigen Variablen – in diesem Falle die URLs und die Namen der einzelnen Menüpunkte – am Anfang des Skripts in globalen Variablen, damit sie einfach angepasst werden können.

<HTML>
<HEAD>
<TITLE>Navigation mit Auswahllisten – Teil 1</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function kategorie_anzeigen(){}
function seite_laden(){}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
// *** globale Variablen
var urls = new Array(
   new Array(""),
   new Array("", "seite1-1.html", "seite1-2.html", "seite1-3.html"),
   new Array("", "seite2-1.html", "seite2-2.html"),
   new Array("", "seite3-1.html", "seite3-2.html", "seite3-3.html",
 "seite3-4.html")
)
var beschriftung = new Array(
   new Array("Bitte auswählen", ""),
   new Array("Bitte auswählen", "Punkt 1.1", "Punkt 1.2",
     "Punkt 1.3"),
   new Array("Bitte auswählen", "Punkt 2.1", "Punkt 2.2"),
   new Array("Bitte auswählen", "Punkt 3.1", "Punkt 3.2",
     "Punkt 3.3", "Punkt 3.4")
)
// *** Ende der globalen Variablen
function kategorie_anzeigen(f){
   var kategorie = f.kategorien.selectedIndex
   f.unterpunkte.options.length=urls[kategorie].length
   for (var i=0; i<urls[kategorie].length; i++)
      f.unterpunkte.options[i].text = (beschriftung[kategorie])[i]
}
function seite_laden(f){
   var kategorie = f.kategorien.selectedIndex
   var unterpunkt = f.unterpunkte.selectedIndex
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Navigation mit Auswahllisten</H3>
<FORM>
<SELECT NAME="kategorien" onChange="kategorie_anzeigen(this.form)">
 <OPTION>Bitte auswählen</OPTION>
 <OPTION>Kategorie 1</OPTION>
 <OPTION>Kategorie 2</OPTION>
 <OPTION>Kategorie 3</OPTION>
</SELECT>
<SELECT NAME="unterpunkte" onChange="seite_laden(this.form)">
 <OPTION>Bitte auswählen</OPTION>
</SELECT>
</FORM>
</BODY>
</HTML>

Abbildung 12.3  Die beiden Auswahllisten

Wenn Sie dieses Beispiel im Browser ausprobieren, werden Sie allerdings wahrscheinlich einen kleinen Nachteil feststellen: Wenn Sie das zweite Auswahlmenü ausklappen wollen, werden Sie – bei manchen Browsern und Betriebssystemen – interessante grafische Nebeneffekte feststellen (siehe Abbildung 12.4). Um diese zu vermeiden, muss das obige Skript etwas sauberer programmiert werden.

Abbildung 12.4  Das Scrollen der rechten Auswahlliste ist schwierig.

12.2.2 Ein fortgeschrittener Ansatz

Um das Beispiel ganz sauber zu programmieren, sollte man zuerst alle Optionen in der Auswahlliste löschen und dann die Optionen hinzufügen. Für Menüoptionen gibt es einen eigenen Konstruktor, new Option("Beschriftung", "VALUE-Attribut").

Eine einzelne Option kann gelöscht werden, indem das entsprechende Element im Array options[] auf null gesetzt wird. Mit folgendem Kommando wird die zweite Option in einer Auswahlliste gelöscht:

document.forms[0].auswahlliste.options[1] = null

Sie können sich den Aufwand jedoch sparen, wenn Sie die Eigenschaft length des Arrays options[] auf 0 setzen. Dann können die Optionen erzeugt werden. Die Eigenschaft length wird hierbei automatisch angepasst. Es genügt, wenn Sie die Funktion kategorie_anzeigen() folgendermaßen abändern:

function kategorie_anzeigen(f){
   var kategorie = f.kategorien.selectedIndex
   f.unterpunkte.options.length=0
   for (var i=0; i<urls[kategorie].length; i++)
      f.unterpunkte.options[i] =
        new Option((beschriftung[kategorie])[i], "")
}

Abbildung 12.5  Jetzt fällt das Scrollen leichter.

Außerdem hilft es, pro forma in die linke Auswahlliste ein paar freie leere Felder einzufügen; vor allem der Netscape Navigator führt das Skript dann zuverlässiger aus.

Wie Sie sehen, umgehen Sie so grafische Unfälle.

12.3 Überprüfungsfunktionen

Im Kapitel »Formulare I« wurden Formulare auf Vollständigkeit überprüft. In der Praxis gibt es jedoch noch weitere Anforderungen. Manche Eingabefelder verlangen besondere Eingaben, beispielsweise Postleitzahlen, Telefonnummern oder Uhrzeiten. In diesem Abschnitt werden einige Funktionen aus diesem Bereich entwickelt.

12.3.1 Ganze Zahlenwerte

In JavaScript gibt es die Funktion isNaN(), die feststellt, ob ein Eingabewert keine Zahl ist. Der große Nachteil an dieser Funktion ist, dass der Netscape Navigator 2 sie nur in der UNIX-Version unterstützt. Aus diesem Grund muss man sich diese Funktion selbst programmieren. Der Eingabewert wird dazu als Zeichenkette betrachtet, und bei jedem Zeichen wird überprüft, ob es eine Ziffer von 0 bis 9 ist. Sollte das für alle Zeichen zutreffen, handelt es sich um eine Zahl, ansonsten liegt keine Zahl vor.

function isANumber(n){
   var s = "" + n //Umwandlung in eine Zeichenkette
   var ziffern = "0123456789" //Gültige Zeichen
   for (var i=0; i<s.length; i++)
      if (ziffern.indexOf(s.charAt(i))==-1) //keine Ziffer
         return false
   return true
}

Mit dieser Methode kann man beispielsweise überprüfen, ob ein Eingabewert eine deutsche Postleitzahl darstellen könnte:

if (eingabe.length==5 && isANumber(eingabe))

Strenggenommen sind aber nicht alle Postleitzahlen natürliche Zahlen, so beispielsweise 01234. Das ist die Postleitzahl einiger Postfächer in Dresden, aber keine natürliche Zahl, da sie mit 0 beginnt, was nicht sein darf (Ausnahme: die Null selbst). Für streng nummerische Eingaben (beispielsweise ein Anzahl-Feld in einem Bestellformular) muss man die Funktion folgendermaßen umschreiben:

function isANumber2(n){
   var s = "" + n //Umwandlung in eine Zeichenkette
   var ziffern = "0123456789" //Gültige Zeichen
   if (s=="0") //Bei "0"
      return true
   if (s.charAt(0)=="0") //Bei 0 am Anfang
      return false
   for (var i=0; i<s.length; i++)
      if (ziffern.indexOf(s.charAt(i))==-1) //keine Ziffer
         return false
   return true
}

Im dritten Schritt soll noch die zusätzliche Funktionalität implementiert werden, dass auch negative Zahlen erkannt werden, beispielsweise »-42«. Die Überprüfung gestaltet sich jedoch sehr einfach. Ist das erste Zeichen ein Minus, wird es einfach abgetrennt. Hinter dem Minuszeichen dürfen nur noch Ziffern stehen, also bleibt alles wie gehabt.

function isANumber3(n){
   var s = "" + n //Umwandlung in eine Zeichenkette
   var ziffern = "0123456789" //Gültige Zeichen
   if (s.charAt(0)=="-")  //führendes Minus entfernen
      s = s.substring(1, s.length)
   if (s=="0") //Bei "0"
      return true
   if (s.charAt(0)=="0") //Bei 0 am Anfang
      return false
   for (var i=0; i<s.length; i++)
      if (ziffern.indexOf(s.charAt(i))==-1) //keine Ziffer
         return false
   return true
}

12.3.2 Dezimalzahlen

Das Überprüfen von Dezimalzahlen ist schon eine etwas anspruchsvollere Aufgabe. Zum einen gibt es den Unterschied zwischen der deutschen und der amerikanischen Schreibweise: Während man in Deutschland den Ganzzahlanteil vom Dezimalteil durch ein Komma trennt, verwendet man in Amerika einen Punkt. JavaScript benötigt für Rechnungen die amerikanische Notation, sodass als aller erstes in einer Überprüfungsfunktion alle Kommata durch Punkte ersetzt werden. Zum anderen darf in der vermeintlichen Dezimalzahl maximal ein Punkt (bzw. Komma) vorkommen.

function isAFract(n){
   var s = "" + n //Umwandlung in String
   while (s.indexOf(",")>-1){//Kommata durch Punkte ersetzen
      s=s.substring(0,s.indexOf(",")) + "."
+ s.substring(s.indexOf(",")+1 ,s.length)
   }
   var anzahl_punkt=0//Variable zum Zählen der Dezimalpunkte
   for (var i=0; i<s.length; i++)
      if (s.charAt(i)==".")
         anzahl_punkt++
   if (anzahl_punkt>1) //Mehr als ein Dezimalpunkt?
      return false
   // *** Eigentliche Überprüfung nach obigem Muster
   // *** Neu: Der Dezimalpunkt ist ein erlaubtes Zeichen
   var ziffern = ".0123456789" //Gültige Zeichen
   if (s.charAt(0)=="-")  //Führendes Minus entfernen
      s = s.substring(1, s.length)
   if (s=="0") //Bei "0"
      return true
   if (s.charAt(0)=="0" &&s.charAt(1)!=".")
      //Bei 0 am Anfang ohne folgenden Punkt
      return false
   for (var i=0; i<s.length; i++)
      if (ziffern.indexOf(s.charAt(i))==-1) //Keine Ziffer
         return false
   return true
}

12.3.3 Telefonnummern

Es gibt viele Möglichkeiten, eine Telefonnummer zu schreiben. Eine Telefonnummer mit der Vorwahl 0123 und der Rufnummer 456789 kann beispielsweise folgendermaßen geschrieben werden:

	(0123) 456789
	(01 23) 45 67-89
	01234/456789
	+49[0]123-456789

Zwar können Sie für jeden dieser Fälle eine eigene Überprüfungsfunktion schreiben, aber in diesem Falle ist es effizienter, einfach eine Liste der wahrscheinlich vorkommenden Zeichen zu erstellen und darauf zu überprüfen. Eine mögliche Validierungsfunktion kann dann so aussehen:

function isAPhoneNumber(n){
   var s = "" + n //Umwandlung in eine Zeichenkette
   var zeichen = "0123456789+-()[]/ " //Gültige Zeichen
   for (var i=0; i<s.length; i++)
      if (zeichen.indexOf(s.charAt(i))==-1)
         //kein gültiges Zeichen
         return false
   return true
}

12.3.4 In Zahlenwerte umwandeln

Wenn man mit Formularen rechnet, ist es oft nicht nur wichtig, Formulareingaben auf nummerische Werte zu überprüfen, sondern auch, diese nummerischen Werte zu erhalten. Zwar gibt es die Funktionen parseFloat("Zeichenkette") für Dezimalzahlen und parseInt("Zeichenkette") für ganze Zahlen, aber diese liefern gegebenenfalls ein NaN-Objekt zurück: Not A Number. Zur Überprüfung des Rückgabewerts von parseFloat() und parseInt() würde man die Funktion isNaN() benötigen, und diese hat ja die eingangs erläuterten Nachteile. Außerdem funktioniert parseFloat() nur mit amerikanisch formatierten Eingabewerten, also mit einem Dezimalpunkt statt einem Dezimalkomma. Im Folgenden soll eine neue Funktion programmiert werden, die der Funktion eval() ähnelt, und einen Eingabewert überprüft und einen nummerischen Wert zurückgibt. Ist der Eingabewert kein korrekt formatierter Zahlenwert, so wird 0 zurückgegeben. Das hat den Vorteil, dass mit Formularen sehr bequem gerechnet werden kann, da hier oft multipliziert wird (etwa Stückzahl mal Preis). Ist ein Eingabewert eine leere Zeichenkette oder allgemein keine Zahl, so wird 0 zurückgegeben, und das Ergebnis der Multiplikation ist auch 0.

Die im Folgenden aufgeführte Funktion benutzt eine bereits zuvor entwickelte Funktion, sodass Sie auf eine konsistente Namensgebung achten müssen.

function smartEval(n){
   var s = "" + n //Umwandlung in eine Zeichenkette
   for (var i=0; i<s.length; i++)  //Kommata in Zahlen
      if (s.charAt(i)==",")
         s=s.substring(0,i)+"."+s.substring(i+1,s.length)
   if (isAFrac(s))
      return 1*s //Umwandlung in einen Zahlenwert
   else
      return 0
}

12.4 Reguläre Ausdrücke

Die Programmiersprache Perl ist unter anderem deswegen so beliebt, weil die Verwendung von regulären Ausdrücken so hoffähig gemacht worden ist1 . Ein regulärer Ausdruck ist – stark vereinfacht gesagt – eine Zeichenfolge, die ein Textmuster repräsentiert. Dieses Textmuster kann dann in einer längeren Zeichenkette gesucht werden. Ein umgangssprachlich formuliertes Textmuster ist etwa: »ein Wort, das mit J beginnt und zwei ›a‹s enthält«. Auf dieses Textmuster würden beispielsweise sowohl »Java« als auch »JavaScript« passen. Mit regulären Ausrücken kann man beispielsweise Formulareingaben sehr schnell überprüfen. Einige der Funktionen aus dem vorangegangenen Abschnitt können so viel einfacher programmiert werden. Ein Wort zur Warnung aber gleich vorweg: Mit den Methoden des String-Objekts, beispielsweise indexOf() und substring() kann man praktisch alle Funktionalitäten nachbilden, die reguläre Ausdrücke anbieten. Dazu ist jedoch eine Menge Programmierarbeit nötig (es gibt in der Tat auch Programme, die reguläre Ausdrücke in Programmcode umwandeln). Seitdem es die Browser der Generation 4 gibt, kann man sich die Extra-Arbeit sparen. Wenn Sie für ein Intranet arbeiten und wissen, dass nur neue Browser verwendet werden, können Sie reguläre Ausdrücke verwenden. Wenn Ihre Seiten zwar auch von älteren Browsern besucht werden, diese aber klar in der Minderheit sind, können Sie ebenfalls reguläre Ausdrücke verwenden, Sie sollten aber mit einer Abfrage Fehlermeldungen vermeiden.

12.4.1 Kurzeinführung

Ein Muster kann eine einfache Zeichenfolge sein, beispielsweise "abc". Das Interessante an Mustern sind jedoch die Sonderzeichen und Ausdrücke, mit denen man Muster flexibler gestalten kann. Im folgenden werden die wichtigsten dieser Sonderzeichen und Ausdrücke vorgestellt.

Sonderzeichen zum Zählen

Mit diesen Ausdrücken kann angegeben werden, wie oft ein gewisses Zeichen vorkommen darf oder muss. Der Ausdruck muss dabei immer direkt hinter dem Zeichen stehen.

	?: Null- oder einmal. Auf das Muster "ab?c" passen also "ac" und "abc", aber nicht "abbc".
	*: Null- oder mehrmals. Auf das Muster "ab*c" passen also "ac", "abc" und "abbc", aber nicht "adc".
	+: Ein- oder mehrmals. Auf das Muster "ab+c" passen also "abc" und "abbc", aber nicht "ac".
	{n}: Genau n-mal. Auf das Muster "ab{1}c" passt also "abc", aber nicht "abbc". Das Muster ließe sich zu "abc" vereinfachen.
	{n.m}: Zwischen n- und m-mal. Auf das Muster "ab{2,3}c" passen also "abbc" und "abbbc", aber nicht "abc".
	{n,}: Mindestens n-mal. Das Muster "ab{1,}" ist also äquivalent zu "ab+c". Dieser Ausdruck kann auch vollständig durch vorherige Ausdrücke ersetzt werden; äquivalent zu "ab{5,}c" ist beispielsweise "ab{4}b+c".

Die Sonderzeichen zum Zählen müssen sich nicht nur auf ein einzelnes Zeichen beziehen. Wenn man mehrere Zeichen mit runden Klammern umgibt, werden diese als Gruppe behandelt (die Klammern sind hierbei Sonderzeichen, das Muster sucht also nicht nach den Zeichen "(" und ")"). Auf das Muster "(abc)+" passen also unter anderem "abc", "abcabc" und "abcabcabc".

Metazeichen

Innerhalb eines regulären Ausdrucks versteht man unter einem Metazeichen ein normales Zeichen, das durch einen vorangestellten Backslash (\) eine besondere Bedeutung erhält. JavaScript unterstützt die folgenden Metazeichen:

	\b: Wortgrenze. An der Stelle, an der dieses Metazeichen steht, muss ein Wort beginnen oder aufhören, damit das Muster passt. Auf das Muster "\babc" passt beispielsweise "abcde", aber nicht "ababc". Auf "\babc\b" passt nur "abc"; das erste \b steht für den Wortanfang, das zweite für das Wortende.
	\B: Keine Wortgrenze, das Gegenteil von \b. Auf das Muster "\Babc" passt beispielsweise "ababc", aber nicht "abcde". Auf das Muster "\Babc\B" passt weder "ababc" (Wortende) noch "abcde" (Wortanfang), aber "babcb".
	\d: Ziffer. Auf das Muster "\d\d\d\d" passt beispielsweise "0815", aber nicht "R2D2".
	\D: Keine Ziffer. Auf das Muster "\D\D" passt weder "12" noch "A1" noch "1A", aber "AB".
	\s: Leerzeichen. Auf das Muster "Java\sScript" passt "Java Script", aber nicht "JavaScript".
	\S: Kein Leerzeichen. Auf das Muster "Java\SScript" passen "Java_Script" und "Java-Script", aber nicht "Java Script".
	\w: Buchstabe, Ziffer oder Unterstrich (_). Auf das Muster "\w" passen also beispielsweise "A", "a", "1" und "_", aber nicht "!".
	\W: Kein Buchstabe oder Ziffer oder Underscore. Auf das Muster "\W" passt beispielsweise "!", aber nicht "A", "a" oder "_".

Weitere Ausdrücke

	.: Jedes beliebige Zeichen außer einem Zeilensprung. Auf das Muster ".." passt also jede beliebige Folge zweier Zeichen.
	[...]: Eine Auswahlliste von Zeichen. Aus der Liste von Zeichen kann genau eines ausgewählt werden. Die Zeichen stehen dabei hintereinander. Es können auch Abkürzungen vorgenommen werden, beispielsweise bezeichnet "[A-Z]" alle Großbuchstaben und "[0-9]" alle Ziffern. Auf das Muster "[LJ]ava" passt also beispielsweise "Lava" und "Java", aber nicht "Cava". Das Metazeichen "\w" kann durch folgendes Muster ausgedrückt werden: "[a-zA-Z0-9_]" (alle Klein- und Großbuchstaben, Ziffern und Unterstrich).
	[^...]: Negierte Auswahlliste. Das Muster "[^a-zA-Z0-9_]" ist also äquivalent zum Metazeichen "\W".
	^: Zeilenanfang. Auf das Muster "^Java" passen beispielsweise "Java" und "JavaScript", aber nicht "I love Java".
	$: Zeilenende. Auf das Muster "Java$" passen beispielsweise "I love Java" und "Java", aber nicht "JavaScript".
	\: Entwertung eines Sonderzeichens. Das Dollar-Symbol "$" hat in regulären Ausdrücken eine besondere Bedeutung. Will man aber nach dem Währungssymbol suchen, so muss man "$" mit einem vorangestellten Sonderzeichen entwerten. Also passen auf das Muster "\d\d\d \$" beispielsweise "100 $" und "200 $". Natürlich kann ein Backslash auch sich selbst entwerten; auf das Muster "\\" passt "\".
	|: Oder-Operation. Auf das Muster "abc|def" passen unter anderem "abc" und "def".

12.4.2 Ein Objekt erzeugen

Ein regulärer Ausdruck kann mit JavaScript auf zwei Arten erstellt werden:

1.	var re = new RegExp("ab+c", "gi") Der erste Parameter ist der reguläre Ausdruck, was unschwer zu erkennen ist. Der zweite Parameter ist optional, kann aber – wenn er angegeben wird, einen der Werte "", "g", "i" oder "gi" haben (als regulärer Ausdruck geschrieben: "g?i?"). Hierbei steht "g" für global, und das ist beim Ersetzen wichtig. So kann ein Muster auch mehrmals in einer Zeichenkette gesucht (und gefunden) werden. Für case insensitive, also unabhängig von Groß- und Kleinschreibung, steht "i". Somit ist new RegExp("[a-zA-Z]") äquivalent zu new RegExp("[a-z]", "i").
2.	var re = /ab+c/gi Die Bedeutung des "gi" am Ende des Ausdrucks ist die gleiche wie im ersten Punkt. Der Unterschied ist hier, dass der reguläre Ausdruck von Schrägstrichen begrenzt wird. Das sieht im Vergleich zur restlichen JavaScript-Syntax etwas merkwürdig aus, weshalb ich die erste Variante bevorzuge. In diesem Buch wird jedoch die zweite Variante bevorzugt, weil die erste den Nachteil hat, dass z. B. der Backslash innerhalb eines Strings entwertet werden muss, also etwa "\\d". Das macht den Code für den Einsteiger nicht gerade lesbarer. Bei der zweiten Variante ist außerdem zu beachten, dass der Schrägstrich dann ja eine besondere Bedeutung hat und innerhalb des Musters mit einem Backslash entwertet werden muss, damit der JavaScript-Interpreter das Ende des Musters findet. Das Muster "\d\d/\d\d" passt beispielsweise auf "08/15", und new RegExp("\\d\\d/\\d\\d") ist auch korrekt, aber mit der zweiten Schreibweise muss es /\d\d\/\d\d/ heißen.

12.4.3 Mit dem Objekt arbeiten

Auf eine der beiden vorgestellten Arten können Sie ein RegExp-Objekt erzeugen. Dieses Objekt stellt mehrere Methoden zur Verfügung, die Ihnen bei der Anwendung von regulären Ausdrücken von Nutzen sein werden.

Einen Treffer suchen

Man spricht im Englischen von match, einem Treffer, wenn das Muster in der zu durchsuchenden Zeichenkette vorhanden ist. Die dazugehörige Methode lautet test("Zeichenkette"). Das folgende Codestück überprüft, ob es sich bei der Zeichenkette um eine deutsche Postleitzahl handeln könnte:

var re = /\d{5}/
var plz1 = re.test("01234") //gibt true zurück
var plz2 = re.test("8000") //gibt false zurück
var plz2 = re.test("D8000") //gibt false zurück

Mit dem folgenden Code wird überprüft, ob es sich bei dem Eingabewert um eine ganze Zahl handelt. Dieser Test wurde weiter oben schon etwas mühsam entwickelt; hier handelt es sich um deutlich weniger Schreibarbeit:

var re = /0|-?[1-9]\d*/
var zahl1 = re.test("12345") //gibt true zurück
var zahl2 = re.test("01234") //gibt false zurück

Zur Erklärung: Eine ganze Zahl ist entweder die Null oder eine Ziffernfolge, die nicht mit der Null beginnt (also eine Ziffer von 1 bis 9). Hinter der führenden Ziffer stehen beliebig viele weitere Ziffern oder aber auch keine Ziffer mehr. Die Ziffernfolge kann durch ein optionales Minus-Zeichen eingeleitet werden.

Treffer zurückliefern

In der Praxis kommt es oft darauf an, nicht nur einen Treffer zu finden, sondern auch den auf das Muster passenden Teil der Zeichenkette zu erhalten, und teilweise auch darauf, Teile davon zu erhalten.

Oben wurde bereits erwähnt, dass man mit runden Klammern einzelne Zeichen im Muster gruppieren kann. Das ist nicht nur für Nummerierungen von Bedeutung, sondern auch für das Ergebnis, da man den Wert der einzelnen Klammern gezielt abfragen kann. Dies soll an einem Beispiel verdeutlicht werden.

In einem Firmen-Intranet wird die Stundenerfassung elektronisch erledigt. Um Eingabefehler abzufangen, soll JavaScript verwendet werden. Eine Stundenangabe soll im Format »0:30« bzw. »12:45« erfolgen. Der folgende reguläre Ausdruck prüft auf dieses Format. Beachten Sie bitte, dass dabei die ersten runden Klammern um die Stundenzahl stehen, die zweiten runden Klammern um die Minutenzahl.

var dauer = /(1?\d):([0-5]\d)/g

Der gewerkschaftlich organisierte Leser wird gewiss verzeihen, dass Arbeitszeiten bis zu 19 Stunden und 59 Minuten zugelassen werden; der Leser in Führungsposition übersehe, dass keine Arbeitszeiten über 20 Stunden erlaubt sind.

In diesem Beispiel wird die Methode exec("Zeichenkette") des RegExp-Objekts verwendet. Im Gegensatz zu test("Zeichenkette") wird hier nicht einfach ein Boolescher Wert zurückgegeben, sondern ein spezielles Objekt, das den Teil der Zeichenkette enthält, auf die das Muster passt. Außerdem werden auch die Teile innerhalb der runden Klammern abgespeichert. Folgender Code wird das verdeutlichen:

var dauer = /(1?\d):([0-5]\d)/
var test = dauer.exec("abc2:45def")
document.write("Uhrzeit: " + test[0] + "<BR>") // 2:45
document.write("Stunden: " + test[1] + "<BR>") // 2
document.write("Minuten: " + test[2] + "<BR>") // 45

Das Objekt, das exec() zurückgibt, ist so etwas wie ein Array. Im Element mit dem Index 0 steht der Teil der Zeichenkette, auf den das Muster passt. Im Element mit dem Index 1 steht der Teil, der im Muster durch die ersten Klammern umgeben ist.

Mehrere Treffer

Oft ist es nicht nur von Bedeutung herauszufinden, ob in einer Zeichenkette ein Muster vorkommt und wie dieses eine Vorkommen aussieht, sondern auch, wie oft es vorkommt und wie diese Vorkommen denn aussehen. Für diese Zwecke ist die Methode match() des String-Objekts geeignet. Als Parameter kann dazu ein regulärer Ausdruck übergeben werden. Die Methode match() gibt alle Treffer in einem Array zurück. Sobald man dieses Array hat, kann man auf die herkömmliche Art und Weise die Ergebnisse auslesen.

An folgendem Beispiel soll dies gleich einmal verdeutlicht werden. Innerhalb einer Zeichenkette sollen alle Wörter herausgesucht werden, die den Buchstaben "e" nur einmal enthalten. Der zugehörige reguläre Ausdruck lautet "\b[a-df-zA-DF-Z]*e[a-df-zA-DF-Z]*\b". Er sieht kompliziert aus, bedeutet aber einfach, dass es sich um ein Wort handelt (angezeigt durch die Wortgrenzen am Anfang und am Ende), das ein e enthält und ansonsten aus weiteren Buchstaben ungleich e (also von a bis d und von f bis z) besteht. Des weiteren muss die Option "g" für globales Suchen angegeben werden, damit auch alle Vorkommen gefunden werden.

var nur_ein_e = /\b[a-df-zA-DF-Z]*e[a-df-zA-DF-Z]*\b/g
var satz = "Die Geister die ich rief ward ich nicht mehr los"
var liste = satz.match(nur_ein_e)
if (liste){
   document.write(liste.length + " Treffer gefunden!<BR>")
   for (var i=0; i<liste.length; i++)
      document.write(liste[i]+"<BR>")
} else
   document.write("Keine Treffer!")

Abbildung 12.6  Alle Wörter, die nur ein ’e’ enthalten

Suchen und ersetzen

Die letzte Anwendung für reguläre Ausdrücke, die hier vorgestellt werden soll, wird mit am häufigsten verwendet – wurde aber lange Zeit nur vom Netscape Navigator unterstützt. Man kann nicht nur nach Mustern suchen, sondern diese Muster auch durch andere Muster ersetzen. Ein Beispiel war die Umformung einer »deutschen« Dezimalzahl in die amerikanische Schreibweise. Dazu mussten alle Kommata durch Dezimalpunkte ersetzt werden. Der folgende Code erledigt das sehr einfach – aber eben leider nur bei Browsern der 4. Generation.

var komma = /,/g
var dezimalzahl_brd = "3,141592"
var dezimalzahl_usa = dezimalzahl_brd.replace(komma, ".")
document.write(dezimalzahl_usa) // 3.141592

Auch hier gibt es fortgeschrittenere Anwendungen. Ein weiterer Unterschied in der Schreibweise zwischen Deutschland und den USA besteht im Datum. Während das Format hierzulande meistens tt.mm.jj bzw. tt.mm.jjjj ist (t=Tag, m=Monat, j=Jahr), so verwendet man in den Vereinigten Staaten in der Regel jj-mm--tt bzw. jjjj-mm-tt. Die Aufgabe besteht jetzt darin, deutsche Datumsangaben durch das amerikanische Pendant zu ersetzen. Beginnen wir mit dem regulären Ausdruck für einen Datumswert. Das Jahr ist zwei- oder vierstellig, Monat und Tag sind aber unter Umständen einstellig. Außerdem dürfen als Werte für den Tag nur Werte von 1 bis 31, beim Monat nur Werte von 1 bis 12 verwendet werden (unmögliche Daten wie etwa dem 30. Februar werden hier übergangen, um das Beispiel einfach zu halten). Der Ausdruck sieht also recht kompliziert aus, aber die Idee, die dahintersteht, ist recht einfach. Probieren Sie es doch einmal mit indexOf()!

var datum = /\b(0?[1-9]|[12][0-9]|3[01])\.(0?[1-9]|1[0-2])\.
  (\d?\d?\d\d)\b/

Wie Sie sehen, wurden um Tag, Monat und Jahr runde Klammern eingefügt. Der Sinn des ganzen zeigt sich bei der Übersetzung in das amerikanische Format. Die Jahreszahl muss nach vorn, der Tag nach hinten. Während beim Ergebnis der Methode exec() die Inhalte der Klammern in ergebnisarry[1], ergebnisarray[2] und so weiter stehen, findet man die Inhalte der Klammern bei regulären Ausdrücken in den speziellen Variablen $1, $2 und so weiter. Mit folgendem Code wandelt man ein deutsches Datum in das amerikanische Format um.

function deutsch_zu_usa(d){
   var datum = /\b(0?[1-9]|[12][0-9]|3[01])\.(0?[1-9]|1[0-2])\.
     (\d?\d?\d\d)\b/
   if (datum.test(d))
      return d.replace(datum, "$3-$2-$1")
   else
      return d
}
document.write(deutsch_zu_usa("Das dritte Jahrtausend
beginnt am 1.1.01 – und keinen Tag früher"))

Mit d.replace(datum, "$3-$2-$1") wird der reguläre Ausdruck auf die Eingabe angewandt. In der dritten Klammer, also in $3, steht die Jahreszahl, in $2 der Monat und in $1 der Tag. Die Ausgabe lautet dann: "Das dritte Jahrtausend beginnt am 01-1-1 – und keinen Tag früher". In der Variablen $0 steht übrigens analog zu exec() der gesamte Treffer, in diesem Fall also "1.1.2001".

Die Funktion replace() gibt es auch in einer Luxusvariante. Wie beim Netscape-Pendant auch werden an replace() zwei Parameter übergeben. Die erste ist ein regulärer Ausdruck, und der zweite ist eine Funktion, welche vom JavaScript-Interpreter automatisch beim Aufruf von replace() aufgerufen wird. An diese Funktion werden (vom JavaScript-Interpreter!) die folgenden Parameter übergeben (in der angegebenen Reihenfolge):

	Die Zeichenkette, die auf das Muster passt.
	Der Reihe alle Untermuster. Wenn im regulären Ausdruck Klammern verwendet worden sind, werden die Entsprechungen in diesen Klammern (also die Werte von $1, $2 usw.) an die Funktion übergeben.
	Die Position, an der das Muster in der zu überprüfenden Zeichenkette gefunden wurde.
	Die überprüfte Zeichenkette.

Die Funktion, die von replace() aufgerufen wird, muss nun nur noch folgendes leisten: Einen Wert zurückliefern. Durch diesen Wert wird das gefundene Muster in der zu überprüfenden Zeichenkette ersetzt.

Das Beispiel von oben – die Umformung des Datums in ein amerikanisches Format – kann folgendermaßen angepasst werden:

function deutsch_zu_usa(d){
   var datum = /\b(0?[1-9]|[12][0-9]|3[01])\.(0?[1-9]|1[0-2])\.
     (\d?\d?\d\d)\b/
   if (datum.test(d))
      return d.replace(datum, d_zu_usa)
   else
      return d
}
function d_zu_usa(str, m1, m2, m3, pos, quelle){
   return m3+"-"+m2+"-"+m1 //entspricht $3-$2-$1
}
document.write(deutsch_zu_usa("Das dritte Jahrtausend
beginnt am 1.1.01 – und keinen Tag früher"))

Microsoft hat die replace()-Funktion erst in Version 5.5 (wie bereits erwähnt im Beta-Stadium) des Internet Explorer eingebaut, mit früheren Versionen, inklusive der momentan aktuellen Version 5, funktioniert das noch nicht.

Neues in JavaScript 1.5

In JavaScript 1.5, was zur Zeit nur vom Netscape 6 unterstützt wird, erhält der Fragezeichenoperator ? eine weitere Bedeutung. Normalerweise arbeitet die Mustererkennung bei einem regulären Ausdruck »gierig«, sprich: Es wird ein möglichst großer Treffer zurückgeliefert. Hier ein Beispiel:

var htmltag = /(<.*>)/
var test = htmltag.exec("<p>JavaScript</p>")
test[0] = test[0].replace("<", "&lt;")
test[0] = test[0].replace(">", "&gt;")
document.write("HTML-Tag: " + test[0])

Was gibt dieses Programm aus? Vielleicht erwarten Sie als Ausgabe "<p>", denn das würde auf das angegebene Muster passen. Doch leider falsch gedacht, denn es wird wie gesagt immer ein möglichst großer Treffer zurückgeliefert, in diesem Falle also "<p>JavaScript</p>". Wenn Sie einen möglichst kleinen Treffer möchten, müssen Sie direkt nach einem Sonderzeichen zum Zählen (*, +, ?, {}) den Fragezeichenoperator angeben. Folgender Code würde also in der Tat "<p>" ausgeben:

var htmltag = /(<.*?>)/
var test = htmltag.exec("<p>JavaScript</p>")
test[0] = test[0].replace("<", "&lt;")
test[0] = test[0].replace(">", "&gt;")
document.write("HTML-Tag: " + test[0])

Wenn Sie diesen Code mit dem Netscape Navigator 4.x oder dem Internet Explorer 5.0x oder kleiner ausführen, erhalten Sie entweder ein falsches Ergebnis oder eine Fehlermeldung. Der Internet Explorer 5.5 unterstützt zwar kein JavaScript 1.5, hat aber diese Erweiterung der Syntax für reguläre Ausdrücke auch im Programm.

Abbildung 12.7  Netscape 6 interpretiert den regulären Ausdruck richtig

12.5 Fragen & Aufgaben

1.	Ändern Sie das Buchbestellungsformular so um, dass die URL der folgenden Seite »von Hand« erzeugt wird statt durch den Browser beim Absenden des Formulars.
2.	Ändern Sie das Beispiel mit den zwei Auswahllisten so um, dass die Link-Ziele im VALUE-Attribut (bzw. der Eigenschaft value der Option) gespeichert werden.
3.	Überlegen Sie sich, wir man überprüfen könnte, ob eine Email-Adresse gültig ist. Schreiben Sie eine einfache Überprüfungsfunktion, die aber JavaScript 1.0-kompatibel sein sollte.
4.	Geben Sie reguläre Ausdrücke an für:
		Vierbuchstabige Wörter
		Gerade, positive Zahlen
		(Vierstellige) Jahreszahlen des 20. Jahrhunderts
		Email-Adressen (muss nicht allzu strikt sein)
5.	Schreiben Sie ein JavaScript-Programm, das eine (beliebige) Stundenangabe im Format 12:35 annimmt und dann die Entlohnung bei einem Stundensatz von 8 DM ausgibt – in deutschem Format. Reguläre Ausdrücke dürfen verwendet werden.
6.	Schreiben Sie eine JavaScript-Funktion, die in einer Zeichenkette alle dreibuchstabigen Wörter durch die Zeichenkette "$0" ersetzt.
7.	Schreiben Sie das letzte Beispiele in diesem Kapitel (Suche nach HTML-Tag) so um, dass es auch im Netscape 4.x und im Internet Explorer 5.0x oder kleiner funktioniert! Verwenden Sie dabei aber einen regulären Ausdruck.

1    Natürlich gibt es reguläre Ausdrücke schon viel länger, aber mit der Verbreitung von Perl stieg auch die Verbreitung von regulären Ausdrücken.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 13 Arrays
			13.1 Array-Erweiterungen
			13.2 Eigene Objekte
			13.3 Fragen & Aufgaben

Kapitel 13 Arrays

Floyd: Doyle, I know I gave him four threes. He had to make a switch. We can’t let him get away with that!

Doyle: What was I supposed to do – call him for cheating better than me, in front of the others?

– aus: Der Clou (The Sting)

Bisher wurde bei Arrays immer tunlichst darauf geachtet, dass diese auch stets JavaScript-1.0-kompatibel sind. In diesem Kapitel wählen wir zunächst einen anderen Ansatz und stellen die erweiterten Array-Möglichkeiten der JavaScript-Versionen 1.0 und 1.1 vor. Um einige der Methoden kennen zu lernen, werden wir Spielkarten mischen.

Am Ende des Kapitels wird die Browser-Unabhängigkeit wieder hergestellt, und einige der neuen Array-Methoden werden für ältere Browser nachgebildet. Hierzu ist es nötig, ein eigenes Array-Objekt zu erstellen. Grundlage dafür wird die Funktion MakeArray() aus dem Kapitel »Programmierung II« sein.

13.1 Array-Erweiterungen

Wie bereits erwähnt, kann man folgendermaßen eine Instanz eines Arrays erstellen:

var a = new Array()

Werden Parameter übergeben, so wird das Array vorausgefüllt:

var a = new Array(1, 2, 3, "abc")

	Beim Netscape Navigator 3 und dem recht bald danach erschienenen Internet Explorer 4 gibt es jedoch einen Bug in der Implementierung. Der folgende Befehl sollte ein Array erstellen, das (am Anfang) genau ein Element enthält; er wird jedoch als Generierung eines Arrays interpretiert, das (anfangs) die Länge 5 hat:

var a = new Array(5)

In neueren JavaScript-Versionen kann ein Array auch so initialisiert werden:

var a = [1, 2, 3, "abc"]

In der Eigenschaft length des Arrays wird die Anzahl der Elemente festgesetzt. Verringert man beispielsweise diese Eigenschaft, so werden die letzten Elemente des Arrays dementsprechend gelöscht. An sich hat ein Array aber beliebig viele Elemente. Wird ein zu großer Index für ein Element verwendet, so wird length dementsprechend angepasst. Nach den folgenden beiden Zeilen ist a.length gleich fünf.

var a = new Array(1, 2, 3)
a[4] = 42

13.1.1 Einfügen, nicht anfügen

	In der JavaScript-Version 1.0 waren die Arrays eher unflexibel. Der Programmierer konnte hinten Daten anfügen und (durch Setzen der length-Eigenschaft) hinten Daten löschen, aber ein Einfügen von Daten in der Mitte beispielsweise gestaltete sich zunächst etwas schwierig. Man musste hier einen etwas umständlichen Weg gehen: Das Array musste zuerst vergrößert werden (am besten, indem die length-Eigenschaft um eins erhöht wird), dann mussten alle Daten ab der Einfügestelle um eins nach hinten kopiert werden. Abschließend wurden die neuen Daten an die entsprechende Stelle im Array gesetzt. Die folgende Funktion bietet diese Funktionalität; als Parameter müssen das Array, die Einfügestelle1  und die Daten übergeben werden. Die Funktion gibt das modifizierte Array zurück:

function einfuegen(_array, _position, _datum){
   _array.length ++
   for (var i=_array.length-1; i>=position; i--)
      _array[i+1] = _array[i]
   _array[_position] = _datum
   return _array
}

13.1.2 Anfügen und löschen

Auch mit den neueren JavaScript-Versionen ist es nicht möglich, direkt mitten in einem Array Elemente einzufügen. Jedoch gibt es neue Methoden, mit denen Elemente bequem an ein Array angehängt oder aus ihm gelöscht werden können. Wenn wir Karten mischen, werden diese Methoden noch einmal interessant werden.

Eine komplette Auflistung der Methoden befindet sich wie gewohnt in der Referenz. Exemplarisch werden hier nur die Funktionen vorgestellt, die für das Beispiel von Bedeutung sein werden. Die folgenden Methoden sind alle ab JavaScript 1.2 möglich und sind (im Gegensatz zur Funktion einfuegen() oben) alle Methoden des Array-Objekts.

Microsoft hat an dieser Stelle übrigens geschlafen: Die neuen Funktionen sind – sofern nicht anders vermerkt – erst ab Internet Explorer 5.5 in der JScript-Implementierung enthalten. Wenn Sie also auf diese Funktionalitäten Wert legen, sollten Sie das Kapitel bis zum Ende durchlesen, um zu erfahren, wie Sie diese Funktionalität auch auf älteren Browsern implementieren können.

Mit der Methode push() werden Elemente hinten an ein Array angehängt. Die Methode ist dabei in bezug auf die Anzahl der übergebenen Parameter flexibel, das heißt, es muss zwar mindestens ein Element angegeben werden, es können aber auch zwölf sein.

Das folgende Beispiel erzeugt wieder ein Array mit den Monatsnamen, aber in mehreren Schritten:

var monate = new Array("Januar", "Februar", "März")
monate.push("April", "Mai", "Juni", "Juli", "August")
monate.push("September", "Oktober", "November", "Dezember")

Natürlich ist es auch möglich, Elemente aus einem Array zu entfernen. An die Methode push() angelehnt ist die Methode pop(), die das letzte Element aus einem Array entfernt. Viel flexibler ist jedoch die Methode splice(), die Elemente aus einem Array entfernt (die gibt es übrigens nur im Netscape Navigator, und auch im Internet Explorer 5.5 noch nicht). Dieser Methode werden mindestens zwei Parameter übergeben:

	Der erste Parameter gibt an, ab welcher Position Elemente entfernt werden sollen (wie immer beginnt die Zählung bei Null).
	Der zweite Parameter enthält die Anzahl der Array-Elemente, die aus dem Array entfernt werden sollen.
	Alle folgenden Parameter werden an das Array hinten angefügt, so wie bei push(). Diese Parameter sind jedoch optional, es ist also auch möglich, aus einem Array nur Elemente zu entfernen.

Im folgenden Beispiel enthält die Monatsliste einige Fehler, die mit einem einzigen Aufruf von splice() behoben werden:

var a = new Array("Januar", "Februar", "März", "April", "Mai",
  "JavaScript", "JScript", "Juni", "Juli", "August", "September")
//Aufgabe: die Einträge an Position 5 und 6 entfernen
//und die fehlenden Einträge/Monate anhängen
a.splice(5, 2, "Oktober", "November", "Dezember")

13.1.3 Karten mischen

Zum Mischen der Karten wird ein neues Array erstellt. Ein Element aus dem Array mit den Karten wird zufällig ausgewählt und an ein neues Array angehängt. Abschließend muss die Karte noch aus dem alten Array entfernt werden, damit die Karte im neuen Array nicht etwa doppelt vorkommt. Der folgende Code ist somit ziemlich selbsterklärend. Im Kapitel »Java« finden Sie einen ähnlichen Code noch einmal.

//Hilfsvariablen für die Kartenbezeichnungen
var kartenname = new Array()
kartenname[0]="Zwei"; kartenname[1]="Drei"
kartenname[2]="Vier"; kartenname[3]="Fünf"
kartenname[4]="Sechs"; kartenname[5]="Sieben"
kartenname[6]="Acht"; kartenname[7]="Neun"
kartenname[8]="Zehn"; kartenname[9]="Bube"
kartenname[10]="Dame"; kartenname[11]="König"
kartenname[12]="As"
var farben = new Array();
farben[0] = "Herz"; farben[1] = "Karo"
farben[2] = "Pik"; farben[3] = "Kreuz"
//Initialisierung des Karten-Arrays
var cards = new Array()
for (var i=0; i<13; i++)
   for (var j=0; j<4; j++){
      karte = kartenname[j]+" "+farben[i]
      cards.push(karte)
   }
//Mischen
var neu = new Array()
while (cards.length>0){
   var zufall = Math.floor(Math.random()*cards.length)
   karte = cards[zufall]
   cards.splice(zufall, 1)
   neu.push(karte)
}

13.1.4 Sortieren

	Schon seit der JavaScript-Version 1.1 gibt es die Methode sort() für Arrays, die die Elemente eines Arrays alphanumerisch sortiert. Zuvor werden die Array-Elemente alle in Zeichenketten umgewandelt, was zu Problemen führt:

var a = new Array(1, 3, 5, 7, 11).sort()

Nach diesem Aufruf hat a den Wert [1, 11, 3, 5, 7] – denn sowohl eins als auch elf beginnen mit einer "1" – und das kommt im ASCII-Alphabet vor der "3". Man kann sich hier jedoch behelfen, indem man eine Sortierfunktion schreibt. Das muss eine Funktion sein, der zwei Parameter übergeben werden können. Diese Funktion gibt dann eine positive Zahl zurück, wenn der erste Parameter gemäß den Sortierkriterien »größer« als der zweite Parameter ist; ist der zweite Parameter der »größere«, wird eine negative Zahl zurückgegeben. Im dritten Fall, wenn die beiden Parameter »gleich groß« sind, muss der Rückgabewert der Funktion 0 betragen.

In unserem Beispiel soll das Kartenblatt sortiert werden, und zwar nach dem Wert der Karten. Hierbei wird folgendermaßen vorgegangen:

	Alle Zeichen vor dem Leerzeichen stellen die eigentliche Karte dar (also ohne Farbwert).
	In einem Array sind die Kartenwerte abgespeichert.
	Von den beiden übergebenen Parametern wird der Array-Index im Kartenwert-Array ermittelt. So kann angegeben werden, welche Karte »größer« ist und welche »kleiner«. Dementsprechend kann der korrekte Wert zurückgegeben werden.
	Haben beide Karten denselben Wert, so wird (alphabetisch) nach der Farbe sortiert.

Die folgende Funktion erledigt das. Da jetzt JavaScript 1.1 verwendet werden darf, wird eine neue Funktion verwendet: Zeichenkette. split(Trennzeichen). Die Zeichenkette wird anhand der Trennzeichen aufgeteilt, und die einzelnen Teilstrings werden in einem Array zurückgegeben. Der Aufruf

"1;2;3".split(";")

liefert folgendes Array zurück:

[1, 2, 3]

Nun aber zur Sortierfunktion:

function cardsort(a, b){
   var kartenname = new Array()
   kartenname[0]="Zwei"; kartenname[1]="Drei"
   kartenname[2]="Vier"; kartenname[3]="Fünf"
   kartenname[4]="Sechs"; kartenname[5]="Sieben"
   kartenname[6]="Acht"; kartenname[7]="Neun"
   kartenname[8]="Zehn"; kartenname[9]="Bube"
   kartenname[10]="Dame"; kartenname[11]="König"
   kartenname[12]="As"
   var wert_a = (a.split(" "))[0]
   var wert_b = (b.split(" "))[0]
   var index_a = -1; var index_b = -1
   for (var i=0; i<kartenname.length; i++){
      if (kartenname[i]==wert_a)
         index_a = I
      if (kartenname[i]==wert_b)
         index_b = I
   }
   if (index_a>index_b) return 1
      else if (index_a<index_b) return -1
   var farbe_a = (a.split(" "))[1]
   var farbe_b = (b.split(" "))[1]
   return (farbe_a>farbe_b) ? 1 : 0
}

Der Name der Funktion wird dann als Parameter an die sort()-Methode des Arrays übergeben. Bitte beachten Sie, dass hierbei dem Funktionsnamen keine Klammern folgen.

//Hilfsvariablen für die Kartenbezeichnungen
var kartenname = new Array()
kartenname[0]="Zwei"; kartenname[1]="Drei"
kartenname[2]="Vier"; kartenname[3]="Fünf"
kartenname[4]="Sechs"; kartenname[5]="Sieben"
kartenname[6]="Acht"; kartenname[7]="Neun"
kartenname[8]="Zehn"; kartenname[9]="Bube"
kartenname[10]="Dame"; kartenname[11]="König"
kartenname[12]="As"
var farben = new Array()
farben[0] = "Herz"; farben[1] = "Karo"
farben[2] = "Pik"; farben[3] = "Kreuz"
//Initialisierung des Karten-Arrays
var cards = new Array()
for (var i=0; i<13; i++)
   for (var j=0; j<4; j++){
      karte = kartenname[i]+" "+farben[j]
      cards.push(karte)
   }
//Mischen
var neu = new Array()
while (cards.length>0){
   var zufall = Math.floor(Math.random()*cards.length)
   karte = cards[zufall]
   cards.splice(zufall, 1)
   neu.push(karte)
}
//Sortieren
neu.sort(cardsort)
//Hand ausgeben
document.write(neu.toString())

Mit der Methode toString() wird jedes Objekt, sofern möglich, in eine Zeichenkette umgewandelt. Bei einem Array werden ab der JavaScript-Version 1.3 die einzelnen Elemente durch Kommata getrennt ausgegeben; bei älteren Versionen wird der Quellcode des Arrays ausgegeben (siehe Abbildung 13.1).

Abbildung 13.1  Das gemischte und dann wieder sortierte Array

Beachten Sie, dass in Abbildung 13.1 das Kartenblatt sortiert ist. Wenn Sie im Listing die Zeile neu.sort(cardsort) auskommentieren, erhalten Sie ein vermischtes Blatt (siehe Abbildung 13.2).

Abbildung 13.2  Das unsortierte Array

13.2 Eigene Objekte

In diesem Abschnitt sollen einige Array-Funktionalitäten der JavaScript-Version 1.2 für ältere Browser (und die meisten Versionen des Internet Explorer) nachgebildet werden. Dazu ist es nötig, eigene Objekte zu erstellen.

In der Praxis wird diese Technik nur bei größeren Projekten verwendet, und wenn der Funktionsumfang der üblichen Variablen und Arrays nicht mehr ausreicht.

13.2.1 Allgemeines

Betrachten Sie noch einmal die berühmte Funktion MakeArray() aus dem Kapitel »Programmierung II«:

function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
}

Hier die kurze, aber um so länger versprochene Erklärung für den obigen Code: Mit dem Schlüsselwort this wird ja normalerweise auf das aktuelle Objekt zugegriffen, im Allgemeinen auf das aktuelle Fenster oder Formularelement. Wird diese Funktion jedoch als sogenannte Konstruktorfunktion für ein Objekt verwendet, also mit new MakeArray() aufgerufen, so bezeichnet this die aktuelle Instanz des Objekts. Somit wird durch die wiederholte Ausführung des Befehls this[i]=0 die Instanz als Array deklariert, und jedes Array-Element mit Null vorbelegt. Von besonderer Bedeutung ist die Zeile this.length = n. Hierdurch wird die Eigenschaft length des Objekts auf n gesetzt, und nicht etwa die Länge eines Arrays (Anzahl der Elemente) festgelegt. Standardmäßig hat ja ein Array unbegrenzt viele Elemente, und das ist auch hier so. Da es sich hierbei aber um kein »echtes« Array handelt, sondern um ein eigenes Objekt, hat die Eigenschaft length nichts mit der Anzahl der Elemente des Objekts zu tun. Wird also ein Element an das Array angefügt, so wird length nicht automatisch angepasst; das muss man also selbst übernehmen. Aus diesem Grund sollten Sie bei der Verwendung von MakeArray() sehr vorsichtig sein.

13.2.2 Methoden definieren

Fast genauso einfach wie die Definition von Objekteigenschaften ist die Definition von Objektmethoden. Auch hier ist der this-Operator wieder von Bedeutung. Beim Setzen einer Methode verwendet man folgende Syntax im Konstruktor:

this.methode = funktion

Bei jedem Aufruf der Methode wird funktion() ausgeführt, und innerhalb von funktion() kann man mit this auf die verwendete Instanz des Objekts zugreifen. Beachten Sie, dass auch hier die Klammern fehlen.

Als Beispiel soll die Methode toString() implementiert werden. Dazu muss zunächst MakeArray() folgendermaßen geändert werden:

function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
   this.toString = arraytoString
}

Die Funktion arraytoString() gibt die Elemente des Arrays, durch Kommata voneinander getrennt, aus. Dazu werden einfach alle Elemente in this abgefragt und miteinander verkettet.

function arraytoString(){
   var returnstring = ""
   for (var i=0; i<this.length-1; i++)
      returnstring += this[i] + ","
   returnstring += this[this.length-1]
   return returnstring
}

Analog kann man auch die Funktion push() nachbilden: Alle übergebenen Parameter werden an das Array angehängt. Abschließend muss die Eigenschaft length noch angepasst werden.

function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
   this.toString = arraytoString
   this.push = arraypush
}
function arraypush(){
   for (var i=0; i<arraypush.arguments.length; i++)
      this[this.length+i] = arraypush.arguments[i]
   this.length += arraypush.arguments.length
}

13.2.3 Eigene Sortiermethode

	Das Sortieren war bei JavaScript Version 1.0 noch nicht möglich. Erstellt man jedoch ein eigenes Objekt, kann man diese Funktionalität auch nachbilden. Die Einrichtung einer Methode fällt nicht schwer, Sie müssen nur eine Zeile in die Konstruktorfunktion einfügen:

function MakeArray(n){
   for (var i=0; i<n; i++)
      this[i] = 0
   this.length = n
   this.toString = arraytoString
   this.push = arraypush
   this.sort = arraysort
}

Bei der Implementierung der Funktion arraysort() muss man sich zunächst für einen geeigneten Sortieralgorithmus entscheiden. Am leichtesten tut man sich – zumindest nach meiner Meinung – mit dem Bubblesort-Algorithmus. Der benötigt zwar eine quadratische Laufzeit (unter diesem Aspekt gibt es bessere Algorithmen), aber ist dafür besonders einfach zu implementieren. Das Verfahren funktioniert wie im Folgenden beschrieben: Zwei nebeneinander liegende Elemente des Arrays werden miteinander verglichen. Haben diese Elemente schon die richtige Reihenfolge (ist das »linke« also kleiner als das »rechte«), passiert nichts, ansonsten tauschen die beiden Elemente ihren Platz. Sodann wird das jetzt rechts liegende Element und das Element rechts daneben betrachtet. Auf diese Weise wird das gesamte Array durchlaufen, und das geschieht so oft, bis das Array korrekt sortiert ist.

Das folgende Ablaufschema zeigt exemplarisch die Sortierung. Elemente, die vertauscht werden, sind jeweils unterstrichen:

3142®1342®1324®1234

Zunächst muss man sich überlegen, wie man zwei Elemente – oder vereinfacht gesagt, zwei Variablen – vertauscht. Der folgende Code funktioniert leider nicht:

var a, b
function tausche(){
   a=b
   b=a
}

Nachdem die Zuweisung a=b ausgeführt wurde, enthalten a und b denselben Wert; der ursprüngliche Wert von a ist verloren. Um nun wirklich vertauschen zu können, verwendet man eine Hilfsvariable, in der man den ursprünglichen Wert von a abspeichert. Sodann wird a der Wert von b zugewiesen, und b enthält den ursprünglichen Wert von a – aus der Hilfsvariablen:

var a, b
function tausche(){
   var hilfsvariable = a
   a = b
   b = hilfsvariable
}

Die Implementierung des Bubblesort-Algorithmus ist dann nicht weiter schwierig. Man darf sich nur beim Vertauschen der Array-Elemente nicht vertun und muss immer fleißig this verwenden!

function arraysort(){
   var sortiert = false  //Überprüfung, ob sortiert
   while (!sortiert){
      sortiert = true
      for (var i=0; i<this.length-1; i++)
         if (this[i]>this[i+1]){
            sortiert = false
            hilfsvariable = this[i]
            this[i]=this[i+1]
            this[i+1] = hilfsvariable
         }
   }
}

Beachten Sie, dass die Laufvariable i von 0 bis this.length-2 läuft, da das Array-Element an Position i mit dem nachfolgenden Element verglichen wird – und das Element an der Position this.length-1 hat keinen Nachfolger.

13.2.4 Eigene Sortiermethode, Teil 2

In Hinblick auf das Beispiel mit dem Kartenspiel wäre es natürlich noch schön, wenn man wieder die Sortiermethode selbst angeben könnte. Auch dies kann man mit JavaScript erreichen, zunächst muss man die Funktion arraysort() leicht modifizieren:

function arraysort(){
   var sortiert = false  //Überprüfung, ob sortiert
   while (!sortiert){
      sortiert = true
      for (var i=0; i<this.length-1; i++)
         if (groesser(this[i], this[i+1], arraysort.arguments[0])){
            sortiert = false
            hilfsvariable = this[i]
            this[i]=this[i+1]
            this[i+1] = hilfsvariable
         }
   }
}

Die Funktion groesser(a, b, arg) gibt zurück, ob a größer als b ist; arg enthält einen an die Funktion arraysort übergebenen Parameter (wozu der nützlich ist, wird gleich erläutert). Im Beispiel aus dem vorherigen Abschnitt würde diese Funktion folgendermaßen aussehen:

function groesser(a, b, arg){
   return (a>b)
}

Unser Ziel soll es jedoch sein, eine beliebige Funktion an arraysort() bzw. an die Methode sort() des MakeArray-Objekts zu übergeben. Aufgrund der Einschränkungen von JavaScript muss der Name der Sortierfunktion als Zeichenkette übergeben werden. Der Rest ist dann gar nicht mehr so schwierig. Mittels eval() wird die Sortierfunktion mit zwei Array-Elementen als Parametern aufgerufen und das Ergebnis ausgewertet. Zur Erinnerung: Ist das Ergebnis größer als 0, so ist der erste Parameter größer als der zweite, und nur dann. Zusätzlich muss natürlich noch überprüft werden, ob überhaupt ein Parameter an arraysort() übergeben worden ist. Sollte das nicht der Fall sein, wird ein alphanumerischer Vergleich mit dem >-Operator durchgeführt.

function groesser(a, b, arg){
   if (arg==null)
      return (a>b)
   else{
      var erg = eval(arg + "(\"" + a + "\", \"" + b + "\")")
      return (erg>0)
   }
}

13.2.5 Zusammenfassung

	Im folgenden finden Sie eine Anwendung für das MakeArray-Objekt. Das Kartenblatt wird initialisiert, in vier Teile aufgeteilt (beispielsweise für eine Partie Schafkopf zu viert) und (sortiert) ausgegeben. Obwohl der Code natürlich länger ist, als wenn man sich auf JavaScript 1.2 beschränkt, ist das potentielle Publikum dafür gleich viel größer.

Die Funktion MakeArray() wurde für dieses Beispiel leicht angepasst, so dass man als Parameter nicht die Größe des Arrays übergibt, sondern die ersten Array-Elemente selbst.

<HTML>
<HEAD>
<TITLE>Karten spielen mit JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
//Funktionen des MakeArray-Objekts
function MakeArray(){
   for (var i=0; i<MakeArray.arguments.length; i++)
      this[i] = MakeArray.arguments[i]
   this.length = MakeArray.arguments.length
   this.toString = arraytoString
   this.push = arraypush
   this.sort = arraysort
}
//Methoden
function arraytoString(){
   var returnstring = ""
   for (var i=0; i<this.length-1; i++)
      returnstring += this[i] + ","
   returnstring += this[this.length-1]
   return returnstring
}
function arraypush(){
   for (var i=0; i<arraypush.arguments.length; i++)
      this[this.length+i] = arraypush.arguments[i]
   this.length += arraypush.arguments.length
}
function arraysort(){
   var sortiert = false  //Überprüfung, ob sortiert
   while (!sortiert){
      sortiert = true
      for (var i=0; i<this.length-1; i++)
         if (groesser(this[i], this[i+1], arraysort.arguments[0])){
            sortiert = false
            hilfsvariable = this[i]
            this[i]=this[i+1]
            this[i+1] = hilfsvariable
         }
   }
}
function groesser(a, b, arg){
   if (!arg)
      return (a>b)
   else{
      var erg = eval(arg + "(\"" + a + "\", \"" + b + "\")")
      return (erg>0)
   }
}
// *** Das eigentliche Programm ***
//Hilfsvariablen für die Kartenbezeichnungen
var kartenname = new MakeArray("Zwei", "Drei", "Vier", "Fünf",
  "Sechs", "Sieben", "Acht", "Neun", "Zehn", "Bube", "Dame",
    "König", "As")
var farben = new MakeArray("Herz", "Karo", "Pik", "Kreuz");
//Initialisierung des Kartenarrays
var cards = new MakeArray()
for (var i=0; i<13; i++)
   for (var j=0; j<4; j++){
      karte = kartenname[i]+" "+farben[j]
      cards.push(karte)
   }
//Karten mischen
//Karten auf vier Personen verteilen
var hand1 = new MakeArray()
var hand2 = new MakeArray()
var hand3 = new MakeArray()
var hand4 = new MakeArray()
for (i=0; i<=12; i++)
   hand1.push(cards[i])
for (i=13; i<=25; i++)
   hand2.push(cards[i])
for (i=26; i<=38; i++)
   hand3.push(cards[i])
for (i=39; i<=51; i++)
   hand4.push(cards[i])
//Karten sortieren
hand1.sort("cardsort")
hand2.sort("cardsort")
hand3.sort("cardsort")
hand4.sort("cardsort")
//Sortierfunktion
function cardsort(a, b){
   var wert_a = a.substring(0, a.indexOf(" "))
   var wert_b = b.substring(0, b.indexOf(" "))
   var index_a = -1; var index_b = -1
   for (var i=0; i<kartenname.length; i++){
      if (kartenname[i]==wert_a)
         index_a = i
      if (kartenname[i]==wert_b)
         index_b = i
   }
   if (index_a>index_b) return 1
      else if (index_a<index_b) return -1
   var farbe_a = a.substring(a.indexOf(" ")+1, a.length)
   var farbe_b = b.substring(b.indexOf(" ")+1, b.length)
   return (farbe_a>farbe_b) ? 1 : 0
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Karten spielen mit JavaScript</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
function br() { return "<" + "BR" + ">" }
document.write("Hand 1: " + hand1.toString() + br())
document.write("Hand 2: " + hand2.toString() + br())
document.write("Hand 3: " + hand3.toString() + br())
document.write("Hand 4: " + hand4.toString() + br())
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 13.3  Die an vier Leute verteilten Karten, sortiert

13.3 Fragen & Aufgaben

1.	Geben Sie eine möglichst einfache nummerische Sortierfunktion an, die als Parameter an Array.sort() übergeben werden kann.
2.	Die Array-Methode pop() entfernt das letzte Element eines Arrays. Ergänzen Sie das MakeArray-Objekt um diese Methode. Es geht hier nur um das Entfernen des Elements, nicht um den Rückgabewert dieser Methode (beim Array-Objekt: das entfernte Element).
3.	Ergänzen Sie das MakeArray-Objekt um die Methode swap(i, j), die die Elemente mit den Indizes i und j miteinander vertauscht.
4.	Ergänzen Sie das MakeArray-Objekt um die (bereits bekannte) Methode splice(). Dabei brauchen nur die ersten beiden Parameter berücksichtigt werden, Sie brauchen also nichts anfügen.
5.	Ergänzen Sie das letzte Beispiel in diesem Kapitel um die Mischfunktion.

1    Denken Sie daran, dass Array-Indizes mit Null beginnen.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 14 Musik
			14.1 Plugins erkennen
			14.2 Zugriff auf Musikdateien

Kapitel 14 Musik

Musik ist heutzutage oft nur Lärm mit Copyright.

– Peter Holl

Die Einbindung von Musik auf Webseiten übt auf viele angehende Webmaster eine eigentümliche Faszination aus. Und so hört man auf vielen Webseiten ein grausames Gedudel, und nicht einmal mit jedem Browser. Auf professionellen Webseiten, insbesondere bei betont seriösen Anbietern, fehlen diese Effekte vollkommen. Hin und wieder sieht man eine Flash-Animation oder einen Shockwave-Film, aber von Musikeinbindung keine Spur. Es gibt hierfür zwei Gründe. Zum einen werden viele kommerzielle Webseiten der Informationen wegen angesurft. Grafiken und Animationen mögen da zwar das Auge locken und der Webseite ein appetitliches Aussehen bescheren, aber Musik hat hier nichts zu suchen – und wird auch schnell eintönig. Lesen Sie einmal einen mehrseitigen Text, und hören Sie dabei eine sich stets wiederholende Melodie (zum Beispiel ein Modern Talking-Album)! Der zweite Grund ist ein betriebswirtschaftlicher. Zwar gibt es ziemlich viele Grafiker, aber Komponisten sind ziemlich rar. Und geklaute Sounddateien findet man zwar auf privaten Seiten, auf kommerziellen Seiten in der Regel nicht.

Warum in diesem Buch das Thema dennoch behandelt wird? Nun, sparsam und vorsichtig eingesetzt, können auch Soundeffekte gut ankommen, vor allem dann, wenn Sie eh viele Multimedia-Elemente auf Ihrer Seite einsetzen. Außerdem erfahren Sie in diesem Kapitel en passant, wie Sie das Vorhandensein gewisser Plugins überprüfen können (nur beim Netscape Navigator): Wie so oft in diesem Buch haben Netscape und Microsoft unterschiedliche Techniken zur Soundeinbindung und -steuerung, und wie so oft werden am Schluss des Kapitels Strategien vorgestellt, das JavaScript-Programm browserunabhängig zu machen.

14.1 Plugins erkennen

Die Unterstützung von Musik ist kein in den Browsercode eingebautes Feature. Statt dessen verwenden beide Browser jeweils ein Plugin. Beim Netscape heißt dies LiveAudio, beim Internet Explorer ist es ActiveMovie Control oder der installierte Windows Media Player 6.4 oder 7.0. Der Internet Explorer kennt keine Plugins, deswegen kann man bei diesem Browser nicht mit JavaScript auf irgendwelche Plugins zugreifen. Beim Netscape Navigator ist das schon anders.

14.1.1 Zugriff auf Plugins

Alle Plugins werden beim Netscape Navigator im Array navigator.plugins[] gespeichert. Der Internet Explorer kennt dieses Objekt auch, es ist aber leer. Beim Zugriff gibt es also eine Fehlermeldung, aber man kann keine Werte abfragen. Jedes Element des navitator.plugins[]-Array ist ein Plugin-Objekt. Es hat die folgenden Eigenschaften:

	name: Name des Plugins
	description: Beschreibung des Plugins
	filename: Der lokale Dateiname des Plugins
	length: Anzahl der vom Plugin unterstützten MIME-Typen

Ein MIME-Type ist eine Art von Identifikator, die der Webserver den Daten, die er schickt, voranstellt. Bei HTML-Dateien ist dieser MIME-Typ text/html, bei .js-Dateien sollte es text/javascript sein.

Auf ein Plugin kann auf die folgende Art und Weise zugegriffen werden:

	navigator.plugins["Plugin-Name"]
	navigator.plugins[Index]

Wie immer beginnt die Zählung bei Null, das dritte Plugin hat also den Index Zwei.

Die folgende Schleife gibt alle Plugins aus, die in Ihrem Netscape Navigator installiert sind.

function tag(s) return "<"+s+">"
tag("TABLE BORDER=1");
for (var i=0; i<navigator.plugins.length; i++){
   document.write(tag("TR") + tag("TD"))
   document.write(navigator.plugins[i].name)
   document.write(tag("/TD"))
   document.write(tag("TD"))
   document.write(navigator.plugins[i].description)
   document.write(tag("/TD"))
   document.write(tag("TD"))
   document.write(navigator.plugins[i].filename)
   document.write(tag("/TD"))
   document.write(tag("TD"))
   document.write(navigator.plugins[i].length)
   document.write(tag("/TD")+tag("/TR"))
}
tag("/TABLE")

14.1.2 Zugriff auf MIME-Typen

Um auf MIME-Typen zuzugreifen, gibt es ebenfalls mehrere Möglichkeiten:

	navigator.plugins["Name"/Index]["Name"]
	navigator.plugins["Name"/Index][Index]
	navigator.mimeTypes["Name"/Index]

Ein mimeTypes-Objekt, also ein Element des Arrays, hat die folgenden Eigenschaften:

	type: Name des MIME-Typs
	description: Beschreibung des MIME-Typs
	suffixes: Mögliche Dateiendungen der Dateien des MIME-Typs
	enabledPlugin: Boolescher Wert, ob es für diesen MIME-Typen ein Plugin im Browser gibt

Mit einer ähnlichen Schleife wie oben lassen sich alle vom Browser akzeptierten MIME-Typen ausgeben; da dies jedoch in der Regel über hundert sind, sollte man dies nicht unbedingt ausprobieren. Vor allem der Netscape braucht beim Rendern von riesigen Tabellen sehr lange, und friert dabei manchmal sogar ein.

14.1.3 Refresh

Von besonderem Interesse ist noch die Methode plugins.refresh(). Hiermit wird die Liste aller Plugins aktualisiert und gegebenenfalls werden alle Plugins aktiviert. Nach der Installation eines Plugins kann man diese Methode aufrufen. Ein Boolescher Parameter muss übergeben werden. Das hat die folgenden Konsequenzen:

	navigator.plugins.refresh(false): Plugins, die normalerweise aktiv wären, werden nicht aktualisiert oder aktiviert.
	navigator.plugins.refresh(true): Die gesamte Plugin-Liste wird aktualisiert, und alle Plugins neu gestartet.

Die letztere Variante wird ebenfalls erreicht, wenn kein Parameter an die refresh()-Methode übergeben wird. Wenn Sie – beispielsweise über die Netscape’sche SmartUpdate-Technologie – ein Plugin installieren, und den Browser neu starten müssen, so wird der Benutzer, der das Plugin gerade installiert hat, nicht unbedingt auf Ihre Seite zurückkommen. Den Neustart können Sie sich aber wie gesagt sparen, wenn Sie navigator.plugins.refresh(true) verwenden.

Der Netscape Navigator hat einen Menübefehl Help • About plug-ins bzw. Hilfe • Über Plug-ins, der Ähnliches leistet. In Abbildung 14.1 finden Sie eine Beispielsausgabe.

Abbildung 14.1  Die Plugin-Anzeige des Netscape Navigator

14.2 Zugriff auf Musikdateien

Der Internet Explorer und Netscape Navigator bieten verschiedene HTML-Tags an, um Musikdateien in HTML-Seiten einzubinden. Ohne sich hier in allzu viele Details zu verlieren: Der kleinste gemeinsame Nenner ist der <EMBED>-Tag. Dieser wird vom Netscape Navigator ab Version 3 sowie im Internet Explorer ab Version 4 unterstützt. Wenn Sie auch beim Internet Explorer 3 Musik verwenden wollen, sollten Sie den <BGSOUND>-Tag verwenden, der aber nicht Thema dieses Kapitels ist.

Obwohl der <EMBED>-Tag von beiden Browsern unterstützt wird, ist die Implementierung der Browser leicht unterschiedlich. Im Folgenden werden einige Methoden aufgezeigt, die häufig benötigt werden, beispielsweise für das Starten und Anhalten der Musik. Außerdem wird aufgezeigt, wie die Musikunterstützung des Browsers mit JavaScript festgestellt werden kann.

14.2.1 Browsertest

Beim Internet Explorer ist das ActiveMovie Control, das für die Steuerung von Sounddateien zuständig ist, stets installiert, beim Netscape Navigator muss das LiveAudio-Plugin vorliegen (das aber bei der Standardinstallation mitinstalliert wird). Es haben sich die folgenden beiden Methoden durchgesetzt, um zu überprüfen, ob der Browser Soundwiedergabe unterstützt und um welchen Browserhersteller es sich hierbei handelt:

	Der (soundfähige) Internet Explorer liegt vor, wenn navigator.plugins existiert (wie erwähnt, es hat zwar keine Eigenschaften oder Methoden, aber das Objekt existiert, wenn die Unterstützung von ActiveX-Controls aktiviert ist) und document.all existiert (dann ist es ein Internet Explorer ab Version 4).
	Der (soundfähige) Netscape Navigator liegt vor, wenn navigator.plugins existiert und das LiveAudio-Plugin vorliegt. Man muss die Existenz von navigator.plugins überprüfen, um eine Fehlermeldung in der zweiten, direkten Plugin-Abfrage zu vermeiden. Aufgrund der Short Evaluation funktioniert das auch.

Fassen wir zusammen. Mit dem folgenden Code werden zwei Boolesche Variablen gesetzt, die angeben, ob ein soundfähiger Netscape Navigator oder Internet Explorer vorliegt:

var IE = (navigator.plugins && document.all)
var NN = (navigator.plugins&&navigator.plugins["LiveAudio"])

14.2.2 Soundsteuerung

Es würde an dieser Stelle zu weit führen, alle Eigenschaften und Methoden des LiveAudio-Plugins und des ActiveMovie Control aufzuführen. Im Alltagsgebrauch sind eh nur ein paar Funktionen nützlich, und diese finden Sie in Tabelle 14.1.

Tabelle 14.1  Die wichtigsten Funktionen zur Soundsteuerung im Überblick

Funktion	Netscape Navigator	Internet Explorer (ActiveMovie)	Internet Explorer (Windows Media Player)
Starten der Wiedergabe	play(true)	play()	play()
Pausieren der Wiedergabe	pause()	pause()	pause()
Stoppen der Wiedergabe	stop()	stop()	stop()
Lautstärke ändern	setvol(Lautstärke) ](Methode; aktueller Wert mit GetVolume())	volume (Eigenschaft)	volume (Eigenschaft)
Abspielstatus	IsReady() (Stop) IsPaused() (Pause) IsPlaying() (Wiedergabe)	currentState 0 = Stop, 1 = Pause, 2 = Wiedergabe	PlayState 0 = Stop, 1 = Pause, 2 = Wiedergabe (Version 6.4) 1 = Stop, 2 = Pause, 3 = Wiedergabe (Version 7.0)

14.2.3 Jukebox

Mit diesem Hintergrundwissen lässt sich nun eine einfache, browserunabhängige Jukebox programmieren. Wie oben beschrieben, wird der Browsertyp bestimmt. Man kann die Soundwiedergabe anhalten, pausieren und wieder starten sowie den aktuellen Status des <EMBED>-Elements auslesen. Ebenso kann die Lautstärke angepasst werden.

<HTML>
<HEAD>
<TITLE>Soundsteuerung mit JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
//globale Variablen
var IE, NN, musik
function init()
   IE = (navigator.plugins && document.all)
   NN = (navigator.plugins&&navigator.plugins["LiveAudio"])
   musik = document.jukebox
   zeigestatus()
function zeigestatus()
   var s = "unbekannt"
   if (NN)
      if (musik.IsReady())
         s = "Stop"
      if (musik.IsPaused())
         s = "Pause"
      if (musik.IsPlaying())
         s = "Wiedergabe"
   else if (IE)
      var stat = musik.currentState
      if (stat==0)
         s = "Stop"
      if (stat==1)
         s = "Pause"
      if (stat==2)
         s = "Wiedergabe"

   if (NN)
      s += " ("+musik.GetVolume()+")"
   else if (IE)
      s += " ("+musik.volume+")"
   document.forms[0].Soundstatus.value = s
function Stop()
   if (NN||IE)
      musik.stop()
      zeigestatus()

function Pause()
   if (NN||IE)
      musik.pause()
      zeigestatus()

function Start()
   if (NN)
      musik.play(true)
   else if (IE)
      musik.play()
   zeigestatus()
function Lauter()
   if (NN)
      musik.setvol(musik.GetVolume()+5)
   else if (IE)
      musik.volume += 5
   zeigestatus()
function Leiser()
   if (NN)
      musik.setvol(musik.GetVolume()-5)
   else if (IE)
      musik.volume -= 5
   zeigestatus()
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Jukebox</H3>
<EMBED NAME="jukebox" SRC="musik.mid" AUTOSTART="true"
  MASTERSOUND HIDDEN="true">
<FORM>
<INPUT TYPE="BUTTON" VALUE="Start" onClick="Start()">
<INPUT TYPE="BUTTON" VALUE="Stop" onClick="Stop()">
<INPUT TYPE="BUTTON" VALUE="Pause" onClick="Pause()">
<INPUT TYPE="BUTTON" VALUE="Lauter" onClick="Lauter()">
<INPUT TYPE="BUTTON" VALUE="Leiser" onClick="Leiser()">
<INPUT TYPE="TEXT" NAME="Soundstatus" SIZE="10"
  onFocus="this.blur()">
</FORM>
</BODY>
</HTML>

Abbildung 14.2  Die Jukebox in Aktion

Beachten Sie die interessanten Attribute des <EMBED>-Tags:

	NAME gibt den Bezeichner an, unter dem der Container mit JavaScript angesprochen werden kann.
	SRC gibt den Dateinamen der Sounddatei an. Wenn Sie mit ein paar MIDI-Files experimentieren wollen, durchsuchen Sie (wenn Sie mit Microsoft Windows arbeiten) mal das Windows-Verzeichnis nach Dateien mit der Endung .mid!
	AUTOSTART gibt an, ob die Sounddatei beim Laden der Seite sofort abgespielt werden soll ("true") oder nicht ("false"). Beim Netscape Navigator wird "true" angenommen, wenn nichts angegeben wird; beim Internet Explorer wird standardmäßig von "false" ausgegangen.
	HIDDEN gibt an, ob man eine Konsole sieht, die ebenfalls Schaltflächen zum Abspielen und Anhalten der Soundatei anbietet ("false") oder nicht ("true"). Standardmäßig wird der Wert "false" angenommen.
	Wenn das Beispiel unter Ihrem Netscape Navigator einfach nicht laufen will, überprüfen Sie bitte in den Einstellungen, ob Java aktiviert ist. Für Plugin-Steuerung benötigt der Netscape Navigator nämlich Java. Man kann übrigens mit navigator.javaEnabled() überprüfen, ob der Benutzer Java eingeschaltet hat (siehe//Kapitel »Java«).
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 15 Events
			15.1 Events mit dem Netscape Navigator
			15.2 Events mit dem Internet Explorer
			15.3 Events mit beiden Browsern
			15.4 Event-Handling im Netscape 6
			15.5 Fragen & Aufgaben

Kapitel 15 Events

Große Ereignisse werfen ihre Dementis voraus.

– Lothar Schmidt

Die Behandlung von Ereignissen, also die Reaktion auf Benutzereingaben oder aktionen, gestaltet sich bis jetzt noch ziemlich überschaubar. Es gibt Event-Handler, die in den entsprechenden HTML-Tags eingesetzt werden und bei Eintreten des entsprechenden Ereignisses eine JavaScript-Aktion ausführen (können). In diesem Kapitel wird dieses Konzept noch einmal behandelt. Es werden Erweiterungen daran in der JavaScript-Version 1.2 und eine alternative Methode vorgestellt, um Event-Handler zu setzen. Dann wird es erst richtig interessant: Sowohl Netscape als auch Microsoft haben für die Version 4 ihrer Browser das Event-Konzept erweitert und bieten ausgefeiltere Möglichkeiten an. Eine praxisnahe Anwendung dafür zu finden, fällt nicht immer leicht, aber beispielsweise können Tastatureingaben abgefangen und zum Teil auch erkannt werden. Im letzten Abschnitt dieses Kapitels werden dann Wege aufgezeigt, wie Sie Ihre Abfragen für beide Browsertypen funktionsfähig machen – aber erst ab Version 4, wohlgemerkt. Ganz am Schluss werfen wir noch einen kurzen Blick auf den brandneuen Netscape 6.

15.1 Events mit dem Netscape Navigator

Im Folgenden wird – der Einfachheit halber – auf Ereignisse mit möglichst simplen Aktionen reagiert, im Normalfall mit window.alert(). Das hat den Vorteil, dass man – bei diesem neuen Stoff – nicht den Überblick innerhalb eines längeren, ausführlicheren Beispiels verliert, sondern sich auf das Wesentliche konzentrieren kann.

Die bisherige Methode, auf ein Ereignis zu reagieren, bestand darin, einen HTML-Event-Handler dementsprechend zu setzen:

<HTML>
<HEAD>
<TITLE>Events</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function hamlet(){
   alert("To be, or not to be")
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="hamlet()">
<H3>Events mit Netscape</H3>
</BODY>
</HTML>

15.1.1 Neue Ereignisse

In JavaScript Version 1.2 wurden neue Ereignisse und dazugehörige Event-Handler eingeführt. Diese betreffen Maus- und Tastatureingaben.

	Bei einem Mausklick trat in den älteren Versionen nach dem Drücken und Loslassen der Maustaste das Ereignis click ein, und dann konnte mit dem Event-Handler onClick reagiert werden. Ab Netscape Navigator 4.0 wurde dieses Verfahren etwas verfeinert. Es gibt die zusätzlichen Ereignisse mousedown und mouseup, die eintreten, wenn die Maustaste gedrückt respektive wieder losgelassen wird. Ein Mausklick lässt also drei Ereignisse hintereinander eintreten, und zwar in dieser Reihenfolge:
	mousedown
	mouseup
	click

An folgendem Beispiel können Sie die Reihenfolge ausprobieren. Klicken Sie auf die Formular-Schaltfläche, und beobachten Sie, wie sich die Statuszeile verändert1 , wenn Sie die Schaltfläche anklicken und dann die Maustaste wieder loslassen.

<HTML>
<HEAD>
<TITLE>Neue Mausereignisse</TITLE>
</HEAD>
<BODY onLoad="window.status=''">
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" VALUE="Klick mich!"
  onMousedown="window.status+='[mousedown]'"
  onMouseup="window.status+='[mouseup]'"
  onClick="window.status+='[click]'">
</FORM>
</BODY>
</HTML>

Abbildung 15.1  Die neuen Mausereignisse

Ein weiteres neues Ereignis ist dblclick, das einen Doppelklick darstellt. Neu ist auch das Ereignis mousemove, das die Bewegungen der Maus erfasst. Wir werden später darauf zurückkommen.

Auch Tastatureingaben können abgefangen werden, dazu erfahren Sie später in diesem Kapitel mehr.

15.1.2 Ereignisse als Objekteigenschaften

Ab JavaScript Version 1.1, also Netscape Navigator 3, konnte man Event-Handler auch ohne HTML-Code besetzen. Kommen wir zu dem Code vom Anfang des Kapitels zurück:

<BODY onLoad="hamlet()">

	Dies kann – ab JavaScript 1.1 – auch folgendermaßen ausgedrückt werden:

window.onload=hamlet

	Hierbei sind zwei Dinge bemerkenswert. Zum einen fehlen die Klammern hinter hamlet; das liegt daran, dass kein Funktionsaufruf angegeben werden darf, sondern eine Funktionsreferenz, also ein Funktionsname ohne Klammern. Zum anderen erfolgt die Zuweisung anders: Da <BODY onLoad=""> beim Laden des Fensters ausgeführt wird, muss die onload-Eigenschaft des window-Objekts gesetzt werden. Ab Netscape Navigator 4.0 ist man in der Groß- und Kleinschreibung relativ frei, aber Netscape Navigator 3 besteht ausschließlich auf Kleinbuchstaben; deswegen werden und müssen wir uns auf die Kleinschreibung beschränken, können also kein window.ONLOAD oder Ähnliches verwenden.

Durch dieses Vorgehen gewinnt man an Flexibilität, da man den Event-Handler an jeder Stelle im Dokument setzen kann. Ebenso kann – wenn es die Applikation erfordert – der Event-Handler gelöscht werden:

window.onload = null

In diesem Fall ist das eher unsinnig, da das Ereignis load ohnehin nur einmal auftritt, beim Laden der Seite nämlich.

Das oben angeführte Beispiel mit den neuen Mausereignissen kann wie folgt äquivalent umgeschrieben werden:

<HTML>
<HEAD>
<TITLE>Neue Mausereignisse</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(){window.status += "[click]"}
function mup(){window.status += "[mouseup]"}
function mdown(){window.status += "[mousedown]"}
function init(){
   window.status = ''
   with (document.forms[0].elements[0])
      onclick = mclick
      onmouseup = mup
      onmousedown = mdown
}
window.onload = init
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" VALUE="Klick mich!">
</FORM>
</BODY>
</HTML>

Es ist hierbei sehr wichtig, dass die Funktion init() erst beim Eintreten des load-Ereignisses aufgerufen wird. Das Dokument muss vollständig geladen worden sein, denn davor existiert die Schaltfläche noch nicht, ihr können also auch keine Eigenschaften gegeben werden.

15.1.3 Ereignisse abfangen

Wie oben zu sehen, sind ein Ereignis und ein Event-Handler immer einem bestimmten Element zugewiesen. Die Funktion init() ist dem onLoad-Event-Handler des Fensters zugewiesen, die anderen Funktionen den mausbezogenen Event-Handlern der bestimmten Schaltfläche. Rein theoretisch kann es aber ganz geschickt sein, wenn nicht die Schaltfläche die Abarbeitung des Ereignisses übernimmt, sondern vielleicht das Fenster, das das »Oberobjekt« der Schaltfläche ist (die Schaltfläche kann als window.document.forms[0].elements[0] angesprochen werden). Dazu gibt es die Methode captureEvents(), mit der man festlegen kann, dass bestimmte Objekte Ereignisse abfangen, die in deren Unterobjekten auftreten. Als Parameter werden die zu überwachenden Ereignisse übergeben. Mit dem folgenden Befehl fängt das Objekt window alle click-Ereignisse in seinen Unterobjekten ab:

window.captureEvents(Event.CLICK)

Hierbei bezeichnet Event.CLICK das click-Ereignis, die Schreibweise (insbesondere das Ereignis in Großbuchstaben) ist verpflichtend. Das Event-Objekt wird in diesem Kapitel noch etwas ausführlicher behandelt.

Sollen mehrere Ereignisse überwacht werden, so werden diese – durch den |-Operator getrennt – angegeben. Der |-Operator steht für das bitweise Oder, was an dieser Stelle aber nicht sonderlich interessant ist; es kommt vielmehr darauf an, wie dieser Operator für die Ereignisbehandlung eingesetzt wird. Wenn das window-Objekt die Ereignisse click, mousedown und mouseup überprüfen soll, muss der folgende Befehl ausgeführt werden:

window.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP)

Alternativ kann man auch mehrere captureEvents()-Aufrufe hintereinander schalten, wenn man sich mit dem |-Operator nicht wohl fühlt (die Verwechslungsgefahr mit || ist recht groß).

Die Methode captureEvents() kann nicht nur beim window-Objekt eingesetzt werden, sondern auch beim document-Objekt und beim layer-Objekt (dieses Objekt wird in den DHTML-Kapiteln noch näher erläutert).

Natürlich kann man das frühe Abfangen von Ereignissen auch wieder ausschalten; hierzu dient die Methode releaseEvents(). Die folgenden Codezeilen heben sich gegenseitig auf:

window.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP)
window.releaseEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP)

15.1.4 Ereignisbehandlung

Wenn ein übergeordnetes Projekt Ereignisse abfangen soll, so muss man feststellen können, welches Ereignis wo eingetreten ist, um darauf reagieren zu können. Im Folgenden wird so etwas am bekannten Beispiel mit der Schaltfläche exemplarisch vorgeführt. Die Anwendung soll insofern erweitert werden, dass eine zweite Schaltfläche eingeführt wird, die auch mit Event-Handlern bestückt werden soll. Um Schreibarbeit zu sparen, soll die Ereignisbehandlung nicht direkt in dem HTML-Code für die Schaltflächen definiert werden, sondern »von oben« gesteuert werden.

Zunächst einmal muss man mit captureEvents() die Ereignisse an das window-Objekt (zumindest in diesem Beispiel) binden. Sodann muss man für die Ereignisse entsprechende Verarbeitungsfunktionen erstellen und zuweisen. Das Beispiel sieht dann ungefähr folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>Neue Mausereignisse</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(e) {}
function mup(e) {}
function mdown(e) {}
window.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP)
window.onclick = mclick
window.onmousedown = mdown
window.onmouseup = mup
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1">
<INPUT TYPE="BUTTON" NAME="Button2" VALUE="Button2">
</FORM>
</BODY>
</HTML>

Beachten Sie die leeren Funktionsaufrufe:

function mclick(e) {}
function mup(e) {}
function mdown(e) {}

Anscheinend wird ein Parameter e übergeben, doch woher kommt dieser? Wenn man Event-Handler mittels JavaScript-Eigenschaften setzt, kann man ja keine Parameter übergeben, da die Klammern fehlen. In diesem Fall wird jedoch das Ereignis selbst, eine Instanz des Objekts Event, an die Behandlungsfunktion übergeben. Die Bezeichnung e ist hierbei zwar frei wählbar, das e hat sich aber mittlerweile in Programmiererkreisen durchgesetzt. Solche ungeschriebenen Gesetze haben den Vorteil, dass man fremden Code auch ohne ausreichende Dokumentation recht schnell verstehen kann – unter Umständen.

Das Event-Objekt hat eine ganze Reihe von Eigenschaften, die in der Referenz vollständig vorgestellt werden. Für unsere Zwecke verwenden wir zunächst die Folgenden:

	target: Das Ziel des Ereignisses, also das Objekt, für das das Ereignis bestimmt war. Im Gegensatz zu manchen Quellen gibt der Netscape Navigator 4.x eine Objektreferenz zurück und keine Zeichenkette.
	type: Die Art des Ereignisses als Zeichenkette

Sie sehen, dass es eigentlich völlig unnötig war, gleich drei Funktionen, mclick(), mdown() und mup(), zu verwenden, da sich der Typ des eingetretenen Ereignisses bestimmen lässt. Zur Übung können Sie diesem Missstand ja einmal beheben.

Die drei Behandlungsfunktionen werden nun so umgeschrieben, dass in der Statuszeile nicht nur der Name des Ereignisses angegeben wird, sondern auch der Name des Objekts, für das dieses Ereignis bestimmt war. Da man mit der Eigenschaft target eben dieses Objekt erhält, kann man mit der Objekteigenschaft name den gewünschten Wert erhalten.

function mclick(e){window.status += "[click@"+e.target.name+"]"}
function mup(e){window.status += "[mouseup@"+e.target.name+"]"}
function mdown(e){window.status += "[mousedown@"+e.target.name+"]"}

Abbildung 15.2  Die geklickte Schaltfläche wird identifiziert.

15.1.5 Ereignisse umleiten

Es ist ab dem Netscape Navigator 4 nicht nur möglich, Ereignisse abzufangen und abzuarbeiten, bevor sie bei dem eigentlichen Zielobjekt eintreffen; man kann die Ereignisse auch auf andere Objekte umleiten. Beispielsweise ist es möglich, ein click-Ereignis einer Schaltfläche auf einen Link umzuleiten. Wenn das click-Ereignis bei einem Link eintrifft, wird dieser Link aktiviert (das muss natürlich noch programmiert werden). Die entsprechende Methode heißt handleEvent(), und als Parameter muss das Ereignis explizit übergeben werden.

Wird im folgenden Code die erste Schaltfläche angeklickt, so wird das Ereignis an die Methode handleEvent() des Links übergeben (alle Links eines Dokuments werden im Array document.links[] gespeichert), und die Website des Galileo Verlags wird aufgerufen. Wird dagegen die zweite Schaltfläche angeklickt, so wird wie gewöhnlich die Statuszeile geändert.

<HTML>
<HEAD>
<TITLE>Neue Mausereignisse</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(e){
   if (e.target.name=="Button1")
      document.links[0].handleEvent(e)
   else
      window.status += "[click@"+e.target.name+"]"
}
function mup(e){window.status += "[mouseup@"+e.target.name+"]"}
function mdown(e){window.status += "[mousedown@"+e.target.name+"]"}
window.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP)
window.onclick = mclick
window.onmousedown = mdown
window.onmouseup = mup
function galileo(){location.href = "http://www.galileo-press.de"}
function init(){
   document.links[0].onclick = galileo
   window.status = ""
}
window.onload = init
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1">
<INPUT TYPE="BUTTON" NAME="Button2" VALUE="Button2">
</FORM>
<HR>
<A HREF="http://www.galileo-press.de">Galileo Press</A>
</BODY>
</HTML>

15.1.6 Ereignisse durchleiten

Ein Problem hat das Netscape-System noch. Wenn dem window-Objekt ein Ereignis zugeordnet wird (durch captureEvents()), aber dieses Objekt damit nichts tut, ist das Ereignis verloren oder muss manuell an ein anderes Objekt weitergeleitet werden (mit handleEvent()). Das muss aber noch nicht das Ende der Fahnenstange sein; und in der Tat gibt es noch eine weitere Methode, routeEvent(). Dieser wird auch das Ereignis als Parameter übergeben, aber man kann mit ihr das Ereignis nicht an ein fixes Objekt weitergeben, sondern es in der Hierarchie nach unten durchreichen. Wird also eine Schaltfläche angeklickt, das click-Ereignis vom window-Objekt abgefangen und dann routeEvent(e) aufgerufen, so wird zuerst nachgeschaut, ob das document-Objekt (das Nächste in der Hierarchie) einen Event-Handler für das Ereignis (hier: click) hat. Falls nicht, so wird – in diesem Beispiel – zunächst das Formular überprüft, aber das hat beim Netscape Navigator ja ohnehin kein click-Ereignis. Zuletzt wird die Schaltfläche selbst überprüft.

Dieses Vorgehen hat seine Vorteile. So kann man explizit prüfen, wo ein Ereignis herkommt, und wenn man damit nichts anfangen kann, wird es einfach weitergereicht. Im folgenden Beispiel, der nächsten Erweiterung unseres Codes, wird dieses Verfahren an zwei Stellen eingesetzt.

	Wenn der Benutzer irgendwo in das Fenster klickt, tritt auch ein click-Ereignis auf, und wird vom window-Objekt (dank captureEvents()) abgefangen. Mitunter erscheint dann Müll in der Statuszeile. Dies wird verhindert, indem überprüft wird, ob der Name des aufrufenden Objekts mit "Button" anfängt.
	Klickt der Benutzer auf den Link, wird auch nichts in die Statuszeile geschrieben, und das Ereignis wird direkt weitergereicht, sodass das Ziel des Links auch angezeigt wird, ohne dass groß mit handleEvent() umgeleitet werden muss.

<HTML>
<HEAD>
<TITLE>Neue Mausereignisse</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(e){
   if (e.target.name.indexOf("Button")==0)
      window.status += "[click@"+e.target.name+"]"
   routeEvent(e)
}
function mup(e){window.status += "[mouseup@"+e.target.name+"]"}
function mdown(e){window.status += "[mousedown@"+e.target.name+"]"}
window.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP)
window.onclick = mclick
window.onmousedown = mdown
window.onmouseup = mup
function galileo(){location.href = "http://www.galileo-press.de"}
function init(){
   document.links[0].onclick = galileo
   window.status = ""
}
window.onload = init
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1">
<INPUT TYPE="BUTTON" NAME="Button2" VALUE="Button2">
</FORM>
<HR>
<A HREF="http://www.galileo-press.de" >Galileo Press</A>
</BODY>
</HTML>

15.1.7 Tastatureingaben

Für Tastatureingaben wurden mit JavaScript 1.2 ebenfalls neue Ereignisse eingeführt. Auf einen Tastendruck tritt das Ereignis keypress ein. Wie bei einem Mausklick besteht auch dieser Tastendruck aus zwei Teilen, und zwar keydown (Taste drücken) und keyup (wieder loslassen).

Bei Tastatureingaben gewinnt das Ereignis an besonderer Bedeutung. In der Eigenschaft which steht der ASCII-Code des Zeichens. So kann ein einfaches Ratespiel implementiert werden. Der Benutzer kann in das folgende Texteingabefeld beliebige Buchstaben eingeben. Nach jedem Tastendruck wird der eingegebene Buchstabe mit dem zu erratenden Buchstaben verglichen. Hat der Benutzer richtig geraten, so wird dies ausgegeben. Bei jedem Rateversuch wird ein Zähler um eins erhöht, denn man kann nicht unendlich oft raten, sondern (bei uns) maximal zehnmal. Beachten Sie, wie im folgenden Code die Funktion immer mit return true verlassen wird, außer wenn das Ratespiel zu Ende ist, dann endet die Funktion mit return false. Der Grund ist Folgender: Wie Sie bereits an diversen Beispielen in anderen Kapiteln gesehen haben, wird die weitere Abarbeitung des Ereignisses im Browser abgebrochen, wenn ein Event-Handler mit return false endet. In diesem Fall soll verhindert werden, dass die zusätzlich eingetippten Buchstaben im Eingabefeld erscheinen.

<HTML>
<HEAD>
<TITLE>Tastatureingaben mit dem Netscape Navigator</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var versuche = 0
var geheim = "Q"  //Geheimes Zeichen
function taste(e){
   versuche = 0
   //Umwandlung ASCII-Code in Zeichen
   var zeichen = String.fromCharCode(e.which)
   if (zeichen.toUpperCase()==geheim){
      alert("Richtig geraten, mit genau " + versuche + " Versuchen")
      versuche = 10
   }
   return (versuche<10)
}
document.captureEvents(Event.KEYPRESS)
document.onkeypress = taste
//--></SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="TEXT" SIZE=10>
</BODY>
</HTML>

Ein Hinweis noch am Rande: Mit einer einzigen zusätzlichen Zeile kann man zumindest verhindern, dass auf älteren Netscape-Browsern und auf allen Versionen des Microsoft Internet Explorer keine Fehlermeldung ausgegeben wird. Nicht vorhandene Eigenschaften kann man ohne Ärger setzen, die einzige Gefahrenquelle ist die folgende Zeile:

document.captureEvents(Event.KEYPRESS)

Mit einem Trick, der unter anderem schon aus dem Kapitel »Images« bekannt ist, kann man das verhindern:

if (document.captureEvents)
   document.captureEvents(Event.KEYPRESS)

15.2 Events mit dem Internet Explorer

Wie bereits eingangs erwähnt, hat auch der Internet Explorer mit seiner Version 4 ein neues Ereignismodell eingeführt. Leider ist dieses Modell fast vollständig inkompatibel zu der Variante von Netscape, aber gegen Ende dieses Kapitels werden wir uns auch dieses Problems annehmen. Galten alle vorherigen Beispiele in diesem Kapitel nur für den Netscape Navigator 4 oder höher, so funktionieren die folgenden Beispiele nur ab dem Internet Explorer Version 4. Zur Vereinigung dieser beiden Browser gelangen wir wie gesagt später.

Ganz allgemein kann man sagen, dass das DOM (Document Object Model) des Internet Explorer ausgereifter ist als die Netscape-Variante. So kann beispielsweise jeder Tag mit Event-Handlern bestückt werden, beispielsweise auch <P>, <I> und <B>. Um aber am Ende browser-unabhängig zu bleiben, sollte man nur die Elemente mit Event-Handlern bestücken, die auch der Netscape Navigator mit einer Ereignisbehandlung versehen kann.

15.2.1 Neue Ereignisse

Auch der Internet Explorer hat in Version 4 neue Ereignisse eingeführt. Für Mausbewegungen sind das mousedown, mouseup und dblclick; bei der Tastatur handelt es sich um keydown, keyup und keypress. Bei der Bedeutung dieser Ereignisse gibt es keinen Unterschied zu Netscape, sodass die Ereignisse an dieser Stelle nicht noch einmal ausführlich erklärt werden. Der Unterschied liegt in der Behandlung der Maus- und Tastatureingaben, aber dazu später mehr.

15.2.2 Ereignisse als Objekteigenschaften

	Auch der Internet Explorer 4 kann wie der Netscape Navigator 4 statt HTML-Event-Handlern JavaScript-Objekteigenschaften benutzen. Das Beispiel von oben kann also unverändert wieder verwendet werden:

<HTML>
<HEAD>
<TITLE>Events</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function hamlet(){
   alert("To be, or not to be")
}
window.onload = hamlet
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Events mit dem Internet Explorer</H3>
</BODY>
</HTML>

15.2.3 Spezielle Skripten

Es gibt beim Internet Explorer eine spezielle Möglichkeit, Event-Handler zu erzeugen. Dazu verwendet man ein gewöhnlichen <SCRIPT>-Tag genommen, und setzt die Parameter EVENT und FOR. Ersterer enthält den Namen des Event-Handlers (beispielsweise onload oder onclick), Letzterer den Identifikator des Objekts oder HTML-Elements, für das der Event-Handler eingesetzt werden soll. In der Praxis sieht das folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>Spezielle Skripten</TITLE>
<SCRIPT LANGUAGE="JavaScript" EVENT="onclick" FOR="Button1"><!--
window.status = "Schaltfläche gedrückt!"
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Spezielle Skripten</H3>
<FORM>
<INPUT TPYE="BUTTON" NAME="Button1" VALUE="Klick mich">
</FORM>
</BODY>
</HTML>

So schön die Idee auch ist, in der Praxis ist dieses Vorgehen völlig verfehlt. Der Internet Explorer 3 sowie alle Netscape-Versionen ignorieren die Parameter EVENT und FOR des <SCRIPT>-Tags und führen die Befehle darin schon beim Laden der Seite aus. Aus diesem Grund werden Sie die obige Methode nur auf schlechten Seiten finden, und auch das nur äußerst selten.

15.2.4 Ereignisse abfangen

Beim Netscape Navigator kann man mit captureEvents() und release Events() Ereignisse abfangen, die in Unterobjekten auftreten. Das liegt daran, dass beim Netscape Navigator Ereignisse in der Regel nur an das Objekt weitergeleitet werden, für das das jeweilige Ereignis bestimmt ist. Beim Internet Explorer funktioniert es etwas anders: Tritt bei einem Objekt ein Ereignis auf und ist dazu kein Ereignis-Handler definiert, so wird zum überordneten Objekt weitergegangen und nachgeschaut, ob zu diesem vielleicht ein Event-Handler definiert ist. Um auf das in diesem Kapitel schon öfter verwendete Formularbeispiel zurückzukommen: Im folgenden Code werden alle Mausklicks in das Dokument abgefangen – also insbesondere auch die Klicks auf eine Schaltfläche:

<HTML>
<HEAD>
<TITLE>Ereignisse mit dem Internet Explorer</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(){
   window.status += "[Mausklick]"
}
document.onclick = mclick
//--></SCRIPT>
</HEAD>
<BODY onLoad="window.status=''">
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1">
</FORM>
</BODY>
</HTML>

Auch für die Methode releaseEvents() gibt es eine äquivalente Anweisung – die Objekteigenschaft muss einfach auf null gesetzt werden:

document.onclick = null

15.2.5 Bubbling

Der zuvor skizzierte Ablauf beim Eintreten eines Ereignisses wird nun noch etwas genauer dargestellt. Tritt bei einem Objekt ein Ereignis auf, so wird bei diesem Objekt und dann nacheinander bei allen übergeordneten Objekten nachgeschaut, ob einer der beiden folgenden Fälle eintritt:

	Es gibt einen Event-Handler, und dieser wird mit return false abgeschlossen.
	Man ist beim obersten Objekt angelangt, dem document-Objekt.

Wenn man das oben dargestellte Programm leicht modifiziert bzw. ergänzt, kann man diesen Effekt sehr gut beobachten:

<HTML>
<HEAD>
<TITLE>Ereignisse mit dem Internet Explorer</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(){
   window.status += "[Mausklick]"
}
function buttonclick(){
   window.status += "[Buttonclick]"
}
document.onclick = mclick
//--></SCRIPT>
</HEAD>
<BODY onLoad="window.status=''">
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1"
onClick="buttonclick()">
</FORM>
</BODY>
</HTML>

Wenn Sie das Skript ausführen, und auf die Schaltfläche klicken, werden sowohl die Funktionen buttonclick() als auch mclick() aufgerufen.

Endet jedoch buttonclick() mit return false, so wird mclick() nicht mehr ausgeführt, wenn auf die Schaltfläche geklickt wird:

<HTML>
<HEAD>
<TITLE>Ereignisse mit dem Internet Explorer</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(){
   window.status += "[Mausklick]"
}
function buttonclick(){
   window.status += "[Buttonclick]"
   return false
}
document.onclick = mclick
//--></SCRIPT>
</HEAD>
<BODY onLoad="window.status=''">
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1"
  onClick="buttonclick()">
</FORM>
</BODY>
</HTML>

Abbildung 15.3  Die neuen Mausereignisse

Das hierarchische Vorgehen von unten nach oben nennt man im Englischen »Bubbling«, weil das Ereignis wie eine Blase (bubble) nach oben steigt.

15.2.6 Das Event-Objekt

Schon im Abschnitt über den Netscape Navigator wurde das Event-Objekt vorgestellt. Die gute Nachricht: Beim Internet Explorer verhält sich dieses Objekt recht ähnlich. Die schlechte Nachricht: Es gibt ganz am Anfang einen entscheidenden Unterschied – Kompatibilität adé! Während beim Netscape Navigator das aktuelle Ereignis als Parameter an den Event-Handler übergeben wird, ist das beim Internet Explorer nicht so – es ist nicht einmal nötig. Auf das aktuelle Ereignis kann mit window.event oder einfach nur mit event zugegriffen werden.

Auch hier gibt es wieder die Eigenschaft type, die die Art des Ereignisses als Zeichenkette angibt (z. B. "load" oder "click"). Nur event.target gibt es nicht mehr, beim Internet Explorer heißt diese Eigenschaft srcElement und enthält (wie target beim Netscape Navigator) eine Referenz auf das Objekt, für das das Ereignis bestimmt war.

	Beachten Sie auf jeden Fall, dass beim Netscape Navigator Event mit großem E geschrieben wird, beim Internet Explorer mit kleinem e.
Abbildung 15.4  Die geklickte Schaltfläche wird identifiziert.

Im folgenden Beispiel wird der NAME-Parameter derjenigen Schaltfläche angegeben, die geklickt worden ist:

<HTML>
<HEAD>
<TITLE>Ereignisse mit dem Internet Explorer</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mclick(){
   window.status +=  "["+event.type+"@"+event.srcElement.name+"]"
}
document.onclick = mclick
//--></SCRIPT>
</HEAD>
<BODY onLoad="window.status=''">
<H3>Neue Mausereignisse</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Button1">
<INPUT TYPE="BUTTON" NAME="Button2" VALUE="Button2">
</FORM>
</BODY>
</HTML>

Das Prinzip des Event-Bubblings kann nicht nur generell abgeschaltet werden – etwa durch ein return false – sondern auch explizit für genau ein Ereignis. Dazu verwenden Sie das folgende Kommando:

event.cancelBubble = true

15.3 Events mit beiden Browsern

Im letzten Abschnitt dieses Kapitels werden noch kurz Strategien vorgestellt, wie Sie Ihre Skripten auf beiden Browsern ohne Fehler benutzen können – vielleicht auf älteren Browsern nicht mit der vollen Funktionalität, aber immerhin ohne Fehlermeldungen. Außerdem werden kurz die Unterschiede bei der Abfrage von gedrückten Tastaturtasten und Maustasten bei den beiden »großen« Browsern beleuchtet.

15.3.1 Browser-Unabhängigkeit

Im Folgenden sollen einige allgemeine Konzepte vorgestellt werden, die bei der fortgeschrittenen, browserunabhängigen Ereignisbehandlung von Nutzen sein können.

Netscape oder nicht?

In Sachen Ereignis fällt es ziemlich leicht, den Netscape Navigator vom Internet Explorer zu unterscheiden. Sie verwenden dazu die Objektüberprüfung, die schon im Kapitel »Images« nützlich war:

if (window.Event)
   //Code für den Netscape Navigator 4
else
   //Code für den Internet Explorer 4

Ereignisse abfangen

Wie bereits erwähnt, kennt der Internet Explorer die Methode capture Events() nicht; durch das Bubbling-Prinzip ist sie ja auch nicht nötig, da Ereignisse nach oben weitergereicht werden. Soll etwa ein Mausklick abgefangen werden, so kann man sich mit folgendem Code behelfen:

function mclick(){
   window.status += "[Mausklick]"
}
if (window.Event)
   document.captureEvents(Event.MOUSEUP)
document.onclick = mclick

Denken Sie daran, dass der Internet Explorer beim document-Objekt aufhört und nicht mehr weiter nach oben gehen kann; Folgendes wäre also falsch:

if (window.Event)
   window.captureEvents(Event.MOUSEUP)
window.onclick = mclick

Ereigniseigenschaften

Wie bereits angedeutet, gibt es bei der Abfrage von Ereignissen Unterschiede zwischen den beiden Browsern, angefangen von der Übergabe als Parameter bis hin zur Schreibweise. Auch hier kann man sich wieder mit einer Objektüberprüfung behelfen:

function mclick(e){
   var ev = (window.Event) ? e : window.event
   window.status += "["+ev.type+"]"
}
if (window.Event)
   document.captureEvents(Event.MOUSEUP)
document.onclick = mclick

Beim Netscape Navigator wird auf den Parameter e zugegriffen, beim Internet Explorer auf window.event (oder event). Die Eigenschaft type ist bei beiden Browsern identisch, kann also problemlos verwendet werden. Bei dem Ziel des Ereignisses ist das etwas aufwendiger, man benötigt eine eigene Anweisung:

function mclick(e){
   var ev = (window.Event) ? e : window.event
   var ziel = (window.Event) ? ev.target : ev.srcElement
   window.status += "["+ev.type+"@"+ziel.name+"]"
}
if (window.Event)
   document.captureEvents(Event.MOUSEUP)
document.onclick = mclick

15.3.2 Benutzereingaben

In den vorherigen Abschnitten wurden Tastatureingaben und Mausklicks nur eher stiefmütterlich behandelt; beispielsweise wurden Sondertasten wie etwa (Alt) und (Strg) nicht erwähnt. Das soll sich an dieser Stelle ändern. Zwar unterscheiden sich auch hier die beiden Browser, aber inzwischen sollten Sie so abgehärtet sein, dafür eine Lösung zu finden.

Mausklicks

PC-Mäuse haben zwei oder drei Tasten. Da ist es doch interessant herauszufinden, welche dieser Tasten gedrückt worden ist. Bevor Sie sich irrwitzige Anwendungsmöglichkeiten ausdenken, eine kleine Warnung: Beispielsweise ruft die rechte Maustaste ein Kontextmenü auf, das Ereignis tritt (für den Browser) also gar nicht ein. Viele Maustreiber belegen die mittlere Maustaste mit einem Doppelklick, und damit ist die Taste für den differenzierten Einsatz auch nicht sonderlich geeignet.

Beim Netscape Navigator erhält man die Nummer der gedrückten Maustaste2  aus der which-Eigenschaft des aufgetretenen Ereignisses. Beim Internet Explorer dagegen gibt es hierfür eine gesonderte Eigenschaft, und zwar die Eigenschaft button des Ereignisses.

<HTML>
<HEAD>
<TITLE>Maustasten</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function taste(e){
   if (window.Event)
      var maustaste = e.which
   else
      var maustaste = e.button

   window.status += "[geklickt:" + maustaste + "]"
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="document.forms[0].elements[0].onclick=taste;
  window.status=''">
<H3>Maustasten</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Klick mich">
</FORM>
</BODY>
</HTML>

Tasten

Wie Sie bereits gesehen haben, erhält man den ASCII-Code beim Netscape Navigator aus der which-Eigenschaft des Ereignisses; beim Internet Explorer gibt es wieder eine eigene Eigenschaft, nämlich keyCode. Bei verschiedenen Plattformen gibt es hin und wieder Bugs in der Umsetzung, die aber mit der Methode String.fromCharCode() zusammenhängen. Bei manchen Internet Explorer-Versionen für den Macintosh werden einige seltenere Zeichen falsch zurückgegeben. Verlassen Sie sich im Zweifel also auf den ASCII-Code; im Produktionsbetrieb können Sie dennoch immer auf fromCharCode() zurückgreifen.

<HTML>
<HEAD>
<TITLE>Tastatur</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function taste(e){
   if (window.Event)
      var tastatur = e.which
   else
      var tastatur = e.keyCode

   window.status += "[getippt:" +
     String.fromCharCode(tastatur) + "]"
//--></SCRIPT>
</HEAD>
<BODY onLoad="document.forms[0].elements[0].onclick=taste;
  window.status=''">
<H3>Tastatur</H3>
<FORM>
<INPUT TYPE="TEXT" NAME="TEXT1">
</FORM>
</BODY>
</HTML>

Sondertasten

Mit den Sondertasten verhält es sich vom Prinzip her ähnlich wie mit Tastatureingaben und Mausklicks. Während beim Netscape Navigator möglichst viel in eine Eigenschaft oder Variable gepackt worden ist (ressourcensparend), kann man beim Internet Explorer explizit auf eine bestimmte Eigenschaft pro Sondertaste zugreifen (benutzerfreundlich). Eine Einschränkung gibt es jedoch. Beim Netscape Navigator können die Tasten (Alt), (Strg), (Umschalt) und (Meta) (die (Windows)-Taste) abgefragt werden, beim Internet Explorer lediglich (Alt), (Strg) und (ª). Die (Control)-Taste, das Macintosh-Äquivalent zur (Strg)-Taste, kann beim Macintosh-IE 4 ebenfalls nicht abgefragt werden.

Anstelle von langen Erklärungen nachfolgend ein selbsterklärendes Beispiel. Während beim Internet Explorer einzelne Eigenschaften abgefragt werden, muss man beim Netscape Navigator wieder eine bitweise Operation, diesmal UND (&) verwenden.

<HTML>
<HEAD>
<TITLE>Sondertasten</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function taste(e){
   if (window.Event){//Netscape
      window.status += "["
      if (e.modifiers & Event.ALT_MASK)
         window.status += "Alt"
      if (e.modifiers & Event.CONTROL_MASK)
         window.status += "Strg"
      if (e.modifiers & Event.SHIFT_MASK)
         window.status += "Umschalt"
      if (e.modifiers & Event.META_MASK)
         window.status += "Meta"
      window.status += "]"
  } else{//IE
      window.status += "["
      if (event.altKey)
         window.status += "Alt"
      if (event.ctrlKey)
         window.status += "Strg"
      if (event.shiftKey)
         window.status += "Umschalt"
   }
}
//--></SCRIPT>
</HEAD>
<BODY onload="document.forms[0].elements[0].onclick=taste;
  window.status=''">
<H3>Sondertasten</H3>
<FORM>
<INPUT TYPE="BUTTON" NAME="Button1" VALUE="Klick mich!">
</FORM>
</BODY>
</HTML>

Abbildung 15.5  Auch gedrückte Sondertasten können abgefragt werden.

Testen Sie dieses Programm, indem Sie ein paar der Sondertasten gedrückt halten und dann mit der Maus auf die Schaltfläche klicken.

15.4 Event-Handling im Netscape 6

Die Ereignisbehandlung im neuen Netscape 6 ist eine Mischung aus den Konzepten des Netscape Navigator 4.x und des Internet Explorer ab Version 4. Während der Netscape Navigator ein Ereignis nur beim »Eintauchen« in eine Website abfangen kann (mit captureEvent), stößt der Internet Explorer auf dasselbe Ereignis, wie es via Bubbling nach oben steigt. Der Netscape 6 versteht beide Richtungen, die Ansteuerung ist identisch.

An einer Stelle mussten sich die Softwarearchitekten von Netscape jedoch entscheiden: Welches Modell wählen wir für das Ereignis-Objekt? Man entschied sich für die Netscape-Variante: An jeden Ereignis-Handler wird eine Variable übergeben (wird meistens im Funktionskopf mit e bezeichnet), auf deren Eigenschaften (z. B. e.target etc.) im Funktionsrumpf zugegriffen werden kann. Sie sehen also: Wenn Sie das Netscape-Konzept erst einmal begriffen haben, können Sie auch für Netscape 6 programmieren.

15.5 Fragen & Aufgaben

1.	Was ist der prinzipielle Unterschied bei der Ereignisbehandlung zwischen Netscape Navigator und dem Microsoft Internet Explorer?
2.	Aus welchen Teilereignissen besteht das dblclick-Ereignis? Geben Sie ein Testprogramm an, um genau dies herauszufinden.
3.	Was ist der Unterschied zwischen handleEvent() und routeEvent()?
4.	Welche drei (!) Möglichkeiten gibt es, um die »Ereignisdurchreichung« (Bubbling) beim Internet Explorer abzubrechen?
5.	Erstellen Sie eine HTML-Seite mit drei Schaltflächen. Jede Schaltfläche ist mit einer URL beschriftet. Auf Mausklick soll genau diese URL geladen werden. Der Code darf nur mit Browsern ab Versionsnummer 4 funktionieren, verwenden Sie keine HTML-Event-Handler!
6.	Das letzte Beispiel in diesem Kapitel führt beim Netscape Navigator 3 zu einem Fehler. Warum ist das so, und wie kann man das mit minimalem Aufwand beheben (indem man ein paar Zeichen ändert)?

1    Warum haben wir wohl die Statuszeile zur Ausgabe verwendet, und nicht ein Alert–Fenster?

2    Die linke, primäre Maustaste hat die Nummer 1; bei Mäusen für Linkshänder hat die rechte Maustaste die Nummer 1.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 16 DHTML I: Netscape
			16.1 Grundlagen
			16.2 Beispiele
			16.3 Fragen & Aufgaben

Kapitel 16 DHTML I: Netscape

Avantgardisten sind Leute, die nicht wissen,

wo sie hinwollen, aber als erste dasein möchten.

- Verfasser unbekannt

Allein die Erwähnung des Begriffs DHTML lässt die Augen von vielen Leuten im Web-Bereich leuchten und steigert die Auflage von vielen Zeitschriften. Doch was ist DHTML überhaupt? Die Abkürzung steht für Dynamic HTML, doch handelt es sich hierbei um eine HTML-Erweiterung oder nur um neue JavaScript-Befehle? Wenn Sie in der Marketingabteilung einer Web-Agentur nachfragen, bekommen Sie mit ziemlicher Sicherheit eine weitläufige Erklärung, die diese Technik wahlweise als »Stein der Weisen« oder »Ei des Kolumbus« preist. Ziel dieses Kapitels – und der drei folgenden – soll es sein, dass Sie ein Gefühl dafür bekommen, was man mit DHTML machen kann. Eine vollständige Abhandlung des Themas, inklusive einer Auflistung aller Bugs – denn die Technologie ist von den beiden großen Browsern teilweise ziemlich schlampig umgesetzt worden – werden Sie hier schon allein aus Platzgründen nicht finden. Wenn Sie sich aber den Katalog von Galileo Press anschauen, werden Sie einen interessanten Titel finden, der sich ausschließlich mit DHTML befasst – aber profunde JavaScript-Kenntnisse voraussetzt.

	In diesem Kapitel wird das Thema DHTML aus der Sicht des Netscape-Entwicklers betrachtet. Hierbei wird das Augenmerk auf Netscape 4.x gelegt. Der Netscape Navigator 3 unterstützt nicht die ganze Funktionalität, und beim Netscape Navigator 6, Codename »Gecko«, nähert er sich dem Konzept des Internet Explorer an. Solange aber der Netscape Navigator 4 eine große Verbreitung findet – was noch lange Zeit so sein wird – kann man auch explizit für diesen entwickeln. Im folgenden Kapitel wird dann die DHTML-Unterstützung des Internet Explorer 4 (und 5) betrachtet; dann gehen wir auf den Netscape 6 ein, und stellen schließlich Strategien vor, um DHTML-Anwendungen browser-unabhängig zu gestalten.

16.1 Grundlagen

Wie schon in der Einleitung angedeutet wurde, ist nicht immer ganz leicht zu verstehen, was mit DHTML gemeint ist. In diesem Abschnitt wird der Versuch unternommen, eine Begriffsbestimmung zu liefern, und die notwendigen (theoretischen) Hintergründe zu liefern. Außerdem werden die entsprechenden HTML-Tags für den Netscape Navigator vorgestellt.

16.1.1 Begriffsbestimmung

Was ist DHTML? Jeder Entwickler und jeder Browser-Hersteller gibt eine andere Definition. Da ist von viel Dynamik die Rede und von der Erfüllung aller Träume von Webentwicklern. Ich bevorzuge dagegen eine etwas einfachere, flapsigere Definition: »DHTML ist JavaScript für Browser ab Version 4«. Diese Definition ist so eine Art kleinster gemeinsamer Nenner aller konkurrierenden Beschreibungen. Aber das »D« für »Dynamic« hat schon seine Berechtigung. Mit den bisher vorgestellten JavaScript-Techniken kann man zwar auf gewisse Weise auf Benutzereingaben reagieren, aber man hat nicht viele Zugriffsmöglichkeiten auf die Elemente einer HTML-Seite. Zwar kann man mit dem Image-Objekt Grafiken austauschen, von einer Größenveränderung oder gar Verschiebung kann aber keine Rede sein. Mit DHTML ist das möglich, es ist sogar eine Art von Drag&Drop möglich.

16.1.2 Cascading Style Sheets

Die herkömmliche HTML-Programmierung war nicht immer besonders strukturiert. Wollte man in einer Tabelle alle Zellen in einer bestimmten Schrift darstellen, so musste man in jeder Zelle einen <FONT>-Tag verwenden. Mit dem Konzept der Cascading Style Sheets1  (kurz CSS) kann sich das ändern. Ohne hier auf allzu viele Details eingehen zu wollen, sei nur gesagt: Es gibt immer wieder in der Fachpresse Vergleiche, welcher Browser in welchem Maße CSS unterstützt. Dabei schneidet der Netscape Navigator in der Regel am schlechtesten ab, der Internet Explorer schon etwas besser – und in Führung liegt die Nummer 3 auf dem Browser-Markt, der norwegische Opera-Browser.

Ein Style Sheet sieht folgendermaßen aus:

<STYLE TYPE="text/css"><!--
   A {color:blue; text-decoration:none}
--></STYLE>

Die HTML-Kommentare dienen auch hier dazu, dass ältere Browser den Text zwischen den <STYLE>-Tags nicht anzeigen. Eigentlich interessant ist diese Zeile:

A {color:blue; text-decoration:none}

Das bedeutet: Alle Links (Tag <A>) im Text werden in blauer Farbe angezeigt (color:blue) und nicht unterstrichen (text-decoration:none). Diese Angaben gelten global für das gesamte Dokument. Man kann jedoch diese Vorgaben auch überschreiben, indem bei einem Tag der STYLE-Parameter gesetzt wird:

<A HREF="http://www.galileo-press.de" STYLE="color:blue;
text-decoration:none">Galileo Press</A>

Man kann natürlich nicht nur Links anpassen, sondern beispielsweise auch Absätze (Tag <P>) oder eben Tabellenzellen (Tag <TD>):

<STYLE TYPE="text/css"><!--
   P {color:green}
   TD {font-size: 12pt}
--></STYLE>

16.1.3 Positionierung von Elementen

Ein weiterer Bestandteil von Cascading Style Sheets ist die Möglichkeit, HTML-Elemente exakt auf einer Seite zu positionieren. Dies ist das eigentlich dynamische Element von DHTML, da sich so beispielsweise auch Animationen erstellen lassen. Man kann mit JavaScript die Position der einzelnen Objekte verändern.

Man unterscheidet zwischen absoluter und relativer Positionierung. Wie die Namen schon andeuten, kann man entweder absolute und relative Werte für die Position eines Objekts angeben. Ein entsprechender STYLE-Parameter kann folgendermaßen aussehen:

STYLE="position:absolute"

oder

STYLE="position:relative"

Bei der absoluten Positionierung kann man die absolute Position innerhalb des Browser-Fensters angeben; bei der relativen Positionierung die relative Position, das bedeutet relativ zu der Position, die das Objekt beim normalen HTML-Rendering einnehmen würde. In der Regel verwendet man die relative Positionierung, da man so gut wie nie die exakte Anfangsposition eines Objekts im HTML-Dokument im Voraus wissen kann. Zu unterschiedlich rendern die beiden großen Browser HTML-Dokumente.

16.1.4 JavaScript Style Sheets

Netscape hat mit seinem Browser eine besondere Form der Style Sheets eingeführt, mit der man Style Sheet-Eigenschaften mit JavaScript setzen und ändern kann. Gehen wir zu einem der vorherigen Style Sheets zurück:

<STYLE TYPE="text/css"><!--
   P {color:green}
--></STYLE>

Mit JavaScript kann man das auch folgendermaßen schreiben:

<STYLE TYPE="text/javascript">
   tags.p.color = "green"
</STYLE>

Im tags-Objekt kann man auf die verschiedenen Tags eines Dokuments zugreifen und deren Eigenschaften setzen; eine komplette Auflistung würde hier den Rahmen sprengen.

Man kann Styles nicht nur global allen spezifischen Tags innerhalb eines HTML-Dokuments zuordnen. Mittels Klassen kann man Tags in Gruppen einteilen und diesen Gruppen dann Werte zuweisen.

<A HREF="http://www.netscape.com" CLASS="Browser">Netscape Navigator</A>
<A HREF="http://www.microsoft.com" CLASS="Browser">Microsoft</A>

Alternativ dazu kann man auch einzelnen Tags einen Identifikator, eine ID, vergeben.

<A HREF="http://www.galileo-press.de" ID="Galileo">Galileo Press</A>

Mit JavaScript kann man diese Elemente dann ändern. So kann man beispielsweise einer Gruppe von Links eine bestimmte Eigenschaft zuordnen (etwa die Farbe) oder auch nur einem bestimmten Link (oder einem anderem Objekt) eine Eigenschaft zuweisen. Auf Klassen kann mit classes.Klassenname.Tagname zugegriffen werden, auf Identifikatoren mit ids.Identifikator:

<STYLE TYPE="text/javascript">
   classes.Browser.a.color = "red"
   ids.Galileo. a.color = "black"
</STYLE>

Abbildung 16.1  Verschiedene Styles – verschiedene Farben

16.1.5 Layer

Mit dem Netscape Navigator 4 wurde ein neuer Tag eingeführt, der <LAYER>-Tag. In der nächsten Version wird dieser Tag wohl nur noch aus Gründen der Abwärtskompatibilität existieren. Der Internet Explorer kennt ihn nicht einmal. Das lag daran, dass der Netscape Navigator 4 vor dem Internet Explorer 4 erschienen ist und zum Zeitpunkt der IE-Veröffentlichung schon feststand, dass das W3C den <LAYER>-Tag nicht übernehmen würde.

Ein Layer kann in etwa mit einem Frame verglichen werden. Mit diesem Tag kann man einen Teil der Webseite unabhängig vom Rest des HTML-Dokuments abspeichern. Es gibt zwei Möglichkeiten, einen Layer zu verwenden:

<LAYER ID="Layer1" SRC="externedatei.html">

oder

<LAYER ID="Layer2">
<!-- HTML-Befehle -->
</LAYER>

Es gibt drei Möglichkeiten, auf so einen Layer zuzugreifen:

	document.Layername
	document.layers[Layerindex]
	document.layers["Layername"]

Dieses Vorgehen dürfte Ihnen noch vom Image-Objekt her bekannt sein.

Um auf HTML-Elemente innerhalb des Layers zuzugreifen, beispielsweise auf Formularelemente oder ähnliches, muss man auf die document-Eigenschaft des Layers zurückgreifen. Sind die Layer verschachtelt, so muss man – wie bei Frames – sich von Layer zu Layer nach unten hangeln. So etwas wie die Eigenschaft parent bei den Frames gibt es bei Layern natürlich auch; jeder Layer enthält in der Eigenschaft parentLayer eine Referenz auf den darüberliegenden Layer.

Betrachten Sie beispielsweise folgenden HTML-Code:

<HTML>
<HEAD>
<TITLE>Layer-Test</TITLE>
</HEAD>
<BODY>
<H3>Layer-Test</H3>
<LAYER ID="Layer1">
Layer 1
   <LAYER ID="Layer2">
   <FORM>
   <INPUT TYPE="BUTTON" VALUE="Layer2">
   </FORM>
   </LAYER>
</LAYER>
</BODY>
</HTML>

Abbildung 16.2  Zwei Layer, am Bildschim sonst nicht zu unterscheiden

Um nun auf die Schaltfläche im Dokument zuzugreifen, müssen Sie den folgenden Code verwenden:

document.Layer1.document.Layer2.forms[0].elements[0]

16.2 Beispiele

Die folgenden Beispiele demonstrieren die praktische Umsetzung des bisher Gesagten. Sie werden im folgenden Kapitel auch für den Internet Explorer umgesetzt, sodass die Unterschiede klar erkennbar werden. Es werden hier neue Beispiele vorgestellt. Natürlich können Sie auch die Navigation aus dem Kapitel »Images« mit Layern umsetzen, aber da dort schon eine browser-unabhängige Lösung entwickelt worden ist, sollten Sie hier keine Extra-Anstrengungen unternehmen.

16.2.1 Animiertes Logo

Unsere erste Anwendung soll eine einfache Animation sein. Ein Firmenlogo soll nicht nur statisch auf der Webseite stehen, sondern animiert werden, beispielsweise soll es von links ins Bild schweben. Ein erstes HTML-Grundgerüst sieht folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
</HEAD>
<BODY>
<H3>Animiertes Logo</H3>
<IMG SRC="logo.gif">
</BODY>
</HTML>

Die Animation des Logos geschieht nun folgendermaßen:

	Das Logo wird in einen Layer eingefügt.
	Die Positionierung dieses Layers wird auf relativ gesetzt.
	Beim Laden der Seite wird der Layer zuerst recht weit nach links bewegt.
	Dann startet eine Animation, die das Logo stückweise nach rechts schiebt, bis es an seinem angestammten Platz ist.

Diese Liste soll nun abgearbeitet werden. Als Erstes muss der Layer mit relativer Positionierung eingefügt werden:

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<LAYER ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></LAYER>
</BODY>
</HTML>

Als nächstes muss die Funktion init() programmiert werden, die das Logo nach links verschiebt. Beim Netscape Navigator steht die x-Koordinate die linke obere Ecke eines Layers in der Eigenschaft left, die y-Koordinate der linken oberen Ecke in der Eigenschaft top (und zwar relativ zum Browser-Fenster, Frame oder umgebenden Layer). Da das Logo am Anfang nicht sichtbar sein soll, kann man hier einen negativen Wert angeben. Die ursprüngliche x-Koordinate wird in einer Variablen für später gespeichert.

var layer_x
function init(){
   if (document.layers){
      layer_x = document.logo.left
      document.logo.left = -200
      //Animation starten
      animate()
   }
}

Die Abfrage if (document.layers) liefert genau dann true, wenn der Browser das layers-Objekt kennt, also ähnlich wie beim Image-Objekt. So werden Fehlermeldungen bei Browsern, die keine Layer unterstützen, verhindert.

Die Animation funktioniert ähnlich wie bei der Laufschrift. Das Logo wird um (beispielsweise) drei Pixel nach rechts bewegt, und dann wird mit setTimeout() die Funktion nach einer gewissen Zeit wieder aufgerufen. Das ganze wird so lange wiederholt, bis die (relative) Position der Grafik wieder gleich layer_x ist, sie sich also wieder am ursprünglichen Platz befindet.

function animate(){
   if (document.logo.left>layer_x)
      document.logo.left = layer_x
   if (document.logo.left<layer_x){
      document.logo.left += 3
      setTimeout("animate()", 50)
   }
}

In jedem Bearbeitungsschritt wird das Logo um drei Pixel nach rechts geschoben, sofern die relative Position kleiner als 0 ist (sich das Logo also noch links von der ursprünglichen Position befindet). Ist die Position größer als 0, so ist das Logo ein wenig über das Ziel hinausgeschossen (in unserem Beispiel ist das der Fall, weil 200 nicht durch drei teilbar ist), und die Position wird korrigiert. Das vollständige Listing befindet sich natürlich auf der CD-ROM, hier ist es aber noch einmal im Zusammenhang:

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var layer_x
function init(){
   if (document.layers){
      layer_x = document.logo.left
      document.logo.left = -200
      //Animation starten
      animate()
   }
}
function animate(){
   if (document.logo.left>layer_x)
      document.logo.left = layer_x
   if (document.logo.left<layer_x){
      document.logo.left += 3
      setTimeout("animate()", 50)
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<LAYER ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></LAYER>
</BODY>
</HTML>

Abbildung 16.3  Das animierte Logo im Anflug

Man sieht hier schon einen Nachteil der Layer-Technik: Trotz relativer Positionierung enthält left (und auch top) die Position relativ zum Browser, Frame oder umgebenden Layer, und ist insbesondere nicht mit 0 vorbesetzt. Im Kapitel über browser-kompatibles DHTML wird hierzu eine Lösung vorgestellt.

16.2.2 Drag&Drop

Dank DHTML ist nun endlich auch Drag&Drop möglich. Die Anwendungen halten sich auch hier in Grenzen, aber man kann immerhin den Spieltrieb des Webseitenbesuchers anregen. Sie sollten sich das Kapitel »Events« noch einmal durchlesen, bevor Sie das folgende Beispiel nachvollziehen, da Sie hier eine echte Anwendung für die fortgeschrittene Ereignisbehandlung mit Browsern der Version 4 sehen.

Das Drag&Drop-Beispiel funktioniert folgendermaßen: Das Logo aus dem vorherigen Beispiel soll mit der Maus an eine beliebige Stelle im Browser gezogen werden können. Der Benutzer drückt also die Maustaste, sobald er sich mit dem Mauszeiger über dem Logo befindet, bewegt den Mauszeiger zu einer anderen Stelle im Dokument und lässt die Maustaste dann wieder los.

Programmiertechnisch wird das mit den folgenden Schritten erreicht:

	Mit JavaScript wird das Ereignis mousedown abgefangen. Ist dies der Fall, so wird mittels einer Booleschen Variablen angegeben, dass nun Drag&Drop-Operationen durchgeführt werden dürfen. Grundbedingung: Der Mauszeiger muss sich über dem Logo befunden haben, als die Maustaste gedrückt worden ist.
	Wann immer der Benutzer im folgenden den Mauszeiger bewegt (Ereignis mousemove), wird die Grafik (bzw. der Layer, in dem sich die Grafik befindet) an die Stelle gezogen, an der sich der Mauszeiger befindet (die Koordinaten erhält man aus dem Event-Objekt, vgl. die Referenz oder das Listing).
	Wird die Maustaste losgelassen (Ereignis mouseup), so wird das Drag&Drop deaktiviert, die Boolesche Variable also zurückgesetzt.

Gehen wir schrittweise vor: Zunächst müssen die entsprechenden Ereignisse abgefangen und Event-Handler besetzt werden. Außerdem werden – wie im vorherigen Beispiel – die Koordinaten der linken oberen Ecke des Logos in globalen Variablen gespeichert.

var logo_x, logo_y
function init(){
   document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP
| Event.MOUSEMOVE)
   document.onmousedown = setzestatus
   document.onmouseup = setzestatus
   document.onmousemove = dragdrop
   logo_x = document.logo.left
   logo_y = document.logo.top
}

Am einfachsten zu implementieren ist wohl die Boolesche Variable, die angibt, ob gerade die Maustaste niedergedrückt wird, ob also das Logo gerade bewegt werden darf. Im Falle des Ereignisses mousedown wird die Variable nur dann von true auf false oder von false auf true gesetzt, wenn sich der Mauszeiger über der Grafik befunden hat. Wir nehmen hier an, dass die Grafik das NAME-Attribut "logogfx" trägt. Außerdem werden die Variablen des Mausklicks gespeichert; so kann man die Grafik später exakt positionieren. Bei mousedown werden auch die aktuellen Koordinaten der Grafik abgespeichert, denn man kann ja auch mehrmals hintereinander Drap&Drop-Operationen ausführen.

var bereit = false  //Bereit für Drag&Drop?
var maus_x, maus_y
function setzestatus(e){
   if (e.type=="mouseup" || (e.type=="mousedown" &&
     e.target.name=="logogfx")){
      maus_x = e.pageX
      maus_y = e.pageY
      bereit = !bereit  //von true auf false, von false auf true
      if (e.type=="mousedown"){
         logo_x = document.logo.left
         logo_y = document.logo.top
      }
   }
}

Wie Sie sehen, steht in der Eigenschaft pageX des Event-Objekts die x-Koordinate des Mauszeigers, während das Ereignis eintritt. In pageY steht dann die y-Koordinate.

Als nächstes erstellen wir die Funktion dragdrop(). Diese muss die aktuelle Mausposition aus dem Event-Objekt bestimmen, die Differenz zur ursprünglichen Mausposition berechnen und daraus die neue Position des Logos bestimmen. Das darf im übrigen nur dann passieren, wenn die Variable bereits den Wert true hat (also die Maustaste gedrückt, aber noch nicht wieder losgelassen wurde).

function dragdrop(e){
   if (bereit){
      var aktuell_x = e.pageX
      var aktuell_y = e.pageY
      document.logo.left = logo_x + (aktuell_x – maus_x)
      document.logo.top = logo_y + (aktuell_y – maus_y)
   }
}

Sie sehen hier, wie man schon mit sehr wenig Aufwand überraschende Effekte erzielen kann. Hier folgt noch einmal das gesamte Listing, mitsamt dem HTML-Code:

<HTML>
<HEAD>
<TITLE>Drag &amp; Drop</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var logo_x, logo_y
function init(){
   document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP
| Event.MOUSEMOVE)
   document.onmousedown = setzestatus
   document.onmouseup = setzestatus
   document.onmousemove = dragdrop
   logo_x = document.logo.left
   logo_y = document.logo.top
}
var bereit = false  //Bereit für Drag&Drop?
var maus_x, maus_y
function setzestatus(e){
   if (e.type=="mouseup" || (e.type=="mousedown" &&
     e.target.name=="logogfx")){
      maus_x = e.pageX
      maus_y = e.pageY
      bereit = !bereit  //von true auf false, von false auf true
      if (e.type=="mousedown"){
         logo_x = document.logo.left
         logo_y = document.logo.top
      }
   }
}
function dragdrop(e){
   if (bereit) {
      var aktuell_x = e.pageX
      var aktuell_y = e.pageY
      document.logo.left = logo_x + (aktuell_x – maus_x)
      document.logo.top = logo_y + (aktuell_y – maus_y)
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Drag &amp; Drop</H3>
<LAYER ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></LAYER>
</BODY>
</HTML>

Abbildung 16.4  Drag&Drop: Das Logo wurde nach rechts unten gezogen.

16.2.3 Sichtbar und unsichtbar

Von besonderem Interesse ist noch die Möglichkeit, Layer sichtbar oder unsichtbar zu machen. Man kann sogar Layer übereinander anordnen und deren (virtuelle) z-Koordinate setzen, aber dazu erfahren Sie in der Referenz mehr. Als Beispielanwendung soll eine Art Register programmiert werden, wie man es von Windows-Applikationen her kennt. In diesem Beispiel gibt es drei Register, und nach einem Klick auf die Registerreiter soll das entsprechende Register angezeigt werden.

Hierzu ist Folgendes zu tun:

	Die drei Register werden im HTML-Code definiert und alle an dieselbe Stelle gesetzt.
	Das erste Register wird sichtbar gemacht (bzw. bleibt sichtbar), die anderen beiden werden unsichtbar.
	Wird eine Lasche angeklickt, so wird das aktuelle Register unsichtbar gemacht und das ausgewählte Register angezeigt.

Begonnen wird mit dem HTML-Code. Beachten Sie, dass dort noch nicht alle Register an dieselbe Stelle gesetzt werden (das wäre mit dem STYLE-Tag kein Problem); statt dessen wird später mit JavaScript die Position des ersten Registers bestimmt, und die anderen beiden werden dann dorthin bewegt. Bei den drei Laschen ist aber schon die JavaScript-Funktion zum Ein- bzw. Ausblenden der jeweiligen Register vorgesehen.

<HTML>
<HEAD>
<TITLE>Register</TITLE>
<STYLE TEXT="text/css"><!--
A {color:black; text-decoration:none}
--></STYLE>
</HEAD>
<BODY onLoad="init()">
<TABLE><TR>
<TD BGCOLOR="red">
   <A HREF="javascript:register(1)">Register 1</A>
</TD>
<TD BGCOLOR="green">
   <A HREF="javascript:register(2)">Register 2</A>
</TD>
<TD BGCOLOR="blue">
   <A HREF="javascript:register(3)">Register 3</A>
</TD>
</TR></TABLE>
<LAYER ID="register1" STYLE="position:relative">
   <H3>Register 1</H3>
</LAYER>
<LAYER ID="register2" STYLE="position:relative">
   <H3>Register 2</H3>
</LAYER>
<LAYER ID="register3" STYLE="position:relative">
   <H3>Register 3</H3>
</LAYER>
</BODY>
</HTML>

Die Initialisierungsfunktion init() ist schnell geschrieben. Die Position des zweiten und des dritten Layers muss gesetzt werden; außerdem müssen diese beiden Layer unsichtbar gemacht werden. Das geschieht, indem die Eigenschaft visibility auf "hidden" gesetzt wird. Dieser Vorgang kann durch Setzen auf "visible" umgekehrt werden.

function init(){
   var layer_x = document.register1.left
   var layer_y = document.register1.top
   document.register2.left = layer_x
   document.register2.top = layer_y
   document.register2.visibility = "hidden"
   document.register3.left = layer_x
   document.register3.top = layer_y
   document.register3.visibility = "hidden"
}

Abbildung 16.5  Das zweite Register ist aktiviert.

Die Funktion register() muss das aktuelle Register aus- und das neue Register einblenden. Am einfachsten ist es, alle Register auszublenden, nur das neue wird eingeblendet:

function register(n){
   for (var i=1; i<=3; i++){
      var visi = (i==n) ? "visible" : "hidden"
      document.layers["register"+i].visibility = visi
   }
}

Hier folgt das ganze Listing noch einmal am Stück; auf der CD-ROM werden Sie natürlich auch fündig.

<HTML>
<HEAD>
<TITLE>Register</TITLE>
<STYLE TEXT="text/css"><!--
A {color:black; text-decoration:none}
--></STYLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   var layer_x = document.register1.left
   var layer_y = document.register1.top
   document.register2.left = layer_x
   document.register2.top = layer_y
   document.register2.visibility = "hidden"
   document.register3.left = layer_x
   document.register3.top = layer_y
   document.register3.visibility = "hidden"
}
function register(n){
   for (var i=1; i<=3; i++){
      var visi = (i==n) ? "visible" : "hidden"
      document.layers["register"+i].visibility = visi
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<TABLE><TR>
<TD BGCOLOR="red">
   <A HREF="javascript:register(1)">Register 1</A>
</TD>
<TD BGCOLOR="green">
   <A HREF="javascript:register(2)">Register 2</A>
</TD>
<TD BGCOLOR="blue">
   <A HREF="javascript:register(3)">Register 3</A>
</TD>
</TR></TABLE>
<LAYER ID="register1" STYLE="position:relative">
   <H3>Register 1</H3>
</LAYER>
<LAYER ID="register2" STYLE="position:relative">
   <H3>Register 2</H3>
</LAYER>
<LAYER ID="register3" STYLE="position:relative">
   <H3>Register 3</H3>
</LAYER>
</BODY>
</HTML>

16.2.4 Neuer Mauszeiger

Ein Effekt, der sich auf immer mehr Webseiten befindet, ist die Verwendung eines neuen Mauszeigers. Natürlich ist es nicht möglich, die Anzeigeeigenschaften für den Mauszeiger des Benutzers zu ändern, das wäre alleine aus Sicherheitsgründen eine Katastrophe, aber es ist möglich, einen Layer zu erstellen, der sich immer an der aktuellen Mauszeigerposition befindet und somit die Maus des Benutzers verfolgt. Als Beispielsgrafik verwenden wir hier das Logo von Galileo Press. Sie finden es im Internet unter http://www.galileo-press.de/ – aber Sie können auch eine beliebige andere Grafik verwenden. Die folgenden Schritte müssen umgesetzt werden, damit dies funktioniert:

	Der Layer mit der Grafik wird im HTML-Code definiert (mit ID="mauszeiger").
	Wenn der Benutzer eine Mausbewegung macht (Event-Handler onMouseMove) wird der Layer an die aktuelle Mausposition bewegt.

Wir definieren zunächst eine Funktion init(), die nach dem Laden des Dokuments aufgerufen wird. In dieser wird das MouseMove-Ereignis abgefangen, und an eine Funktion anim() weitergeleitet:

function init(){
   document.captureEvents(Event.MOUSEMOVE)
   document.onmousemove=anim
}

Fehlt nur noch die Funktion anim() – aber das ist wirklich nichts Neues mehr. Die linke obere Ecke des Layers wird auf die aktuelle Position des Mauszeigers gesetzt. Letztere bekommt man aus dem Parameter e, der anim() automatisch übergeben wird. Da das Ereignis von der Mausbewegung ausgelöst worden ist, stehen in e.pageX und e.pageY die Koordinaten des Mauszeigers.

function anim(e){
   document.mauszeiger.left = e.pageX
   document.mauszeiger.top = e.pageY
}

Mehr ist nicht zu tun. Sie können das Beispiel natürlich auf mehrere Arten erweitern, beispielsweise indem Sie den Layer permanent ein wenig nach oben, unten, links und rechts bewegen, um ein wenig Dynamik zu erzeugen. Gehen Sie mit solchen Effekten aber sparsam um, sonst sind Ihre Besucher (zu) schnell überreizt.

Hier folgt noch einmal das komplette Listing, inklusive HTML-Code.

<HTML>
<HEAD>
<TITLE>Mauszeiger</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   document.captureEvents(Event.MOUSEMOVE)
   document.onmousemove=anim
}
function anim(e){
   document.mauszeiger.left = e.pageX
   document.mauszeiger.top = e.pageY
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Mauszeiger</H1>
<LAYER ID="mauszeiger" STYLE="position:absolute">
  <IMG SRC="logo.gif"></LAYER>
</BODY>
</HTML>

Abbildung 16.6  Das Galileo-Logo als Mauszeiger

16.2.5 Permanentes Werbebanner

Gratis-Hoster, also Firmen, die kostenlosen Webspace anbieten, lassen sich ja einiges einfallen, um effektiv Werbung auf den Webseiten unterzubringen. Besonders aufdringlicher Gag: Ein Werbebanner, das so konzipiert ist, dass es immer sichtbar ist (beispielsweise, indem es sich immer in der rechten oberen Ecke des Browserfensters befindet. Weitere Anwendungsmöglichkeit hierfür: Eine Navigation oder Sitemap, die ebenfalls immer sichtbar ist. Auch hier gilt: Den Effekt recht sparsam einsetzen, oder zumindest die Möglichkeit anbieten, das Banner (oder die Sitemap) ausblenden zu können, um die dahinter liegenden Bereiche auf der Website überhaupt ansehen zu können.

Die Vorgehensweise bei diesem Beispiel ist die Folgende:

	Im HTML-Code wird ein Layer definiert, der das Banner enthält (mit ID="logo", wir verwenden auch hier wieder das Galileo-Logo, welches hier die Funktion eines Werbelinks auf die Verlags-Homepage hat).
	Per Timeouts wird der Layer alle halbe Sekunde an die rechts obere Ecke des Browserfensters verschoben.

Auch hier beginnen wir mit einer Funktion init(). Da wir mit Timeouts arbeiten, müssen wir an dieser Stelle nicht mühsam Ereignisse abfangen und umleiten, sondern lediglich das Werbebanner sichtbar machen (wäre etwas unhübsch, wenn das Banner schon beim Laden der Seite sichtbar wäre, denn zu dieser Zeit ist es noch recht schwierig, die richtige Position zu bestimmen), und dann die Funktion aufzurufen, die das Logo an den rechten Platz verschiebt:

function init(){
   document.logo.visibility="visible"
   anim()
}

Auch die Funktion anim() ist relativ kurz, der Aufwand liegt – wie so oft bei DHTML – eher in der Recherche (und in der Fehlersuche) als in der Programmierung per se. In window.pageXOffset und window.pageYOffset steht, an welche Position die aktuelle Seite im Browserfenster gescrollt worden ist. Die Y-Koordinate der linken oberen Ecke des Banners muss also auf window.pageYOffset gesetzt werden, das Banner soll ja oben andocken. Bei der X-Koodinate ist das nicht ganz so trivial, aber nicht unmöglich. Also: In window.innerWidth steht, wie breit das Browserfenster abzüglich Scrollbalken, Leisten etc. ist. In der Praxis ist dieser Wert beim Netscape nicht ganz zutreffend, aber man erhält immerhin eine ganz gute Schätzung. Von diesem Wert muss man die Breite der Grafik abziehen (oder am besten noch ein bisschen mehr, eben wegen den Ungenauigkeiten des Netscape), und hat dann die Position der Grafik – beinahe. Schließlich ist es auch möglich, auf Webseiten horizontal zu scrollen (auch wenn das in der Praxis eher selten vorkommt), also muss zu diesem Wert noch window.pageXOffset addiert werden.

Somit sind die Koordinaten ermittelt worden, und Sie müssen nur noch dafür sorgen, dass sich anim() via Timeout wieder selbst aufruft – oder Sie verwenden gleich setInterval() anstelle von setTimeout().

function anim(){
   document.logo.left=window.innerWidth+window.pageXOffset-100
   document.logo.top=window.pageYOffset
   setTimeout("anim()", 500)
}

Abbildung 16.7  Das Galileo-Logo als immer sichtbares Werbebanner

Zum Abschluss dieses Beispiels finden Sie noch einmal ein komplettes Listing abgedruckt, das Sie wie gewohnt auch auf der Buch-CD finden. Beachten Sie, wie Fülltext erzeugt wird, damit das Dokument überhaupt gescrollt werden kann!

<HTML>
<HEAD>
<TITLE>Werbebanner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   document.logo.visibility="visible"
   anim()
}
function anim(){
   document.logo.left=window.innerWidth+window.pageXOffset-100
   document.logo.top=window.pageYOffset
   setTimeout("anim()", 500)
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Werbebanner</H1>
<LAYER ID="logo" STYLE="visibility:hidden">
<A HREF="http://www.galileo-press.de"><IMG SRC="logo.gif" BORDER="0"></A>
</LAYER>
<SCRIPT LANGUAGE="JavaScript"><!--
for (var i=0; i<30; i++)
   document.write("F&uuml;lltext")
for (i=0; i<3; i++){
   for (var j=0; j<10; j++)
      document.write("<"+"BR"+">")
   document.write("F&uuml;lltext")
}
//--></SCRIPT>
</BODY>
</HTML>

16.3 Fragen & Aufgaben

1.	Gehen Sie zu dem Beispiel mit den zwei verschachtelten Layern zurück. Wie könnte man von der Schaltfläche aus auf das Hauptdokument zugreifen?
2.	Ändern Sie das Beispiel mit dem animierten Logo so, dass a) das Logo von rechts einschwebt, b) es diagonal von links oben kommt.
3.	Testen Sie, was passiert, wenn im Registerbeispiel nur das neue Register sichtbar gemacht wird, aber die anderen nicht unsichtbar werden. Wie könnte man diesen Effekt beheben?
4.	Ändern Sie das permanente Werbebanner so um, dass es auf Mausklick verschwindet.

1    In manchen Quellen auch als »kaskadierende Stilvorlagen« o. ä. bezeichnet, aber in diesem Fall sollte man nichts gegen den Anglizismus haben.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 17 DHTML II: Internet Explorer
			17.1 Grundlagen
			17.2 Beispiele
			17.3 Fragen & Aufgaben

Kapitel 17 DHTML II: Internet Explorer

Ist es ein Fortschritt, wenn ein Kannibale

Messer und Gabel benutzt?

– Lec

Wie bereits im vorherigen Kapitel erwähnt, ist die CSS-Unterstützung des Internet Explorer weitaus vollständiger als die des Netscape Navigator. Aus diesem Grund stehen die Chancen auch ganz gut, dass der Netscape Navigator 6 dieselbe Syntax unterstützen wird wie der Internet Explorer. Doch leider gibt es an den entscheidenden Stellen große Unterschiede, sodass zum heutigen Zeitpunkt (Frühjahr 2001) die wenigsten DHTML-Seiten mit dem Netscape 6 konform gehen. Sie sind nach der Lektüre des nächsten Kapitels in der Lage, diesen Missstand zu beheben, doch zunächst wird in diesem Kapitel der Einsatz von DHTML für den Internet Explorer in den Versionen 4, 5 und 5.5 demonstriert. Wie bereits im vorangegangenen Kapitel versprochen, werden im übernächsten Kapitel Strategien vorgestellt, um die Beispiele browser-unabhängig zu machen. In diesem Kapitel werden die Beispiele, die zuvor für den Netscape Navigator implementiert worden sind, für den Internet Explorer umgeschrieben. Die Beschreibung der Algorithmen fällt also ein wenig kürzer aus. Vom Prinzip her ist ja alles bekannt, es werden nur die technischen Hintergründe (wie man auf welche Objekte zugreift) erläutert.

17.1 Grundlagen

Der Begriff DOM wird Ihnen in Ihrer Laufbahn als JavaScript-Programmierer noch öfter begegnen. Diese Abkürzung steht für Document Object Model, und darunter versteht man die hierarchische Anordnung der einzelnen HTML-Dokumente im document-Objekt. Im Gegensatz zum Netscape Navigator 4 ist im Internet Explorer alles, was zwischen Tags eingeschlossen ist, ein Objekt, also beispielsweise auch kursiv gedruckter Text (<I>-Tag). Auf jedes dieser Objekte kann man zugreifen, und jedes dieser Objekte hat eine Menge von Eigenschaften. Somit benötigt man bei Grafiken (<IMG>-Tag) keinen Link um die Grafiken, um einen Mouseover-Effekt zu erzielen, dem <IMG>-Tag kann auch ein Event-Handler mitgegeben werden.

17.1.1 HTML-Tags

Prinzipiell genügt es, wenn man jedem Tag, auf den man mit JavaScript/DHTML zugreifen will, einen Identifikator gibt. Dazu verwenden Sie, wie beim Netscape Navigator auch, den ID-Parameter:

<P ID="Galileo">Galileo Press</P>

So etwas wie ein Layer hat sich aber schon zuvor als sehr nützlich erwiesen. Es gibt einen Tag, der sogar – man glaubt es kaum – vom Netscape Navigator unterstützt wird: <DIV>. Es wird wie bei einem Layer angewendet, nur kann man keine externen Dateien einbinden.

<DIV ID="DIV1">
<!-- HTML-Kommandos etc. -->
</DIV>

Auch dem <DIV>-Tag kann man einen STYLE-Parameter mitgeben, um beispielsweise den Inhalt des <DIV>-Tags zu verstecken oder zu bewegen.

17.1.2 Objektzugriff

Alle Elemente einer HTML-Seite sind beim Internet Explorer 4 in document.all gespeichert. Über den Identifikator kann man dann auf ein Element zugreifen, um – und das ist das eigentlich Interessante – über die style-Eigenschaft des Elements Zugriff auf das Aussehen des Elements zu haben.

Mit dem folgenden Code macht man beispielsweise den Layer "DIV1" aus dem obigen Beispiel unsichtbar:

document.all.DIV1.style.visibility = "hidden"

Sie sehen an der Punkt-Schreibweise, dass Sie keine Leerzeichen oder Sonderzeichen im ID-Parameter für Ihre <DIV>-Tags verwenden sollten.

An diesem Beispiel sehen Sie auch eine recht einfache Überprüfung, ob der Browser den Zugriff auf Elemente im Internet Explorer-Stil unterstützt (momentan tun das nur der Internet Explorer Version 4 und 5.x). Wie schon früher verwenden wir die Methode, die das Vorhandensein eines Objekts prüft:

if (document.all){
   //Code für Internet Explorer 4/5
}

17.2 Beispiele

Die Beispiele aus dem vorherigen Kapitel werden im Folgenden für den Internet Explorer umgeschrieben. Galt zuvor noch, dass alle Beispiele lediglich mit dem Netscape Naviagor 4 problemlos funktionieren, so gilt hier dasselbe für die Internet Explorer-Versionen 4 und 5.

17.2.1 Animiertes Logo

Wir beginnen mit dem animierten Logo. Zunächst muss der HTML-Code von <LAYER> auf <DIV> geändert werden:

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

Der <DIV>-Tag hat den großen Vorteil, dass – bei relativer Positionierung – die x- und y-Koordinate der linken oberen Ecke gleich Null ist, was das Skript ein wenig vereinfacht. Der Pferdefuß: Beim Internet Explorer heißen die Eigenschaften nicht left und top, sondern posLeft und posTop. Ansonsten muss man im Vergleich zum Netscape Navigator-Skript lediglich den Zugriff auf document.all ändern. Der Aufwand hält sich derart in Grenzen, dass hier gleich die Endversion des Skripts angegeben wird.

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   if (document.all)
      document.all.logo.style.posLeft = -200
   //Animation starten
   animate()
}
function animate(){
   if (document.all.logo.style.posLeft>0)
      document.all.logo.style.posLeft = 0
   if (document.all.logo.style.posLeft<0){
      document.all.logo.style.posLeft += 3
      setTimeout("animate()", 50)
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

Abbildung 17.1  Das Logo fliegt von links ein.

17.2.2 Drag&Drop

Auch das Drag&Drop-Beispiel lässt sich mit recht wenig Aufwand umschreiben. Die Änderungen sind ein wenig komplizierter als beim vorherigen Beispiel, weil die Ereignisbehandlung beim Internet Explorer ja etwas anders abläuft. Während beim Netscape Navigator noch mit capture Events() gearbeitet werden musste, unterstützt der Internet Explorer das Bubbling-Prinzip, was den Aufwand etwas verringert. Die Initialisierungsfunktion init() fällt deswegen etwas kürzer aus als beim Netscape-Pendant: Als weitere Anpassung müssen – beim Auslesen der Koordinaten des Logos – die Zugriffe auf das Objekt angepasst werden.

var logo_x, logo_y
function init(){
   document.onmousedown = setzestatus
   document.onmouseup = setzestatus
   document.onmousemove = dragdrop
   logo_x = document.all.logo.style.posLeft
   logo_y = document.all.logo.style.posTop
}

Als Nächstes müssen Sie sich die Funktion setzestatus() vornehmen. Beim Netscape Navigator wurde das auslösende Ereignis als Parameter übergeben, beim Internet Explorer steht das bekannterweise im Objekt event. Außerdem müssen wiederum die Zugriffe auf die Koordinaten des Logos aktualisiert werden. Die aktuellen Koordinaten der Maus beim Eintreten eines Ereignisses erhält man beim Internet Explorer über die Ereigniseigenschaften clientX und clientY.

var bereit = false
var

 maus_x, maus_y
function

 setzestatus(){

if (event.type=="mouseup" || (event.type=="mousedown" &&
     event.srcElement.name=="logogfx")){

maus_x = event.clientX

maus_y = event.clientY

bereit = !bereit

if (event.type=="mousedown"){

logo_x = document.all.logo.style.posLeft

logo_y = document.all.logo.style.posTop

}

}
}

Die letzte JavaScript-Funktion, die noch angepasst werden muss, ist dragdrop(). Hier geschieht aber wirklich nichts Neues mehr, nur der Zugriff auf das Ereignis sowie die Koordinaten wird wie gehabt umgeschrieben:

function dragdrop(){

if (bereit){

var aktuell_x = event.clientX

var aktuell_y = event.clientY

document.all.logo.style.posLeft = logo_x +
        aktuell_x

 – maus_x

document.all.logo.style.posTop = logo_y +
        aktuell_y

 – maus_y

}
}

Im Folgenden sehen Sie noch einmal das komplette Beispiel zum Abtippen. Im HTML-Code wurde der Layer durch einen <DIV>-Tag ersetzt. Wenn Sie den Code nicht abtippen wollen, was gut zu verstehen ist, da er eine gewisse Länge hat, finden Sie ihn auch auf der Buch-CD-ROM.

<HTML>
<HEAD>
<TITLE>Drag &amp; Drop</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var logo_x, logo_y
function init(){
   document.onmousedown = setzestatus
   document.onmouseup = setzestatus
   document.onmousemove = dragdrop
   logo_x = document.all.logo.style.posLeft
   logo_y = document.all.logo.style.posTop
}
var bereit = false
var maus_x, maus_y
function setzestatus(){
   if (event.type=="mouseup" || (event.type=="mousedown" &&
     event.srcElement.name=="logogfx")){
      maus_x = event.clientX
      maus_y = event.clientY
      bereit = !bereit
      if (event.type=="mousedown"){
         logo_x = document.all.logo.style.posLeft
         logo_y = document.all.logo.style.posTop
      }
   }
}
function dragdrop(){
   if (bereit){
      var aktuell_x = event.clientX
      var aktuell_y = event.clientY
      document.all.logo.style.posLeft = logo_x + aktuell_x – maus_x
      document.all.logo.style.posTop = logo_y + aktuell_y – maus_y
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Drag &amp; Drop</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

Abbildung 17.2  Das Logo wurde per Drag&Drop nach rechts unten verschoben.

Sie werden beim Testen bemerken, dass das Drag&Drop in der Praxis nicht so einfach funktioniert. Der Browser reagiert nämlich, wenn Sie die Maustaste drücken und die Maus dann bewegen, als ob Sie Text markieren wollten. Das System ist also noch nicht perfekt. Ein Ausweg wäre, durch einen Mausklick das Drag&Drop einzuschalten und durch einen weiteren Klick es wieder auszuschalten. Die Funktion setzestatus() müsste dazu immer beim Eintritt des click-Ereignisses aufgerufen werden, und man müsste sich von mouseup und mousedown verabschieden. Sie können das zur Übung einmal ausprobieren, der Arbeitsaufwand ist minimal.

17.2.3 Sichtbar und unsichtbar

Es folgt das Beispiel mit den an Windows-Applikationen angelehnten Registern. Hier gestalten sich die Änderungen aber besonders einfach, vor allem dann, wenn Sie die vorherigen Beispiele schon durchgearbeitet haben. Sie müssen lediglich Zugriffe auf das <DIV>-Element durchführen und die visibility-Eigenschaft ändern. Aus diesem Grund folgt hier gleich der gesamte Code, Änderungen sind wie immer fett gesetzt.

<HTML>
<HEAD>
<TITLE>Register</TITLE>
<STYLE TEXT="text/css"><!--
A color:black; text-decoration:none}
--></STYLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   var layer_x = document.all.register1.style.posLeft
   var layer_y = document.all.register1.style.posTop
   document.all.register2.style.posLeft = layer_x
   document.all.register2.style.posTop = layer_y
   document.all.register2.style.visibility = "hidden"
   document.all.register3.style.posLeft = layer_x
   document.all.register3.style.posTop = layer_y
   document.all.register3.style.visibility = "hidden"
}
function register(n){
   for (var i=1; i<=3; i++){
      var visi = (i==n) ? "visible" : "hidden"
      document.all("register"+i).style.visibility = visi
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<TABLE><TR>
<TD BGCOLOR="red">
   <A HREF="javascript:register(1)">Register 1</A>
</TD>
<TD BGCOLOR="green">
   <A HREF="javascript:register(2)">Register 2</A>
</TD>
<TD BGCOLOR="blue">
   <A HREF="javascript:register(3)">Register 3</A>
</TD>
</TR></TABLE>
<DIV ID="register1" STYLE="position:relative">
   <H3>Register 1</H3>
</DIV>
<DIV ID="register2" STYLE="position:relative">
   <H3>Register 2</H3>
</DIV>
<DIV ID="register3" STYLE="position:relative">
   <H3>Register 3</H3>
</DIV>
</BODY>
</HTML>

Abbildung 17.3  Registerreiter mit DHTML

Sie sehen hier einen weiteren Unterschied zum Netscape Navigator. Wenn man beim Navigator den Identifikator eines Layers nicht angeben will, kann man mit document.layers["Name"] darauf zugreifen, also mit eckigen Klammern. Beim Internet Explorer muss man runde Klammern verwenden, also document.all("Name"). Kleine Frage am Rande: Wie kann man das ohne Klammern erledigen? Kleiner Tipp: Hier hilft eval() weiter.

17.2.4 Neuer Mauszeiger

Das Beispiel mit dem Mauszeiger bringt kaum etwas Neues, sodass Sie an dieser Stelle auch nur den Code wieder finden, mit hervorgehobenen Änderungen. Die Ereignisbehandlung ist eine andere, und die Koordinaten von Layer und Mauszeiger werden auf eine andere Art und Weise ermittelt, ansonsten keine großen Besonderheiten. Sie sollten lediglich darauf achten, absolute Positionierung zu verwenden, denn sonst ist das Galileo-Logo ein wenig zur Seite versetzt (da es sich beim Laden der Seite nicht in der linken oberen Ecke befand).

Abbildung 17.4  Das Galileo-Logo als Mauszeiger

<HTML>
<HEAD>
<TITLE>Mauszeiger</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   document.onmousemove=anim
}
function anim(e){
   document.all.mauszeiger.style.posLeft = event.clientX
   document.all.mauszeiger.style.posTop = event.clientY
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Mauszeiger</H1>
<DIV ID="mauszeiger" STYLE="position:absolute">
  <IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

17.2.5 Permanentes Werbebanner

Das Umschreiben des Beispiels mit dem immer sichtbaren Werbebanner ist ein wenig aufwendiger als der grafische Mauszeiger, deswegen Schritt für Schritt. Das ID-Attribut des <DIV>-Tags, der das Werbebanner umschließt, ist wieder logo. In der Funktion init() wird der Layer sichtbar gemacht, und anim() aufgerufen:

function init(){

document.all.logo.style.visibility="visible"

anim()
}

In der Funktion anim() wird wie zuvor die neue Position des Werbebanners berechnet, das Banner dorthin verschoben, und dann die Funktion via Timeout nach einer halben Sekunde erneut aufgerufen. Jedoch heißen die Eigenschaften, die beispielsweise die aktuelle Scrollposition des Browserfensters enthalten, beim Internet Explorer (und wohl auch beim Netscape 6) komplett anders als beim Netscape Navigator 4. Aus window.innerWidth (Breite des Browserfensters) wird document.body.clientWidth, und window.pageXOffset und window.pageYOffset finden in document.body. scrollLeft und document.body.scrollTop ihre Entsprechung. Der Rest bleibt beinahe identisch. Kleiner Unterschied am Rande: document.body. clientWidth arbeitet viel exakter als das Netscape-Pendant, man muss von diesem Wert also in der Tat nur die Breite der Grafik abziehen, und nicht etwas mehr, wie das noch beim Netscape Navigator 4 der Fall war.

function anim(){

document.all.logo.style.posLeft = document.body.clientWidth +
     document.body.scrollLeft

 – 89

document.all.logo.style.posTop = document.body.scrollTop

setTimeout("anim()", 500)
}

Abbildung 17.5  Das Galileo-Logo als immer sichtbares Werbebanner

Zum Abschluss dieses Beispiels (und dieses Kapitels) noch einmal das komplette Listing wie Sie es auf der Buch-CD finden.

<HTML>
<HEAD>
<TITLE>Werbebanner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   document.all.logo.style.visibility="visible"
   anim()
}
function anim(){
   document.all.logo.style.posLeft = document.body.clientWidth +
     document.body.scrollLeft – 89
   document.all.logo.style.posTop=document.body.scrollTop
   setTimeout("anim()", 500)
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Werbebanner</H1>
<DIV ID="logo" STYLE="visibility:hide;position:absolute">
<A HREF="http://www.galileo-press.de">
<IMG SRC="logo.gif" BORDER="0"></A>
</DIV>
<SCRIPT LANGUAGE="JavaScript"><!--
for (var i=0; i<30; i++)
   document.write("F&uuml;lltext")
for (i=0; i<3; i++){
   for (var j=0; j<10; j++)
      document.write("<"+"BR"+">")
   document.write("F&uuml;lltext")
}
//--></SCRIPT>
</BODY>
</HTML>

17.3 Fragen & Aufgaben

1.	Gehen Sie zu dem Beispiel mit den zwei verschachtelten Layern zurück. Wie könnte man von der Schaltfläche aus auf das Hauptdokument zugreifen?
2.	Ändern Sie das Beispiel mit dem animierten Logo so, dass a) das Logo von rechts einschwebt, b) es diagonal von links oben kommt.
3.	Ändern Sie das permanente Werbebanner so um, dass es auf Mausklick verschwindet.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 18 DHTML III: Netscape 6
			18.1 Grundlagen
			18.2 Beispiele
			18.3 Fragen & Aufgaben

Kapitel 18 DHTML III: Netscape 6

Überhaupt hat der Fortschritt das an sich,

dass er viel größer ausschaut, als er ist.

– Johann Nepomuk Nestroy

Spätsommer 2000. Nach langem Hickhack veröffentlicht Netscape ziemlich überraschend Version 6 seines Browsers. Zunächst erschien eine Preview Release 1, dann eine Preview Release 2, und schließlich Version 6.0. Die Fachwelt war erstaunt, schließlich ließ das unter www.mozilla.org zur Verfügung stehende Open-Source-Pendant in Sachen Stabilität und Zuverlässigkeit nur Übles vermuten. Die Veröffentlichung wurde von einem großen Medien-Hype begleitet, denn der Internet Explorer hatte den Netscape Navigator in Sachen Verbreitung mittlerweile deutlich überholt, und viele Beobachter sahen in der Veröffentlichung des Netscape 6 eine Möglichkeit, die Microsoft-Bastion zu erstürmen (genauer gesagt handelt es sich um eine Netscape-Bastion, die mittlerweile von Microsoft gestürmt worden war). Und der Netscape 6 wäre dazu wohl auch in der Lage – wäre er stabil, doch das ist momentan leider noch nicht der Fall. In Zukunft wird sich da noch viel tun, so viel ist gewiss.

Das Problem liegt an einer anderen Stelle. Aufgrund des erwähnten Hype wurde der neue Netscape von vielen Benutzern installiert. DHTML-Seiten, die sich mittlerweile ja großer Beliebtheit erfreuen, sind jedoch auf Internet Explorer ab Version 4 sowie auf Netscape Navigator 4 ausgerichtet, der Netscape 6 bleibt hier außen vor. Aus mangelndem Wissen und/oder fehlender Literatur haben bis dato auch nur sehr wenige Websitebetreiber ihre Seiten umgestellt, sodass sie auch mit dem Netscape 6 funktionieren. Zumindest der Punkt fehlender Literatur sollte mit diesem Buch behoben sein. Es ist ja gar nicht einmal viel, was verändert werden muss, und Sie finden die notwendigen Informationen in diesem und im nächsten Kapitel.

Vom Kapitelaufbau orientieren wir uns an den beiden vorhergehenden Kapiteln. Zunächst legen wir die Grundlagen für den Zugriff dar, und dann exerzieren wir die bestehenden Beispiele noch einmal durch – diesmal aber für Netscape 6. Aus diesem Grund sind die Beschreibungen bei den Beispielen selbst eher kurz gefasst, denn Sie wissen ja bereits, wie der Hase prinzipiell läuft. Auf die Anpassung für Netscape 6 kommt es an, und hierauf wird jeweils explizit eingegangen.

Eines der Beispiele, das Drag&Drop-Beispiel, funktioniert unter dem Netscape 6 noch nicht so wie vorgesehen. Ein Bug würde eine komplett andere Implementierung erfordern, weshalb wir das Beispiel weglassen.

18.1 Grundlagen

Das DOM des Netscape 6 ähnelt dem des Internet Explorer 5.x sehr stark, was auch kein Wunder ist – orientieren sich beide Modelle ja mehr oder weniger stark an der W3C-Empfehlung. Demnach kann auf alles, was zwischen Tags eingeschlossen ist, per JavaScript zugegriffen werden, beispielsweise auf die Schriftfarbe eines Absatzes.

18.1.1 HTML-Tags

Auch beim Netscape 6 ist der ID-Parameter wichtig, um bequem auf einzelne Elemente zugreifen zu können:

<P ID="Galileo">Galileo Press</P>

Dieser Absatz ist jetzt mit der ID Galileo assoziiert und Sie können mit JavaScript darauf zugreifen. Wie das geht, erfahren Sie in Kürze.

So etwas wie Layer gibt es beim Netscape 6 auch. Sie verwenden den altbekannten Tag <DIV>. Der <LAYER>-Tag wird von Netscape 6 nicht mehr unterstützt. Er wird in der Praxis ignoriert, d. h., das alles, was innerhalb dieses Tags steht, zwar angezeigt wird, aber Sie können über die ID des Layers nicht auf dessen Inhalt zugreifen.

<DIV ID="DIV1">
<!-- HTML-Kommandos etc. -->
</DIV>

Dem <DIV>-Tag gibt man oft einen STYLE-Parameter mit, um beispielsweise dessen Inhalt unsichtbar zu machen.

18.1.2 Objektzugriff

Das document-Objekt hat unter Netscape 6 die praktische Methode getElementById(). Dieser wird als Parameter der Wert des ID-Attributs des entsprechenden Tags übergeben, und sie liefert dafür das entsprechende Element zurück. Über die style-Eigenschaft des Elements können Sie dann das Aussehen des Elements beeinflussen.

Mit dem folgenden Code macht man beispielsweise den Layer "DIV1" aus dem obigen Beispiel unsichtbar:

document.getElementById("DIV1").style.visibility = "hidden"

Diese Syntax ist natürlich insofern verlockend, als dass Sie als Wert für den ID-Parameter auch Leer- und Sonderzeichen verwenden können. Im Sinne der Kompatibilität zu den anderen Browsern sollten Sie dies aber tunlichst vermeiden!

Um festzustellen, ob ein bestimmter Browser die Methode getElementById überhaupt unterstützt, können Sie wie gehabt eine if-Abfrage verwenden:

if (document.getElementById){
   //Code für Netscape 6
}

	Auch der Internet Explorer ab Version 5 kennt document.getElementById. Wie Sie einen Netscape 6 von einem IE 5.x unterscheiden, erfahren Sie im nächsten Kapitel!

18.2 Beispiele

Im Folgenden finden Sie fast alle der bekannten Beispiele aus den beiden vorhergehenden Kapitel, diesmal für den Netscape 6 ausgerichtet. Hier noch einmal das Versprechen: Im nächsten Kapitel werden wir tatsächlich browserübergreifend.

18.2.1 Animiertes Logo

Das animierte Logo ist das erste Beispiel, das wir auf den neuesten Netscape-Browser portieren möchten. Hier zunächst der HTML-Code, natürlich mit einem <DIV>-Element:

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

Obwohl dies das erste Beispiel ist, gibt es hier schon ein wenig babylonische Verwirrung. Der Zugriff auf die Objekteigenschaften geschieht wie beim Internet Explorer: style.eigenschaft. Der große Pferdefuß: Erhält man die Koordinaten der linken oberen Ecke des <DIV>-Elements mit posLeft und posTop, so verwendet Netscape 6 hier die Eigenschaftennamen, die Sie schon aus Kapitel 16 kennen: left und top. Damit geht der Netscape 6 übrigens mit der W3C-Empfehlung konform, der Internet Explorer kocht hier ein eigenes Süppchen.

Es sind also die folgenden Schritte zu tun:

1.	Ausgangsbasis ist das für den Internet Explorer angepasste Skript.
2.	Der Zugriff auf die Objekte geschieht jetzt mit document.getElementById.
3.	Die x- und y-Koordinate der linken oberen Ecke des <DIV>-Elements wird wie beim Netscape Navigator bestimmt.

Wenn Sie diese Änderungen nun vornehmen, werden Sie feststellen, dass das Skript nicht wie gewünscht läuft. Der Grund: Die Eigenschaften top und left sind keine nummerischen Werte, sondern Strings. Sie enthalten Werte wie beispielsweise "200px" für 200 Pixel. Es macht dem JavaScript-Interpreter nichts aus, wenn Sie nummerische Werte zuweisen – die Umwandlung geschieht automatisch –, aber wenn Sie wie im Beispiel mit den Werten rechnen möchten, müssen Sie sie zunächst in Integer-Werte umwandeln. Dies geht mit der Funktion parseInt.

Das Skript sieht dann folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   if (document.getElementById)
      document.getElementById("logo").style.left = "-200px"
   //Animation starten
   animate()
}
function animate(){
   if (parseInt(document.getElementById("logo").style.left)>0)
      document.getElementById("logo").style.left = 0
   if (parseInt(document.getElementById("logo").style.left)<0){
      document.getElementById("logo").style.left =
         parseInt(document.getElementById("logo").style.left) + 3
      setTimeout("animate()", 50)
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

Abbildung 18.1  Das Logo im Anflug von links

18.2.2 Sichtbar und unsichtbar

Als nächstes wird das Beispiel mit den Registern angepasst. Im Vergleich zur Lösung für den Internet Explorer ändert sich kaum etwas. Wieder wird getElementById eingesetzt, der Rest bleibt im Prinzip gleich:

<HTML>
<HEAD>
<TITLE>Register</TITLE>
<STYLE TEXT="text/css"><!--
A {color:black; text-decoration:none}
--></STYLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   var layer_x = document.getElementById("register1").style.left
   var layer_y = document.getElementById("register1").style.top
   document.getElementById("register2").style.left = layer_x
   document.getElementById("register2").style.top = layer_y
   document.getElementById("register2").style.visibility = "hidden"
   document.getElementById("register3").style.left = layer_x
   document.getElementById("register3").style.top = layer_y
   document.getElementById("register3").style.visibility = "hidden"
}
function register(n){
   for (var i=1; i<=3; i++){
      var visi = (i==n) ? "visible" : "hidden"
      document.getElementById("register"+i).style.visibility = visi
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<TABLE><TR>
<TD BGCOLOR="red">
   <A HREF="javascript:register(1)">Register 1</A>
</TD>
<TD BGCOLOR="green">
   <A HREF="javascript:register(2)">Register 2</A>
</TD>
<TD BGCOLOR="blue">
   <A HREF="javascript:register(3)">Register 3</A>
</TD>
</TR></TABLE>
<DIV ID="register1" STYLE="position:absolute">
   <H3>Register 1</H3>
</DIV>
<DIV ID="register2" STYLE="position:absolute">
   <H3>Register 2</H3>
</DIV>
<DIV ID="register3" STYLE="position:absolute">
   <H3>Register 3</H3>
</DIV>
</BODY>
</HTML>

Abbildung 18.2  Registerreiter mit DHTML

	Beachten Sie, dass die Positionierung der Layer absolut sein sollte, damit die einzelnen Register auch direkt unterhalb der drei Links angezeigt werden!

18.2.3 Neuer Mauszeiger

Das Beispiel wird ebenso schnell umgesetzt wie die beiden vorherigen DHTML-Effekte. Die Ereignisbehandlung lehnt sich an der des Netscape Navigator an (Parameter e für Ereignisbehandlungsmethoden), der prinzipielle Elementzugriff am Internet Explorer (über ID-Attribut, nur eben unter Verwendung von getElementById), und der Namen der einzelnen Koordinaten wiederum am Netscape Navigator (left/top). Das wirkt zwar zunächst ein wenig verwirrend, aber nach ein paar Beispielen kennt man die Unterschiede im Schlaf.

<HTML>
<HEAD>
<TITLE>Mauszeiger</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   document.onmousemove=anim
}
function anim(e){
   document.getElementById("mauszeiger").style.left = e.pageX
   document.getElementById("mauszeiger").style.top = e.pageY
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Mauszeiger</H1>
<DIV ID="mauszeiger" STYLE="position:absolute"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

Abbildung 18.3  Das Galileo-Logo als Mauszeiger

18.2.4 Permanentes Werbebanner

Zum letzten Beispiel: auch hier gibt es prinzipiell nicht viel Neues. Da das Listing aber ein wenig länger ist, wollen wir hier – ähnlich wie im vorhergehenden Kapitel – schrittweise vorgehen. Zunächst muss in der Funktion init()der Layer sichtbar gemacht und anim() aufgerufen werden:

function init(){
   document.all.logo.style.visibility="visible"
   anim()
}

In der Funktion anim() wird wie zuvor die neue Position des Werbebanners berechnet, das Banner dorthin verschoben, und dann die Funktion via Timeout nach einer halben Sekunde erneut aufgerufen. Jedoch heißen die Eigenschaften, die beispielsweise die aktuelle Scrollposition des Browserfensters enthalten, beim Internet Explorer (und wohl auch beim Netscape 6) komplett anders als beim Netscape Navigator 4. Aus window.innerWidth (Breite des Browserfensters) wird document.body.clientWidth, und window.pageXOffset und window.pageYOffset finden in document.body. scrollLeft und document.body.scrollTop ihre Entsprechung. Der Rest bleibt beinahe gleich. Kleiner Unterschied am Rande: document.body. clientWidth arbeitet viel exakter als das Netscape-Pendant, man muss von diesem Wert also in der Tat nur die Breite der Grafik abziehen, und nicht etwas mehr, wie das noch beim Netscape Navigator 4 der Fall war.

function anim(){
   document.all.logo.style.posLeft = document.body.clientWidth +
     document.body.scrollLeft – 89
   document.all.logo.style.posTop = document.body.scrollTop}
   setTimeout("anim()", 500)
}

Abbildung 18.4  Das Galileo-Logo als immer sichtbares Werbebanner

Zum Abschluss dieses Beispiels (und dieses Kapitels) noch einmal das komplette Listing wie Sie es auf der Buch-CD finden.

<HTML>
<HEAD>
<TITLE>Werbebanner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   document.getElementById("logo").style.visibility="visible"
   anim()
}
function anim(){
   document.getElementById("logo").style.left =
      window.innerWidth + window.pageXOffset – 100
   document.getElementById("logo").style.top = window.pageYOffset
   setTimeout("anim()", 500)
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Werbebanner</H1>
<DIV ID="logo" STYLE="visibility:hide;position:absolute">
<A HREF="http://www.galileo-press.de"><IMG SRC="logo.gif" BORDER="0"></A>
</DIV>
<SCRIPT LANGUAGE="JavaScript"><!--
for (var i=0; i<30; i++)
   document.write("F&uuml;lltext")
for (i=0; i<3; i++){
   for (var j=0; j<10; j++)
      document.write("<"+"BR"+">")
   document.write("F&uuml;lltext")
}
//--></SCRIPT>
</BODY>
</HTML>

18.3 Fragen & Aufgaben

1.	Gehen Sie zu dem Beispiel mit den zwei verschachtelten Layern zurück. Wie könnte man von der Schaltfläche aus auf das Hauptdokument zugreifen?
2.	Ändern Sie das Beispiel mit dem animierten Logo so, dass a) das Logo von rechts einschwebt, b) es diagonal von links oben kommt.
3.	Ändern Sie das permanente Werbebanner so um, dass es auf Mausklick verschwindet.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 19 DHTML IV: Für alle Browser
			19.1 Animiertes Logo
			19.2 Drag&Drop
			19.3 Sichtbar und unsichtbar
			19.4 Neuer Mauszeiger
			19.5 Permanentes Werbebanner
			19.6 Fragen & Aufgaben

Kapitel 19 DHTML IV: Für alle Browser

Aber es ist auch noch nicht zu spät.

Durch Deutschland muss ein Ruck gehen.

– Roman Herzog, Berliner Rede vom 26.4.97

In den drei vorangegangenen Kapiteln wurde derselbe Kardinalfehler immer und immer wieder begangen: Die JavaScript-Programme waren jeweils nur bei etwa einem Drittel aller Browser funktionsfähig. Es ist jedoch nicht allzu schwer, die Beispiele sowohl für den Netscape Navigator als auch für den Internet Explorer (jeweils ab Version 4) funktionsfähig zu machen. In diesem Kapitel werden einige Methoden vorgeführt, mit denen man zwischen den Browsern unterscheiden kann, mit denen man aber auch einige Abkürzungen nutzen kann, damit man denselben Code – nur leicht modifiziert – nicht immer zweimal tippen muss. Eine Methode werden Sie in diesem Kapitel nicht finden – das wäre die Browsererkennung mit dem navigator-Objekt. Zwar funktioniert auch das, aber sie ist schrecklich ineffizient und mitunter nicht zukunftssicher. So unterstützt der Netscape Navigator 6 wie gesehen Layer überhaupt nicht mehr, um nur ein Beispiel zu nennen.

Aber zurück zu der Aufgabe, die Skripte aus den beiden vorhergehenden Kapiteln browserunabhängig zu machen. Die verschiedenen Strategien werden wieder anhand der fünf Beispiele vorgeführt. Wundern Sie sich also nicht, wenn Ihnen Teile des Codes arg bekannt vorkommen, und richten Sie Ihr Augenmerk auf die Details, die Abfragen also, mit denen – je nach Browser – die entsprechenden Kommandos ausgeführt werden.

In Sachen HTML-Code ist die Anpassung einfach. Sowohl der Internet Explorer als auch der Netscape Navigator als auch Netscape 6 unterstützen den <DIV>-Tag, sodass dieses permanent verwendet wird. Der <LAYER>-Tag kommt jetzt nicht mehr vor.

19.1 Animiertes Logo

Wenn Sie sich den Quellcode für die jeweiligen Browser ansehen, werden Sie feststellen, dass die Unterschiede eigentlich nur bei einer Sorte von Anweisungen auftreten. Jedes Mal nämlich, wenn auf die Position des <DIV>-Tags zugegriffen wird, unterscheiden sich die beiden Browser, und zwar folgendermaßen:

	Für den Internet Explorer verwenden Sie document.all.logo. style.posLeft bzw. document.all.logo.style.posTop.
	Für den Netscape Navigator verwenden Sie document.logo.left bzw. document.logo.top.
	Für den Netscape 6 verwenden Sie document.getElementById("logo"). style.left bzw. document.getElementById("logo").style.top.

Nun ist es leider nicht möglich, die Werte einmal auszulesen und in Variablen zu speichern, da immer der aktuelle Wert benötigt wird. Ein erster Ansatz besteht darin, den Zugriff als Zeichenkette zu speichern und dann den Befehl mittels eval() ausführen zu lassen. Dabei wird folgendermaßen festgestellt, ob der Browser document.all unterstützt, document.getElementById, oder nicht:

if (document.all){
   //Code für IE4, IE5.X
} else if (document.layers) {
   //Code für NN4.X
} else if (document.getElementById) {
   //Code für N6
}

Obwohl keine Layer im Dokument vorkommen, wird dennoch für die Abfrage if (document.layers) verwendet. Das hat den tieferen Sinn, dass bei obiger Abfrage nur dann irgendein Code ausgeführt wird, wenn es sich um einen Browser ab Version 4 handelt; bei älteren Versionen, beispielsweise dem Netscape Navigator 3, passiert nichts, da dort weder document.all noch document.layers noch document.getElementById unterstützt wird.

Der browser-unabhängige Skriptteil kann also folgendermaßen aussehen:

if (document.all)
   var x = "document.all.logo.style.posLeft"
 else if (document.layers)
   var x = "document.logo.left"
 else if (document.getElementById)
   var x = "document.getElementById('logo').style.left"
function init(){
   if (x)  //Wenn Variable x gesetzt
      eval(x + "= -200")
   //Animation starten
   animate()
}
function animate(){
   if (parseInt(eval(x))>0)
      eval(x + "= 0")
   if (parseInt(eval(x))<0){
      eval(x + " = parseInt(" + x +") + 3")
      setTimeout("animate()", 50)
   }
}

Hinweis

Beachten Sie, dass für den Netscape 6 zugleich berücksichtigt worden ist, dass die Koordinaten mit parseInt von Strings in Zahlenwerte umgewandelt werden müssen.

Der Netscape Navigator unterstützt beim <DIV>-Tag die relative Positionierung, Sie müssen also nicht die anfängliche Position des Logos auslesen, wie das noch beim Layer der Fall war.

Eine alternative Methode, auf die Position zuzugreifen, besteht darin, eine Funktion zu schreiben, mit der Sie die Werte auslesen und schreiben können. In dieser Funktion dann wird die Fallunterscheidung ausgeführt. Bei mehreren Zuweisungen sparen Sie sich so die Tipparbeit für mehrere Fallunterscheidungen.

function leselinks(){
   if (document.all)
      return document.all.logo.style.posLeft
   else if (document.layers)
      return document.logo.left
   else if (document.getElementById)
      return parseInt(document.getElementById("logo").style.left)
}
function setzelinks(n){
   alert("setting "+n)
   if (document.all)
      document.all.logo.style.posLeft = n
   else if (document.layers)
      document.logo.left = n
   else if (document.getElementById)
      document.getElementById("logo").style.left = n+"px"
}
function init(){
   if (document.all||document.layers||document.getElementById)
      //Wenn Browser ab v4
      setzelinks(-200)
   //Animation starten
   animate()
}
function animate(){
   if (leselinks()>0)
      setzelinks(0)
   if (leselinks()<0){
      setzelinks(leselinks() + 3)
      setTimeout("animate()", 50)
   }
}

Hier noch einmal der gesamte Code, inklusive HTML-Anteil. Ein animiertes Logo, das auf den drei großen Browsern anstandslos funktioniert.

<HTML>
<HEAD>
<TITLE>Animiertes Logo</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function leselinks(){
   if (document.all)
      return document.all.logo.style.posLeft
   else if (document.layers)
      return document.logo.left
   else if (document.getElementById)
      return parseInt(document.getElementById("logo").style.left)
}
function setzelinks(n){
   alert("setting "+n)
   if (document.all)
      document.all.logo.style.posLeft = n
   else if (document.layers)
      document.logo.left = n
   else if (document.getElementById)
      document.getElementById("logo").style.left = n+"px"
}
function init(){
   if (document.all||document.layers||document.getElementById)
      //Wenn Browser ab v4
      setzelinks(-200)
   //Animation starten
   animate()
}
function animate(){
   if (leselinks()>0)
      setzelinks(0)
   if (leselinks()<0){
      setzelinks(leselinks() + 3)
      setTimeout("animate()", 50)
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Animiertes Logo</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

19.2 Drag&Drop

Beim Drag&Drop-Beispiel müssen wir neben dem Zugriff auf die einzelnen Koordinaten von Maus und <DIV>-Element auch noch das unterschiedliche Event-Handling der beiden Browser betrachten. Fangen wir mit letzterem an: Während der Netscape Navigator die Ereignisse mit captureEvents() abfangen muss, muss man sich beim Internet Explorer nicht so weit verrenken. Um festzustellen, welcher Browser vorliegt, genügt es, beispielsweise das Vorhandensein der Methode capture Events() zu überprüfen:

var logo_x, logo_y
function leselinks(){
   if (document.all)
      return document.all.logo.style.posLeft
   else if (document.layers)
      return document.logo.left
}
function setzelinks(n){
   if (document.all)
      document.all.logo.style.posLeft = n
   else if (document.layers)
      document.logo.left = n
}
function leseoben(){
   if (document.all)
      return document.all.logo.style.posTop
   else if (document.layers)
      return document.logo.top
}
function setzeoben(n){
   if (document.all)
      document.all.logo.style.posTop = n
   else if (document.layers)
      document.logo.top = n
}
function init(){
   if (document.captureEvents)
      document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP
        |Event.MOUSEMOVE)
   document.onmousedown = setzestatus
   document.onmouseup = setzestatus
   document.onmousemove = dragdrop
   logo_x = leselinks()
   logo_y = leseoben()
}

Wie Sie sehen, wird hier das Lesen und Schreiben der Koordinaten des <DIV>-Containers mit Funktionen erledigt.

Doch zurück zur Ereignisbehandlung. In der Funktion setzestatus() wird einige Male die Art des Ereignisses bestimmt, entweder als e.type oder event.type. Da die Methoden gleich heißen, empfiehlt es sich hier, wie übrigens bereits im Kapitel »Events« beschrieben wurde, eine neue Variable einzuführen, um über diesen Variablenbezeichner auf das jeweilige Ereignis zuzugreifen.

Das zweite Problem besteht in der Abfrage der x- und y-Koordinate der Maus, während das Ereignis eintritt, sowie des Zielelements des Ereignisses (zur Erinnerung: target beim Netscape Navigator, srcElement beim Internet Explorer). Auch hier schreiben wir wieder eine Funktion, die das gewünschte Ergebnis zurückgibt.

Bleibt nur noch eine Frage: Wie wird festgestellt, welches Ereignismodell der verwendete Browser unterstützt? Auch diese Frage ist schnell mit einer Objektüberprüfung zu beantworten. Existiert window.Event, so hat man den Netscape Navigator, ansonsten den Internet Explorer.

Letztendlich muss man nur noch beachten, den Funktionen immer eine Variable e als Parameter zu übergeben. Diese Variable wird zwar nur vom Netscape Navigator benötigt, hat aber auf den Internet Explorer keinen Einfluss, und wir wollen ja Browser-Unabhängigkeit erreichen.

Wie wir bereits erwähnt haben, wurde dieses Beispiel nicht auf Netscape 6 portiert. Sehen Sie aber regelmäßig auf MyGalileo nach, denn dort werden Änderungen und neue Codebeispiele zuerst veröffentlicht!

var bereit = false
var maus_x, maus_y
function x_koord(e){
   if (window.Event)
      return e.pageX
   else
      return event.clientX
}
function y_koord(e){
   if (window.Event)
      return e.pageY
   else
      return event.clientY
}
function ziel(e){
   if (window.Event)
      return e.target
   else
      return event.srcElement
}
function setzestatus(e){
   var ev = (window.Event) ? e : window.event
   if (ev.type=="mouseup" ||
     (ev.type=="mousedown" && (e).name=="logogfx")){
      maus_x = x_koord(e)
      maus_y = y_koord(e)
      bereit = !bereit
      if (ev.type=="mousedown"){
         logo_x = leselinks()
         logo_y = leseoben()
      }
   }
}

Der letzte Teil, der noch überarbeitet werden muss, ist die Funktion dragdrop(). Dort kommen aber keine neuen Elemente vor, sodass hier gleich der gesamte Quellcode aufgeführt wird. Neuerungen sind wie immer in fetter Schrift dargestellt.

<HTML>
<HEAD>
<TITLE>Drag &amp; Drop</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var logo_x, logo_y
function leselinks(){
   if (document.all)
      return document.all.logo.style.posLeft
   else if (document.layers)
      return document.logo.left
}
function setzelinks(n){
   if (document.all)
      document.all.logo.style.posLeft = n
   else if (document.layers)
      document.logo.left = n
}
function leseoben(){
   if (document.all)
      return document.all.logo.style.posTop
   else if (document.layers)
      return document.logo.top
}
function setzeoben(n){
   if (document.all)
      document.all.logo.style.posTop = n
   else if (document.layers)
      document.logo.top = n
}
function init(){
   if (document.captureEvents)
      document.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP
| Event.MOUSEMOVE)
   document.onmousedown = setzestatus
   document.onmouseup = setzestatus
   document.onmousemove = dragdrop
   logo_x = leselinks()
   logo_y = leseoben()
}
var bereit = false
var maus_x, maus_y
function x_koord(e){
   if (window.Event)
      return e.pageX
   else
      return event.clientX
}
function y_koord(e){
   if (window.Event)
      return e.pageY
   else
      return event.clientY
}
function ziel(e){
   if (window.Event)
      return e.target
   else
      return event.srcElement
}
function setzestatus(e){
   var ev = (window.Event) ? e : window.event
   if (ev.type=="mouseup" ||
     (ev.type=="mousedown" && (e).name=="logogfx")){
      maus_x = x_koord(e)
      maus_y = y_koord(e)
      bereit = !bereit
      if (ev.type=="mousedown"){
         logo_x = leselinks()
         logo_y = leseoben()
      }
   }
}
function dragdrop(){
   if (bereit){
      var aktuell_x = x_koord(e)
      var aktuell_y = y_koord(e)
      setzelinks(logo_x + aktuell_x – maus_x)
      setzeoben(logo_y + aktuell_y – maus_y)
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<H3>Drag &amp; Drop</H3>
<DIV ID="logo" STYLE="position:relative"><IMG SRC="logo.gif"></DIV>
</BODY>
</HTML>

19.3 Sichtbar und unsichtbar

Das dritte Beispiel in den DHTML-Kapiteln ist besonders einfach, und an dieser Stelle soll zusätzlich eine neue Technik eingeführt werden. Die kritischen JavaScript-Befehle sind das Setzen der visibility-Eigenschaft des <DIV>-Containers. Zwar könnte man auch hier mit einer Zeichenkette und eval() arbeiten, aber es ist praktischer, in einer Variablen eine Referenz auf das Objekt zu speichern. Man kann dann auf die visibility-Eigenschaft mittels Objektreferenz.visibility zugreifen und spart sich alle weiteren Abfragen.

Die Variablendefinition geht wie folgt vonstatten:

if (document.all){
   var objref1 = document.all.register1.style
   var objref2 = document.all.register2.style
   var objref3 = document.all.register3.style
} else if (document.layers){
   var objref1 = document.register1
   var objref2 = document.register2
   var objref3 = document.register3
} else if (document.getElementById){
   var objref1 = document.getElementById("register1").style
   var objref2 = document.getElementById("register2").style
   var objref3 = document.getElementById("register3").style
}

Der Rest des Quellcodes ist dann schnell angepasst. Die Abfrage bzw. das Setzen der Koordinaten für die einzelnen <DIV>-Container erfolgt wie gehabt mit einer Funktion. Dabei kann hier schon die Variable objref1, objref2 oder objref3 verwendet werden. Am Beispiel der Funktion leselinks(n) wird das dargestellt. Als Parameter muss noch die Nummer des <DIV>-Containers übergeben werden, da es auf der HTML-Seite ja drei Stück davon gibt.

function leselinks(n){
   var obj = eval("objref"+n)
   if (document.all)
      return obj.posLeft
   else if (document.layers||document.getElementById)
      return obj.left
}

Es ist noch einiges an Tipparbeit zu leisten, bis man das Skript endlich kompatibel hat. Dann hat man allerdings eine browser-unabhängige Lösung und kann einige der Hilfsfunktionen oder -abfragen immer wieder verwenden.

<HTML>
<HEAD>
<TITLE>Register</TITLE>
<STYLE TEXT="text/css"><!--
A {color:black; text-decoration:none}
--></STYLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var objref1
var objref2
var objref3
function leselinks(n){
   eval("var obj = objref"+n)
   if (document.all)
      return obj.posLeft
   else if (document.layers||document.getElementById)
      return parseInt(obj.left)
}
function setzelinks(n, wert){
   eval("var obj = objref"+n)
   if (document.all)
      obj.posLeft = wert
   else if (document.layers||document.getElementById)
      obj.left = wert
}
function leseoben(n){
   eval("var obj = objref"+n)
   if (document.all)
      return obj.posTop
   else if (document.layers||document.getElementById)
      return obj.top
}
function setzeoben(n, wert){
   eval("var obj = objref"+n)
   if (document.all)
      obj.posTop = wert
   else if (document.layers||document.getElementById)
      obj.top = wert
}
function init(){
   if (document.all){
      objref1 = document.all.register1.style
      objref2 = document.all.register2.style
      objref3 = document.all.register3.style
   } else if (document.layers){
      objref1 = document.register1
      objref2 = document.register2
      objref3 = document.register3
   } else if (document.getElementById){
      objref1 = document.getElementById("register1").style
      objref2 = document.getElementById("register2").style
      objref3 = document.getElementById("register3").style
   }
   var layer_x = leselinks(1)
   var layer_y = leseoben(1)
   setzelinks(2, layer_x)
   setzeoben(2, layer_y)
   objref2.visibility = "hidden"
   setzelinks(3, layer_x)
   setzeoben(3, layer_y)
   objref3.visibility = "hidden"
}
function register(n){
   for (var i=1; i<=3; i++){
      var visi = (i==n) ? "visible" : "hidden"
      eval("var obj = objref"+i)
      obj.visibility = visi
   }
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="init()">
<TABLE><TR>
<TD BGCOLOR="red">
   <A HREF="javascript:register(1)">Register 1</A>
</TD>
<TD BGCOLOR="green">
   <A HREF="javascript:register(2)">Register 2</A>
</TD>
<TD BGCOLOR="blue">
   <A HREF="javascript:register(3)">Register 3</A>
</TD>
</TR></TABLE>
<DIV ID="register1" STYLE="position:relative">
   <H3>Register 1</H3>
</DIV>
<DIV ID="register2" STYLE="position:relative">
   <H3>Register 2</H3>
</DIV>
<DIV ID="register3" STYLE="position:relative">
   <H3>Register 3</H3>
</DIV>
</BODY>
</HTML>

19.4 Neuer Mauszeiger

Das Mauszeigerbeispiel bot schon in den vorherigen Kapitel kaum etwas Neues, sondern hat die bereits bekannten Techniken nur anders angewandt. Grund genug, auch hier nur die neue Version des Skripts abzudrucken. Sie werden übrigens die Funktionen setzelinks() und setzeoben() von oben wieder finden, die nur leicht an das Beispiel angepasst wurden.

<HTML>
<HEAD>
<TITLE>Mauszeiger</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   if (window.Event)
      document.captureEvents(Event.MOUSEMOVE)
   document.onmousemove=anim
}
function setzelinks(n){
   if (document.all)
      document.all.mauszeiger.style.posLeft = n
   else if (document.layers)
      document.mauszeiger.left = n
   else if (document.getElementById)
      document.getElementById("mauszeiger").style.left = n
}
function setzeoben(n){
   if (document.all)
      document.all.mauszeiger.style.posTop = n
   else if (document.layers)
      document.mauszeiger.top = n
   else if (document.getElementById)
      document.getElementById("mauszeiger").style.top = n
}
function anim(e){
   var x = (window.Event) ? e.pageX : event.clientX
   var y = (window.Event) ? e.pageY : event.clientY
   setzelinks(x)
   setzeoben(y)
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Mauszeiger</H1>
<DIV ID="mauszeiger" STYLE="position:absolute">
<IMG SRC="logo.gif">
</DIV>
</BODY>
</HTML>

19.5 Permanentes Werbebanner

Das letzte Beispiel war das immer sichtbare Werbebanner, das natürlich auch als Sitemap oder ähnliches zweckentfremdet werden kann. Da in diesem Beispiel keine Ereignisse eingesetzt werden, spart man sich schon einmal den halben Aufwand bei der Cross-Browser-Programmierung. Lediglich auf die einzelnen Objekteigenschaften muss in Abhängigkeit vom verwendeten Browser zugegriffen werden. Auch hier verwenden wir wieder setzelinks() und setzeoben(), und arbeiten sonst mit den schon gewohnten Fallunterscheidungen: if(document.layers), if(document.all) und if(document.getElementById).

<HTML>
<HEAD>
<TITLE>Werbebanner</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   if (document.layers)
      document.logo.visibility="visible"
   else if (document.all)
      document.all.logo.style.visibility="visible"
   else if (document.getElementById)
      document.getElementById("logo").style.visibility="visible"
   anim()
}
function setzelinks(n){
   if (document.all)
      document.all.logo.style.posLeft = n
   else if (document.layers)
      document.logo.left = n
   else if (document.getElementById)
      document.getElementById("logo").style.left = n
}
function setzeoben(n){
   if (document.all)
      document.all.logo.style.posTop = n
   else if (document.layers)
      document.logo.top = n
   else if (document.getElementById)
      document.getElementById("logo").style.top = n
}
function anim(){
   if (document.layers){
      var x=window.innerWidth+window.pageXOffset-100
      var y=window.pageYOffset
   } else if (document.all){
      var x=document.body.clientWidth+document.body.scrollLeft-89
      var y=document.body.scrollTop
   } else if (document.getElementById){
      var x=window.innerWidth+window.pageXOffset-100
      var y=window.pageYOffset
   }
   setzelinks(x)
   setzeoben(y)
   setTimeout("anim()", 500)
}
//--></SCRIPT>
</HEAD>
<BODY BGCOLOR="white" onLoad="init()">
<H1>Werbebanner</H1>
<DIV ID="logo" STYLE="visibility:hide;position:absolute">
<A HREF="http://www.galileo-press.de"><IMG SRC="logo.gif" BORDER="0"></A>
</DIV>
<SCRIPT LANGUAGE="JavaScript"><!--
for (var i=0; i<30; i++)
   document.write("F&uuml;lltext")
for (i=0; i<3; i++){
   for (var j=0; j<10; j++)
      document.write("<"+"BR"+">")
   document.write("F&uuml;lltext")
}
//--></SCRIPT>
</BODY>
</HTML>

Zum Ende dieses Kapitels noch ein kurzer Ausblick: Die Möglichkeiten von DHTML sind fast unendlich. Für weitere Informationen lohnt es sich – wie bereits erwähnt – den Katalog von Galileo Press zu studieren. An dieser Stelle kann leider kein ausführlicher Einstieg in die Materie gegeben werden, da dies Umfang und Zielsetzung dieses Buches sprengen würde. Aus demselben Grund können hier auch nicht alle Inkompatibilitäten der verschiedenen Browser aufgelistet werden. Das Ziel der letzten vier Kapitel war es, einen browser-unabhängigen Einstieg in die Materie zu geben. Mit den vorgestellten Techniken, der Referenz und ein wenig Fantasie und Freude am Ausprobieren können Sie beeindruckende Ergebnisse erzielen.

19.6 Fragen & Aufgaben

1.	Gehen Sie zu dem Beispiel mit den zwei verschachtelten Layern zurück. Wie können Sie von der Schaltfläche aus auf das Hauptdokument zugreifen?
2.	Ändern Sie das Beispiel mit dem animierten Logo so, dass a) das Logo von rechts einschwebt, b) es diagonal von links oben kommt.
3.	Ändern Sie das permanente Werbebanner so um, dass es auf Mausklick verschwindet.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 20 Java
			20.1 Allgemeines
			20.2 Java und das WWW
			20.3 Java ohne Applet
			20.4 Fragen & Aufgaben

Kapitel 20 Java

Hab ich doch, Freunde, immer mit Recht den Caffé gehasst.

– Johann Wolfgang von Goethe

Wenn Sie sich so weit durch das Buch durchgekämpft haben, werden Sie festgestellt haben, dass man mit JavaScript tolle Effekte realisieren kann. Wozu braucht man überhaupt noch Java? Nun, die Antwort fällt recht lang aus, angefangen bei der Möglichkeit des Dateizugriffs über Datenbankoperationen bis hin zu den grafischen Darstellungsmöglichkeiten. Java hat also durchaus seine Existenzberechtigung im World Wide Web. Aus diesem Grund findet Java auch in diesem Buch Erwähnung. Man kann nämlich mit JavaScript die Java-Programme in einem HTML-Dokument in gewisser Hinsicht ansteuern. So können sich Java und JavaScript gut ergänzen.

20.1 Allgemeines

Eines gleich vorweg: Dieses Buch soll keine Java-Einführung sein, es geht hier lediglich um JavaScript. Um dieses Kapitel voll verständlich zu machen, benötigt man einige Zeilen Java-Code, das lässt sich nicht vermeiden. Es wurde aber versucht, diesen Teil so kurz und so einfach wie möglich zu halten. Da sich die Syntax von Java und JavaScript zum Teil ziemlich ähnelt, können Sie auch ohne Java-Erfahrung – aber mit inzwischen tiefschürfenden JavaScript-Kenntnissen – die vorgestellten Beispiele nachvollziehen. Auch wenn Sie vielleicht nicht jeden einzelnen Befehl verstehen, sollte wenigstens die prinzipielle Vorgehensweise klar werden. Um ein paar einführende Worte kommt man eben nicht herum.

20.1.1 Wie funktioniert Java?

Java ist eine plattformunabhängige Programmiersprache, deren Syntax sich an die Programmiersprache C++ anlehnt. Java-Programme werden in einen so genannten Byte-Code kompiliert. Die meisten Internet-Browser haben eine Java Virtual Machine (Java VM oder auch JVM), welche diesen Bytecode auf der jeweiligen Plattform interpretiert und die Befehle ausführt. Der besondere Vorteil besteht darin, dass der Byte-Code auf jeder Plattform identisch ist. Daher rührt die Bezeichnung »plattformunabhängige Sprache«. Einzig und allein die Virtual Machines unterscheiden sich. Das Konzept von Java heißt auch »written once, runs everywhere« – einmal programmiert, funktioniert es überall. Insbesondere müssen Sie sich nicht um die Portierung Ihres Codes auf die verschiedensten Plattformen kümmern, das haben die Hersteller der Virtual Machine schon erledigt.

Der Nachteil von Java liegt auf der Hand: Da das Programm nicht betriebssystemspezifisch kompiliert worden ist, muss der Byte-Code von der VM interpretiert werden, und das dauert recht lange. Aus diesem Grund sind kompilierte Programme immer noch etwas schneller. Der Vorsprung schwindet allerdings, da die Entwicklung der Virtual Machines fortschreitet, und so genannte JIT-Compiler (Just-In-Time-)Compiler in der Lage sind, Java-Code nicht anfangs am Stück zu interpretieren, sondern immer dann, wenn das entsprechende Programmsegment zur Ausführung kommt. Die wahren technischen Zusammenhänge sind weitaus komplizierter, aber Sie wollen sicherlich so schnell wie möglich zum Thema JavaScript zurückkommen, also weiter im Text.

Kompilierte Java-Programme haben die Endung .class. Ein für den nicht-kommerziellen Einsatz kostenloser Compiler ist auf der Website des Java-Erfinders Sun unter http://java.sun.com zu finden – halten Sie nach dem Java Development Kit, kurz JDK, Ausschau.

Java-Programme werden mit dem <APPLET>-Tag in die HTML-Seite eingebunden. Im Parameter CODE wird der vollständige Name der .class-Datei angegeben, in den Parametern WIDTH und HEIGHT werden – wie beim <IMG>-Tag auch – die Ausmaße des Applets auf dem Bildschirm angegeben. Wichtig ist wie immer das NAME-Attribut, Formular-Experten wissen, warum:

<APPLET CODE="applet.class" NAME="Applet" WIDTH=300 HEIGHT=200>
Ihr Browser unterstützt kein Java oder Sie haben es
ausgeschaltet</APPLET>

	Der Text zwischen <APPLET> und </APPLET> wird genau dann angezeigt, wenn der Browser des Benutzers kein Java unterstützt. (Dies ist beispielsweise bei älteren Versionen des Netscape Navigator für Windows 3.x oder bei Macintosh-Versionen für ältere Systeme der Fall.)

20.1.2 Kurzeinführung in Java

In den folgenden Absätzen werde ich das Grundkonzept von Java grob erklären. Vor allem die Java-Kenner mögen über Auslassungen, Ungenauigkeiten und Vereinfachungen hinwegsehen. Das Thema dieses Buches ist und bleibt JavaScript, und Java wird nur so weit erläutert, wie es für das Verständnis dieses Kapitels nötig ist.

In Java sind alle Daten in Objekten organisiert, so ähnlich wie in JavaScript ja auch – so weit, so gut. Anstelle von Objekt nennt man eine Ansammlung von Methoden und Eigenschaften innerhalb von Java Klasse. Ein Grundgerüst einer Klasse sieht folgendermaßen aus:

class klassenname{
// irgendwelche Komandos
}

Jede Klasse kann Methoden und Eigenschaften enthalten. Die Besonderheit ist, dass der Typ des Rückgabewerts jeder Methode im Methodenkopf direkt angegeben wird, was ein großer Unterschied im Vergleich zu JavaScript ist, das sich im Hinblick auf Variablentypen sehr flexibel verhält. Beispiele für solche Typen sind int für Zahlenwerte, boolean für Wahrheitswerte – und void, wenn nichts zurückgegeben wird. Auch bei Parametern für die Methoden muss der Typ angegeben werden.

public class klassenname{
   private int quadrat(int i){
      return i*i;
   }
   public pythagoras(int kathete1, int kathete2){
      int summe = quadrat(kathete1) + quadrat(kathete2);
      return Math.sqrt(summe);
   }
}

Eine weitere Eigenheit von Java besteht darin, dass nicht alle Methoden und Eigenschaften von überall aus abgefragt werden können. Im obigen Beispiel kann die Funktion quadrat(), die mit dem Schlüsselwort private gekennzeichnet ist, nur innerhalb dieser Klasse aufgerufen werden, also nicht von anderen Klassen aus. Die Funktion pythagoras(), die übrigens die Länge der Hypotenuse in einem rechtwinkligen Dreieck berechnet und dabei quadrat() benutzt, ist durch das Schlüsselwort public gekennzeichnet. Dieses gibt an, dass diese Methode von überall aus aufgerufen werden darf – auch von JavaScript aus!

Die wohl größte Fehlerquelle am Anfang: Jeder Befehl muss mit einem Semikolon beendet werden! Da wünscht man sich manchmal das nicht so strenge JavaScript herbei.

20.2 Java und das WWW

Um ein Java-Programm im Browser betrachten zu können, muss es sich um ein sogenanntes Applet handeln. Dadurch ändert sich der schematische Aufbau ein wenig. Die genauen Details sollen uns aber nicht interessieren. Auf der CD zu diesem Buch finden Sie das kompilierte Applet, und Sie können es auch direkt ausprobieren. Bei MyGalileo finden Sie es übrigens auch.

20.2.1 Ein Beispiel-Applet

Das folgende Applet wird in diesem Kapitel als Beispiel verwendet. Es zeichnet zu Anfang einen roten Kreis, denn die Methode paint() wird beim Laden des Applets aufgerufen. Außerdem gibt es da noch eine Methode auswahl(), die anscheinend ein paar Variablen des Applets verändert und dann wieder paint() aufruft. Wenn Sie das ganze selbst ausprobieren wollen, müssen Sie den Java-Quelltext unter demselben Namen wie die Klasse abspeichern. Letztere heißt ball, also wird der Quelltext unter ball.java abgespeichert.

import java.applet.*;
import java.awt.*;
public class ball extends Applet{
   private int radius = 100;
   private Color farbe = Color.red;
   public void paint(Graphics g){
      g.setColor(Color.white);
      g.fillRect(0, 0, 449, 449);
      g.setColor(farbe);
      g.fillOval(225-radius, 225-radius, 2*radius-1, 2*radius-1);
   }
   public void auswahl(int neuer_radius, String farbcode){
      this.radius = neuer_radius;
         if (farbcode.equals("rot"))
            {this.farbe=Color.red;} else
         if (farbcode.equals("blau"))
            {this.farbe = Color.blue;} else
         if (farbcode.equals("gruen"))
            {this.farbe = Color.green;} else
               this.farbe = Color.black;
      paint(getGraphics());
   }
}

20.2.2 HTML-Integration

Das Ziel dieses Beispiels soll es sein, mit JavaScript dieses Applet anzusteuern. Dazu soll folgendes HTML-Grundgerüst als Basis dienen. In einem Formular kann man den Radius des Kreises eingeben und via Radiobutton die Farbe des Kreises auswählen.

<HTML>
<HEAD>
<TITLE>Java und JavaScript</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function java(){
   alert("Bedaure, Ihr Browser ist zu alt")
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.1"><!--
function java(f){
   if (navigator.javaEnabled()){
      var radius = parseInt(f.radius.value)
      if (isNaN(radius)||radius>200||radius<1)
         radius = 200
      var farbe = f.farbe[0].checked ? "rot" :
        (f.farbe[1].checked ? "blau" : "gruen")
      document.ball.auswahl(radius, farbe)
   } else
   alert("Bedaure, bei Ihrem Browser ist Java deaktiviert")
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Java und JavaScript</H3>
<APPLET CODE="ball.class" NAME="ball" WIDTH=450 HEIGHT=450>
  Ihr Browser unterstützt kein Java!</APPLET>
<FORM>
Radius (von 1 bis 200): <INPUT TYPE="TEXT" NAME="radius"
SIZE=3><BR>
Farbe:
 <INPUT TYPE="RADIO" NAME="farbe" VALUE="rot"> rot -
 <INPUT TYPE="RADIO" NAME="farbe" VALUE="blau"> blau -
 <INPUT TYPE="RADIO" NAME="farbe" VALUE="gruen"> grün<BR>
<INPUT TYPE="BUTTON" VALUE="Zeichnen" onClick="java(this.form)">
</FORM>
</BODY>
</HTML>

Abbildung 20.1  Java-Applets mit JavaScript steuern

Nüchtern analysiert, erledigt die Funktion java() Folgendes: Zuerst wird navigator.javaEnabled() abgefragt. Diese Methode gibt an, ob der Benutzer im Browser Java aktiviert hat. Ein Nebeneffekt dieser Abfrage ist, dass die Java Virtual Machine gestartet wird, sofern das noch nicht geschehen ist. Vor allem beim Netscape Navigator 4 dauert das eine Weile, bei der Vorgängerversion passierte der VM-Start noch beim Laden des Browsers. In diesem Fall fällt das aber nicht ins Gewicht, da aufgrund des Applets innerhalb der HTML-Seite die Virtual Machine ohnehin schon gestartet worden ist.

Als nächstes liest die Funktion java() die Formularwerte ein und wandelt die Eingabe im Radius-Eingabefeld in eine Zahl zwischen 1 und 200 um.

	Die Umwandlung der Zeichenkette in eine Zahl ist prinzipiell gar nicht nötig, das geschieht automatisch. Allerdings musste ja noch der Radius gegebenenfalls innerhalb des Intervalls von 1 bis 200 gebracht werden.

Die interessanteste Zeile der Funktion ist:

document.ball.auswahl(radius, farbe)

Mit document.ball wird auf das Applet in der HTML-Seite zugegriffen, denn dieses hat das NAME-Attribut ball. Mit document.ball.auswahl() greift man also auf die Methode auswahl() im Applet zu. Generell gilt, dass man mit JavaScript auf alle Methoden des Applets zugreifen kann, sofern sie als public deklariert worden sind. Den Rest erledigt in diesem Beispiel das Applet. Die entsprechenden Parameter werden verändert, und der Kreis wird neu gezeichnet.

Der Netscape Navigator bietet des weiteren die Möglichkeit an, von Java-Programmen aus JavaScript-Objekte anzusprechen. Diese Möglichkeit bietet der Microsoft Internet Explorer nicht, und die Funktionalität kann man auch in der anderen Richtung bereitstellen (also von JavaScript aus geeignete Java-Methoden aufrufen).

20.3 Java ohne Applet

Man braucht nicht unbedingt ein Applet, um Java-Methoden von JavaScript aus aufzurufen. Gewisse Grundobjekte von Java können auch direkt aufgerufen werden. Beispielsweise hat man so zu Zeiten des Netscape Navigator 3 versucht, die Höhe und Breite des Bildschirms zu bestimmen, weil es damals screen.width und screen.height noch nicht gab, wohl aber entsprechende Java-Methoden. Diese Vorgehensweise wird jedoch nur relativ selten verwendet; meistens benötigt man nicht nur ein mitgeliefertes Java-Objekt, sondern gleich eine (programmierte) Java-Funktion, und dann muss man ein Applet verwenden.

	Wenn Sie eine (programmierte) Java-Funktion verwenden wollen, beispielsweise eine Nullstellenberechnung oder andere mathematische Berechnungen (was mit den JavaScript-Datentypen nicht immer akkurate Ergebnisse liefert), so können Sie ein 1 x 1 Pixel großes Applet verwenden. Das Applet selbst soll keine Aktivität zeigen und fällt aufgrund seiner Größe nicht sonderlich auf, aber Sie können die öffentlichen Funktionen aufrufen und die Ergebnisse verwenden.

20.3.1 Exemplarische Java-Objekte

Ein mögliches Beispiel ist die Java-Variante eines luxuriöseren Arrays, dort Vektor genannt. Die Klasse heißt Vector und wird von JavaScript aus (und übrigens auch von Java) mit java.util.Vector angesprochen.

Mit den folgenden Befehlen wird eine Instanz des Java-Typs Vector erzeugt. Diese Instanz besitzt als Methoden alle als public deklarierten Methoden des Java-Objekts:

if (navigator.javaEnabled())
   var v = new java.util.Vector()

Dieser Vektor hat im Gegensatz zu einfachen JavaScript-Arrays Funktionen zum einfachen Entfernen und Hinzufügen von Elementen. Zwar gibt es ab dem Netscape Navigator 3 und dem Internet Explorer 4 (also JavaScript 1.1) ein paar neue Möglichkeiten für JavaScript-Arrays, mit denen man diese neue Funktionalität ebenfalls erreichen kann, aber das ist nicht Thema dieses Kapitels.

Ein weiteres interessantes Java-Objekt ist Hashtable. Das ist auch ein Array, aber die Indizes sind nicht nummerisch, sondern können auch Zeichenketten sein. Man kann beispielsweise sehr einfach eine Abbildung von Monatsnamen auf Monatszahlen machen.

Im folgenden Beispiel sollen sowohl Vector als auch Hashtable verwendet werden, letztere jedoch nur in der Version bei MyGalileo. Stellen Sie sich vor, Sie befinden sich in Las Vegas an einem Blackjack-Tisch. Sie haben ein einzelnes Kartenspiel vor sich1  und müssen es mischen und an die Spieler verteilen. Außerdem soll bei jedem Spieler angegeben werden, wie viele Punkte er mit seinen Karten erreicht hat. Eine vollständige Implementierung des Spiels ist Ihnen überlassen, oder schauen Sie hin und wieder bei MyGalileo vorbei.

20.3.2 Blackjack

Zur Vorbereitung in aller Kürze die wichtigsten Blackjack-Regeln:

	Das Kartenspiel enthält in den vier Farben (Herz, Karo, Pik, Kreuz) die Nummernkarten 2 bis 10 sowie die Bildkarten Bube, Dame, König und das As. Insgesamt erhält man so ein Spiel (Deck) aus 52 Karten.
	Das Ziel des Spiels ist es, so nahe wie möglich an 21 Punkte heranzukommen, vor allem näher als die Bank, ohne jedoch die 21 Punkte zu überschreiten (das hat den sofortigen Verlust zur Folge).
	Eine Nummernkarte zählt so viele Punkte, wie auf der Karte stehen. Eine Bildkarte zählt zehn Punkte. Ein As zählt 11 Punkte, außer, der Spieler würde mit seinen Karten über 21 Punkte kommen (»überbieten«), dann zählt es einen Punkt. Hat ein Spieler also ein As und eine 7, so hat er 18 Punkte. Zwei Asse zählen als 12 Punkte, denn würden beide Asse mit 11 Punkten zählen, hätte der Spieler 22 Punkte und damit überboten. Analog zählen drei Asse als 13 Punkte.
	Hat der Spieler ein As und eine Karte, die zehn Punkte wert ist (eine Bildkarte oder die Zehn), so hat er einen »Blackjack«.
	Am Anfang des Spiels bekommt jeder Spieler zwei Karten zugeteilt.
	Weitere Regeln, etwa, was die Bank zu tun hat und wie man mehr Karten bekommen kann, sind nicht Thema dieses Buchs.

Die Strategie für die Blackjack-Applikation ist die folgende:

	In einer Schleife wird ein Array mit allen möglichen Karten gefüllt.
	Die Karten werden gemischt, indem immer ein Element aus dem Array zufällig ausgewählt, einem Spieler zugeteilt und aus dem Array entfernt wird.
	Bei jedem Spieler wird die Punktzahl seiner beiden Karten bestimmt. Diese Punktzahl wurde zuvor für einen schnellen Zugriff in einer Hashtable abgespeichert.

20.3.3 Karten initialisieren

Jede Karte wird wie im Kapitel »Arrays« als Zeichenkette gespeichert. Hierbei werden Farbe und Kartenbezeichnung durch ein Trennzeichen, beispielsweise einen Strichpunkt, voneinander getrennt. Die äußere Schleife geht von 1 bis 13 (die Karten von 2 bis 10, König, Bube, Dame, As). Die innere Schleife geht von eins bis vier und umfasst die vier Farben. Die einzelnen Werte werden in einem Java-Vector gespeichert (natürlich nur zu Übungszwecken, wie bereits gesagt geht das mit minimalem Mehraufwand auch mit reinen JavaScript-Mitteln). Die zugehörige, als public deklarierte Methode zum Einfügen eines Elements in ein Vector-Objekt heißt addElement(). Um noch ein wenig mehr Java zu verwenden, wird das zu übergebende String-Objekt auch als Java-Objekt generiert, obwohl man auch einfach die (JavaScript-)Zeichenkette hätte übergeben können.

function deck(){
   // Hilfsvariablen
   var kartenname = new Array()
   kartenname[0]="Zwei"; kartenname[1]="Drei"
   kartenname[2]="Vier"; kartenname[3]="Fünf"
   kartenname[4]="Sechs"; kartenname[5]="Sieben"
   kartenname[6]="Acht"; kartenname[7]="Neun"
   kartenname[8]="Zehn"; kartenname[9]="Bube"
   kartenname[10]="Dame"; kartenname[11]="König"
   kartenname[12]="As"
   var farben = new Array();
   farben[0] = "Herz"; farben[1] = "Karo"
   farben[2] = "Pik"; farben[3] = "Kreuz"
   //Array initialisieren; als Java-Vector!
   var cards = new java.util.Vector()
   for (var i=0; i<13; i++)
      for (var j=0; j<4; j++){
         temp = farben[j]+";"+kartenname[i]
         karte = new java.lang.string(temp)
         cards.addElement(karte)
      }
   return cards
}

20.3.4 Karten mischen

Das Mischen gestaltet sich, wie bereits beschrieben, mit einem Vektor relativ einfach. Es wird (wie übrigens im Kapitel »Arrays« auch) ein beliebiges Element des Vector-Objekts bestimmt und aus dem Vektor herausgenommen. Parallel dazu wird ein neuer Vektor erzeugt, der die Elemente des »alten« Vektors enthält, nur in einer neuen, zufälligen Reihenfolge.

Um dies zu bewerkstelligen, werden die folgenden Java-Methoden des Vector-Objekts benötigt:

	size(): Liefert die Anzahl der Elemente im Vektor zurück.
	elementAt(i): Liefert das Element an der Position i im Vektor zurück. (Die Zählung beginnt – wie bei Arrays auch – bei 0.)
	removeElementAt(i): Löscht das Element der an Position i aus dem Vektor.

function mischen(alt){
   var neu = new java.util.Vector()
   for (var i=alt.size(); i>0; i--){
      var zufall = Math.floor(Math.random()*i)
      neu.addElement(alt.elementAt(zufall))
      alt.removeElementAt(zufall)
   }
   return neu
}

Die Kartenverteilung und die Punktberechnung wird an dieser Stelle nicht dargestellt. Schauen Sie doch mal bei MyGalileo vorbei! An dieser Stelle folgt lediglich eine Beispielseite, die ein Kartenblatt mischt und auf dem Bildschirm ausgibt. Hierzu wird die toString()-Methode eines Vector-Objekts verwendet, die die Elemente des Vektors als Zeichenkette ausgibt.

<HTML>
<HEAD>
<TITLE>Karten mischen</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function deck(){
   // Hilfsvariablen
   var kartenname = new Array()
   kartenname[0]="Zwei"; kartenname[1]="Drei"
   kartenname[2]="Vier"; kartenname[3]="Fünf"
   kartenname[4]="Sechs"; kartenname[5]="Sieben"
   kartenname[6]="Acht"; kartenname[7]="Neun"
   kartenname[8]="Zehn"; kartenname[9]="Bube"
   kartenname[10]="Dame"; kartenname[11]="König"
   kartenname[12]="As"
   var farben = new Array();
   farben[0] = "Herz"; farben[1] = "Karo"
   farben[2] = "Pik"; farben[3] = "Kreuz"
   //Array initialisieren; als Java-Vector!
   var cards = new java.util.Vector()
   for (var i=0; i<13; i++)
      for (var j=0; j<4; j++){
         temp = farben[j]+";"+kartenname[i]
         karte = new java.lang.String(temp)
         cards.addElement(karte)
      }
   return cards
}
function mischen(alt){
   var neu = new java.util.Vector()
   for (var i=alt.size(); i>0; i--){
      var zufall = Math.floor(Math.random()*i)
      neu.addElement(alt.elementAt(zufall))
      alt.removeElementAt(zufall)
   }
   return neu
}
function verteilen(){
   var c1 = deck()
   var c2 = mischen(c1)
   document.write(c2.toString())
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Karten mischen</H3>
<SCRIPT LANGUAGE="JavaScript"><!--
   if (navigator.javaEnabled())
      verteilen()
//--></SCRIPT>
</BODY>
</HTML>

Abbildung 20.2  Das gemischte Kartenblatt

20.4 Fragen & Aufgaben

1.	Ist Java dasselbe wie JavaScript?
2.	Warum gibt man Java trotz der Geschwindigkeitsnachteile in vielen Projekten den Vorzug?
3.	Was ist der Unterschied zwischen public und private? Wieso kann es sinnvoll sein, nicht alles als public zu deklarieren?
4.	Entwickeln Sie eine Methode, um ein beliebiges Java-Applet auf dem Webserver, dessen Name bekannt, aber auf der momentanen Seite nicht als Applet geladen ist, mit JavaScript-Mitteln aufzurufen. Auf welche Methoden dieses Applets können Sie dann zugreifen?

1    Das findet man heute kaum noch, da es dem Spieler einen Vorteil gegenüber der Bank bringt.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 21 Signierte Skripten
			21.1 Zusätzliche Rechte
			21.2 Signieren

Kapitel 21 Signierte Skripten

Es gibt keine Sicherheit, nur verschiedene Grade der

Unsicherheit.

– Anton Neuhäusler

An einigen Stellen in diesem Buch war von den Sicherheitsmechanismen von JavaScript die Rede. Insbesondere ging es darum, dass man mit JavaScript keine sensitiven Daten auslesen kann. Sensitiv bedeutet, dass es sich um ein potenzielles Sicherheitsrisiko handelt, wenn die Daten auslesbar sind. Beispielsweise kann man nicht auf die URL eines Dokuments in einem Unterframe zugreifen. Erstens geht es niemanden etwas an, wohin man surft (außer, man benutzt die Leitungen seines Arbeitgebers), und außerdem könnten so geheime URLs publik werden, beispielsweise von nicht gesicherten Intranet-Seiten.

In diesem Kapitel werden Wege vorgestellt, diese zusätzlichen Rechte zu erhalten. Im Intranet-Einsatz kann das mitunter ganz nützlich sein; im World Wide Web ist das Vorgehen nicht empfehlenswert, denn selbstredend wird der Benutzer darauf hingewiesen, dass ein Skript zusätzliche Rechte fordert.

Wenn ein Skript schon besondere Rechte haben will, steht der Benutzer vor der schwierigen Entscheidung, ob er dem Skript überhaupt diese Rechte geben will. Man kann das Skript dann signieren: Man erwirbt dazu ein Zertifikat bei einer unabhängigen Authorisierungsbehörde und kann dann seine Skripte mit seiner persönlichen Signatur versehen. Der Benutzer sieht dann, von wem das Skript kommt, und stimmt dann eventuell eher zu (zumindest, wenn er den Skriptersteller persönlich kennt). Aber dazu später mehr.

	Das Sicherheitskonzept wurde beim Netscape Navigator 4 komplett neu erstellt; die folgenden Beispiele funktionieren also weder beim Internet Explorer noch bei älteren Netscape-Versionen.

21.1 Zusätzliche Rechte

Wie bereits in der Einleitung und in vorhergehenden Kapiteln erwähnt, scheitern manche JavaScript-Aktionen an Sicherheitsvorkehrungen des JavaScript-Interpreters. Beispiele sind das Auslesen von Daten aus Dokumenten in einem anderen Frame, sofern diese Dokumente auf einem anderen Webserver liegen, oder das Erzeugen bestimmter Fenster (Sie erinnern sich vielleicht noch an die Auflistung im Kapitel »Fenster II«).

21.1.1 Allgemeines

Die erweiterten Rechte werden anhand von Java-Klassen beantragt, die beim Netscape Navigator 4 mitgeliefert sind. Die allgemeine Syntax lautet:

netscape.security.PrivilegeManager.enablePrivilege(Privileg)

Mit Privileg wird hier die Zeichenkette bezeichnet, die das Privileg angibt, das das Skript beantragt. Man unterscheidet zwischen Privilegien mit mittlerem Risiko und Privilegien mit hohem Risiko. In der Tabelle 21.1 sehen Sie alle Privilegien mit mittlerem und hohem Risiko:

Tabelle 21.1  Privilegien mit hohem Risiko

Privileg	Beschreibung
UniversalBrowserRead	Lesezugriff auf sensible Daten, beispielsweise Dokumente von anderen Domains in einem Unterframe.
UniversalPreferencesRead	Lesezugriff auf die persönlichen Einstellungen des Benutzers (inklusive E-Mail-Adresse, Mailserver-Benutzername etc.).
UniversalSendMail	Versand von E-Mails vom Konto des Benutzers.
UniversalBrowserAccess	Lese- und Schreibzugriff auf sensible Daten, beispielsweise Dokumente von anderen Domains in einem Unterframe; Erzeugung von besonderen Fenstern (etwa außerhalb des Bildschirms).
UniversalBrowserWrite	Erzeugung von besonderen Fenstern (etwa außerhalb des Bildschirms).
UniversalFileAccess	Lese- und Schreibzugriff auf Dateien auf dem Rechner des Benutzers.
UniversalFileRead	Lesezugriff auf Dateien auf dem Rechner des Benutzers.
UniversalFileWrite	Schreibzugriff auf Dateien auf dem Rechner des Benutzers.
UniversalPreferencesWrite	Schreibzugriff auf die persönlichen Einstellungen des Benutzers.

Sie sehen bereits, dass man mit diesen speziellen Rechten schlimme Dinge auf dem Rechner des Benutzers anstellen kann. Aber wie gesagt, er muss erst einmal zustimmen, und die Warnmeldung ist mehr als deutlich.

21.1.2 Surfüberwachung

Im ersten Beispiel soll eine Surfüberwachung realisiert werden. Die Seite besteht aus zwei Frames. Während der Benutzer im unteren Frame nach Gutdünken surfen kann, wird im oberen Frame die URL des Dokuments im unteren Frame angezeigt. Normalerweise ist das ja nicht möglich, aber durch die entsprechenden Privilegien kein Problem.

Anhand obiger Tabelle sehen Sie, dass ein Lesezugriff auf den Frame ausreicht, also das Privileg UniversalBrowserRead.

Die Frameset-Datei sieht folgendermaßen aus:

<HTML>
<HEAD>
<TITLE>Surfüberwachung</TITLE>
</HEAD>
<FRAMESET ROWS="100,*">
   <FRAME SRC="watchdog.html">
   <FRAME SRC="http://www.galileo-press.de">
</FRAMESET>
</HTML>

Die Datei watchdog.html schließlich muss die URL des unteren Frames auslesen. Mit setInterval() wird die Adresse periodisch in einen Layer geschrieben.

<HTML>
<HEAD>
<TITLE>Watchdog</TITLE>
<SCRIPT LANGUAGE="JavaScript1.2"><!--
setInterval("dog()", 5000)
function dog(){
   netscape.security.PrivilegeManager.enablePrivilege
     ("UniversalBrowserRead")
   var adr = parent.frames[1].location.href
   with (document.layers[0].document){
      open()
      write(adr)
      close()
   }
}
//--></SCRIPT>
</HEAD>
<BODY>
<H4>Aktuelle URL:</H4>
<LAYER>
---noch keine---
</LAYER>
</BODY>
</HTML>

Sobald Sie diese Seite im Browser laden, erscheint die in Abbildung 21.1 gezeigte Abfrage.

Abbildung 21.1  Sicherheitsabfrage

Sobald der Benutzer das bestätigt, wird die Seite geladen, und alles funktioniert wie geplant (seihe Abbildung 21.2).

Sollte der Benutzer die Sicherheitsabfrage nicht bestätigen, so erhält der Benutzer auch keinen Lesezugriff auf den unteren Frame, sondern eine Fehlermeldung, die in Abbildung 21.3 zu sehen ist.

Abbildung 21.2  Die Surfüberwachung im Einsatz

Abbildung 21.3

Die Fehlermeldung, die erscheint, wenn der Benutzer die zusätzlichen Rechte nicht gewährt.

21.1.3 Besondere Fenster

Wie in vorherigen Kapiteln bereits erwähnt, gibt es einige Sachen, die man mit Fenstern anstellen kann, die nur mit signierten Skripten möglich sind. Dazu gehören Fenster, die weniger breit oder hoch sind als 100 Pixel, oder die sich außerhalb des sichtbaren Bereichs des Bildschirms befinden. Hierzu wird – wie in Tabellen 21.1 //und 21.2// zu sehen – ein Privileg mit großem Risiko benötigt, entweder UniversalBrowserAccess oder UniversalBrowserWrite. Dabei ist UniversalBrowserWrite das schwächere Privileg, also wird es verwendet. Zwei sicherheitskritische Operationen werden ausprobiert:

	Erstellen eines Fensters, das niedriger oder schmaler als 100 Pixel ist
	Erstellen eines stets sichtbaren Fensters

Im folgenden HTML-Dokument befindet sich ein Formular mit zwei Schaltflächen. Jede dieser Schaltflächen ruft eine der beiden Operationen auf.

<HTML>
<HEAD>
<TITLE>Besondere Fenster</TITLE>
<SCRIPT LANGUAGE="JavaScript1.2"><!--
function fenster1(){
   netscape.security.PrivilegeManager.enablePrivilege
     ("UniversalBrowserWrite")
   var f = window.open("", "", "width=50,height=50")
   netscape.security.PrivilegeManager.disablePrivilege
     ("UniversalBrowserWrite")
   f.document.open()
   f.document.write("50x50")
   f.document.close()
}
function fenster2(){
   netscape.security.PrivilegeManager.enablePrivilege
     ("UniversalBrowserWrite")
   var f = window.open("", "", "width=150,height=150,alwaysRaised")
   netscape.security.PrivilegeManager.disablePrivilege
     ("UniversalBrowserWrite")
   f.document.open()
   f.document.write("immer sichtbar")
   f.document.close()
}
//--></SCRIPT>
</HEAD>
<BODY>
<H3>Besondere Fenster</H3>
<FORM>
<INPUT TYPE="BUTTON" VALUE="50x50" onClick="fenster1()">
<INPUT TYPE="BUTTON" VALUE="immer sichtbar" onClick="fenster2()">
</FORM>
</BODY>
</HTML>

Abbildung 21.4  Das kleine Fenster ist sichtbar, obwohl das große den Fokus hat.

	Beachten Sie die Anweisung disablePrivilege("UniversalBrowserWrite"). Es ist günstig, dem Skript ein Privileg sofort wieder zu entziehen, nachdem es nicht mehr gebraucht wird. Sonst können auch andere Seiten die besonderen Rechte wahrnehmen. Analog zu enablePrivilege() wird auch hier das entsprechende Privileg als Zeichenkette übergeben.

21.2 Signieren

Obwohl bis jetzt immer von signierten Skripten die Rede war, war von einer Signatur nicht viel zu sehen. In Abbildung 21.1 heißt es sogar, dass das Skript keine digitale Unterschrift trägt (im Netscape Navigator: not digitally signed). Wie bereits eingangs erwähnt, kann man so darlegen, dass das sicherheitskritische Skript von einem selbst stammt. Sie kennen das Prinzip vielleicht, wenn Sie etwa bei Netscape SmartUpdate eine Sicherheitsabfrage beantworten müssen. Dort heißt es dann nicht, dass das Skript keine digitale Unterschrift trägt, sondern dass es in der Tat signiert ist – von einer Firma namens Netscape. Wenn Sie dieser Firma vertrauen (und darauf baut SmartUpdate auf), können Sie die Sicherheitsabfrage positiv beantworten.

21.2.1 Zigbert

Wenn Sie schon einmal in Java programmiert haben, kennen Sie wahrscheinlich das JAR-Dateiformat. Es handelt sich hierbei um eine Abwandlung des ZIP-Formats. Sie müssen Ihre Skripten in ein JAR-Archiv packen, um sie signieren zu können. Netscape bietet dazu ein Tool an, mit dem Sie das mehr oder minder bequem erledigen können. Es würde den Umfang dieses Buchs sprengen, wenn das hier ausführlich durchexerziert werden würde; aus diesem Grund nachfolgend nur Links auf die entsprechenden Ressourcen, die Sie zum Signieren benötigen:

	Um ein Skript zu signieren, benötigen Sie zunächst eine Digitale ID. Diese wird unter anderem von der amerikanischen Firma Verisign, http://www.verisign.com, ausgestellt. Das genaue Zertifikat, das Sie benötigen, heißt Netscape Object Signing Certificate. Je nachdem, ob Sie ein kommerzieller Softwareentwickler sind oder nicht, kostet das Zertifikat ein wenig mehr oder weniger.
	Das alte Programm zum Signieren eines Skripts heißt Zigbert und ist bei Netscape unter der URL http://developer.netscape.com/software/ signedobj/zig.html erhältlich. Zum Ausführen von Zigbert benötigen Sie einen Perl-Interpreter. Bei UNIX und Konsorten ist der schon dabei, für andere Betriebssysteme finden Sie unter http://www.perl.com Verweise auf Interpreter für andere Betriebssysteme. Der bekannteste Port für Windows 95/98/NT/ME/2000 heißt ActivePerl und ist von der Firma ActiveState. Sie können den Interpreter unter http://www.activestate.com/ activeperl herunterladen.
	Inzwischen gibt es auch ein etwas komfortabler zu bedienendes Tool, das Netscape Object Signing Tool 1.1, welches unter der URL http:// developer.netscape.com/software/signedobj/jarpack.html nebst Dokumentation heruntergeladen werden kann.

21.2.2 HTML-Code anpassen

Das Programm Zigbert erzeugt aus einem Skript und einem digitalen Zertifikat ein JAR-Archiv, welches auf den Webserver überspielt werden muss. Zuvor jedoch muss der HTML-Code angepasst werden. Zum einen muss der Name des JAR-Archivs angegeben werden, und zum anderen ein Identifikator. Dieser Identifikator wird in dem JAR-Archiv mit gespeichert. Der <SCRIPT>-Tag sieht danach also folgendermaßen aus:

<SCRIPT LANGUAGE="JavaScript" ARCHIVE="datei.jar" ID="id">

Weitergehende Informationen finden Sie in der Online-Dokumentation von Netscape unter der Adresse http://developer.netscape.com/docs/ manuals/signedobj/.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 22 DOM
			22.1 DOM-Baum
			22.2 Navigation im Baum
			22.3 Den Baum modifizieren
			22.4 Fragen & Aufgaben

Kapitel 22 DOM

Die Zukunft hat viele Namen. Für die Schwachen ist sie das Unerreichbare. Für die Furchtsamen ist sie das Unbekannte. Für die Tapferen ist sie die Chance.

– Victor Hugo

JavaScript entwickelt sich natürlich weiter. Inzwischen gibt es JavaScript-Version 1.5, welche jedoch von keinem Browser unterstützt wird. JavaScript 1.5 schließt die Lücke der bisherigen JavaScript-Versionen hin zum Standard ECMAScript, 3. Revision. Dieser Sprachstandard (offizielle Spezifikation unter http://www.ecma.ch oder auf der Buch-CD) entspricht in etwa dem Sprachumfang von JavaScript 1.1, wurde aber bisher noch von keinem Browser komplett unterstützt. Der Internet Explorer 4 war sehr nahe dran, und der Internet Explorer 5 unterstützt (bis auf die üblichen Bugs) vollständig ECMAScript (oder kurz: ECMA-262). Auch Netscape 6, der im Vor-Beta-Stadium befindliche neue Browser (unter http://home.netscape.com, Entwicklerversion unter http://www.mozilla.org) ist ECMA-compliant.

Wenn jedoch im Zusammenhang mit JavaScript von Standards gesprochen wird, dann ist die Rede von DOM, dem Document Object Model. Vereinfacht gesagt, soll ein HTML-Dokument so modelliert werden, dass mit JavaScript darauf zugegriffen werden kann. Wie in den drei DHTML-Kapiteln schon angedeutet wurde, geht der Internet Explorer (ab Version 4) hier viel weiter als der Netscape Navigator 4. Die zueinander inkompatiblen DOM-Umsetzungen der beiden Browserhersteller sind für den Programmierer ein stetes Ärgernis. Da zudem noch sowohl Netscape als auch Microsoft ihre Umsetzung für die jeweils besser hielten, war zunächst keine Einigung in Sicht. Für solche Fälle gibt es glücklicherweise (mehr oder weniger) unabhängige Gremien wie das W3C, welche mittlerweile einen DOM-Standard abgesegnet haben. Die Konsequenz daraus: Der Internet Explorer 5 hält sich daran, der Netscape Navigator 6 ebenfalls (in der momentanen Version ist die Unterstützung aber vor allem von der JavaScript-Seite aus noch überhaupt nicht vollständig). Da es bis zur endgültigen Fertigstellung des Netscape noch eine Weile dauert, und die Verbreitung des Internet Explorer 5 vor allem in Firmennetzwerken noch nicht so groß ist, ist die Zielgruppe für DOM-Effekte nicht allzu groß. Aus diesem Grund finden Sie in diesem Kapitel lediglich eine kurze Einführung in das Konzept. In einer weiteren Auflage kann das schon ganz anders aussehen.

Eine Vorbemerkung noch: Wir beschränken uns hier ausschließlich auf den DOM-Mechanismus des Internet Explorer 5.x. Der Grund hierfür ist ganz einfach der, dass der Netscape 6 – trotz offiziellem Release-Status – noch weit von der Serienreife entfernt ist und deshalb die Entwicklung damit keine Freude ist. In Kapitel 18 haben Sie gesehen, wie Sie alte DHTML-Anwendungen für den neuen Netscape fit machen.

22.1 DOM-Baum

Das HTML-Dokument wird in einen Baum umgewandelt. Jedes HTML-Element, und auch jeder Text, der nicht von Tags umgeben ist, wird zu einem Knoten (engl. nodes) in dem Baum. Elemente zwischen einem öffnenden und dem dazugehörigen schließenden Tag sind Kindknoten (engl. child nodes), sodass auch eine Hierarchie gegeben ist. In diesem Kapitel wird folgendes Beispieldokument betrachtet:

<HTML>
<HEAD>
<TITLE>DOM-Demo</TITLE>
</HEAD>
<BODY ID="alles">
<H3 ID="Ueberschrift">DOM-Demo</H3>
<IMG SRC="ball.gif" ID="Ball1">
<IMG SRC="ball.gif" ID="Ball2">
<IMG SRC="ball.gif" ID="Ball3">
<IMG SRC="ball.gif" ID="Ball4">
</BODY>
</HTML>

In Abbildung 22.1 sehen Sie, wie der DOM-Baum für das vorherige Dokument aussieht.

Beachten Sie, dass jeder Tag ein ID-Attribut trägt. Hiermit kann der Tag dann von JavaScript aus angesprochen werden. Sie ahnen bereits, es geht wohl auch über irgendein Array mit irgendeinem Index, wie bisher immer, aber der Übersichtlichkeit halber ist es auch hier besser, sprechende Namen zu verwenden.

Abbildung 22.1  Der DOM-Baum des HTML-Dokuments

22.2 Navigation im Baum

Ähnlich wie bei Framehierarchien kann man auch in dem DOM-Baum von Ebene zu Ebene springen. Die entsprechenden Methoden und Eigenschaften heißen hier nur anders, aber ansonsten bleibt alles beim Alten. Die Kindknoten eines Elements im DOM-Baum befinden sich im Array childNodes[]. Von einem Knoten (bzw. HTML-Element) aus kann man mit den folgenden Eigenschaften auf andere Knoten zugreifen:

Tabelle 22.1  Eigenschaften eines Knotens im DOM-Baum

Eigenschaft	Beschreibung
firstChild	Der erste Kindknoten (erstes Element im child Nodes-Array)
lastChild	Der letzte Kindknoten (letztes Element im child Nodes-Array)
nextSibling	Das nächste Kind des Elternknotens
parentNode	Der Elternknoten
previousSibling	Das vorherige Kind des Elternknotens

Die Eigenschaften aus Tabelle 22.2 liefern nähere Informationen über einen Knoten zurück:

Tabelle 22.2  Eigenschaften, die nähere Informationen über einen Knoten liefern

Eigenschaft	Beschreibung
nodeName	HTML-Tag des Knotens als Zeichenkette (z. B. "H3")
nodeType	1 = Tag, 2 = Attribut, 3 = Text

In Abbildung 22.2 sehen Sie den DOM-Baum noch einmal, und diesmal mit den Beziehungen zwischen den einzelnen Knoten.

Abbildung 22.2  Navigationsmöglichkeiten innerhalb des DOM-Baums

22.3 Den Baum modifizieren

Der große Vorteil von DOM gegenüber DHTML und den früheren DOM-Implementierungen besteht darin, dass man Elemente nicht nur ändern, sondern auch entfernen und sogar neue Elemente einfügen kann. Die Baumstruktur ist hier von großem Vorteil, da das Löschen eines Knotens nicht die Baumintegrität gefährdet. In Tabelle 22.3 sehen Sie eine grobe Übersicht über die verschiedenen Methoden. Für das Beispiel in diesem Kapitel reicht sogar eine Methode.

Tabelle 22.3  Methoden zur Veränderung des DOM-Baums

Methode	Syntax	Beschreibung
appendChild	Vater.appendChild(Kind)	Hängt Kind als Kindknoten an Vater an.
cloneNode	Original.cloneNode (alles)	Erzeugt einen Knoten, der identisch zu Original ist. Ist alles gleich true, so werden auch alle Kindknoten von  Original mit dupliziert, bei false lediglich der Knoten selbst.
createElement	document.createElement (HTMLTag)	Erzeugt einen Knoten, der aus dem in Klammern angegebenen HTML-Element (z. B. H3) besteht.
hasChildNodes	Knoten.hasChildNodes()	Boolescher Wert, der angibt, ob Knoten Kinder hat oder nicht.
insertBefore	Vater.insertBefore(Kind, Schwester)	Kind wird als Kindknoten von Vater eingefügt, und zwar direkt vor Schwester.
removeNode	Knoten.removeNode(alles)	Knoten wird aus dem DOM-Baum entfernt. Ist alles gleich true, dann werden auch alle Kindknoten von Knoten entfernt.
replaceNode	Alt.replaceNode(Neu)	Der Knoten Alt wird durch den Knoten Neu ersetzt.
setAttribute	Knoten.setAttribute(Name, Wert)	Der Knoten enthält ein neues Attribut.

In einem kleinen Beispiel soll dies einmal ausprobiert werden. Ausgehend von obigem Beispiel-HTML-Dokument sollen die folgenden Effekte eingebaut werden:

	Wenn der Benutzer mit der Maus auf eine der Grafiken klickt, soll diese durch eine andere Grafik ausgetauscht werden.
	Wenn der Benutzer noch einmal auf die Grafik klickt, soll sie komplett verschwinden (eine Art armseliges Ballerspiel mit JavaScript also).

Der Einfachheit halber werden die Event-Handler der Grafiken schon im ursprünglichen HTML-Dokument gesetzt. Es muss also nur noch eine Funktion geschrieben werden, die überprüft, ob die Grafik schon einmal angeklickt worden ist, und dann entweder die Grafik austauscht oder den Knoten aus dem DOM-Baum entfernt.

Der folgende Code ist kurz und einleuchtend und wird daher ohne längere Vorrede abgedruckt. Leider ist noch ein kleiner Fehler drin, dazu später mehr.

<HTML>
<HEAD>
<TITLE>DOM-Demo</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function mausklick(Nummer){
   var obj = document.all.alles.childNodes[1+Nummer]
   var gfx = obj.src
   if (gfx.indexOf("ball.gif")>-1)
      obj.src="kreuz.gif"
   else
      obj.removeNode(false)
}
//--></SCRIPT>
</HEAD>
<BODY ID="alles">
<H3 ID="Ueberschrift">DOM-Demo</H3>
<IMG SRC="ball.gif" ID="Ball1" onClick="mausklick(1)">
<IMG SRC="ball.gif" ID="Ball2" onClick="mausklick(2)">
<IMG SRC="ball.gif" ID="Ball3" onClick="mausklick(3)">
<IMG SRC="ball.gif" ID="Ball4" onClick="mausklick(4)">
</BODY>
</HTML>

Abbildung 22.3  Die DOM-Demo im Internet Explorer 5

Wie Ihnen sicherlich nicht entgangen ist, spuckt der Browser hin und wieder Fehlermeldungen bei der Ausführung dieses Skripts aus, beispielsweise, wenn Sie auf die dritte Grafik von links klicken. Sehr merkwürdig! Zum Testen sollten Sie in die Funktion mausklick() den folgenden Debug-Code einfügen (am besten gleich am Anfang):

function mausklick(Nummer){
   var meldung=""
   for (var i=0; i<document.all.alles.childNodes.length; i++)
     meldung += document.all.alles.childNodes[i].nodeName + "|" +
       document.all.alles.childNodes[i].nodeType + "\n"
   alert(str)
   var obj = document.all.alles.childNodes[1+Nummer]
   var gfx = obj.src
   if (gfx.indexOf("ball.gif")>-1)
      obj.src="kreuz.gif"
   else
      obj.removeNode(false)
}

Abbildung 22.4  Die Debug-Ausgabe

In Abbildung 22.4 sehen Sie die Ursache des Übels: Anscheinend befinden sich zwischen den einzelnen Grafiken noch Textstücke. Auch das ist nicht weiter verwunderlich – auch wenn ein Zeilensprung im HTML-Code in der Anzeige quasi nie Auswirkungen hat, beim DOM-Baum ist das ein Textelement. Sie sollten also die Zeilensprünge entfernen, und dann gibt es beim ersten Anklicken einer Grafik auch keine Fehlermeldungen mehr.

Um dies zu vermeiden, sollten Sie die HTML-Elemente, die Sie in Ihrem Skript verwenden wollen, mit den oben gezeigten Methoden (create Element() und appendChild() bzw. insertBefore()) erzeugen. Das obige HTML-Dokument kann auch folgendermaßen erzeugt werden (von der Klick-Funktionalität mal abgesehen) – jedoch nur ab Internet Explorer 5 und Netscape Navigator 6!

<HTML>
<HEAD>
<TITLE>DOM-Demo</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function init(){
   var basis = document.all.alles
   var h3 = document.createElement("H3")
   h3.setAttribute("id", "Ueberschrift")
   h3.innerText = "Überschrift"
   basis.appendChild(h3)
   for (var i=1; i<=4; i++){
      img = document.createElement("IMG")
      img.setAttribute("id", "Ball"+i)
      img.src = "ball.gif"
      basis.appendChild(img)
   }
}
//--></SCRIPT>
</HEAD>
<BODY ID="alles" onLoad="init()">
</BODY>
</HTML>

Wie Sie in einer Aufgabe am Ende des Kapitels jedoch noch sehen werden, ist das vorherige Skript nicht ganz fehlerfrei. Es ist einfach gefährlich, über Index auf ein Element zuzugreifen, wenn zwischendurch Elemente entfernt werden sollen. Aber Sie haben ja bereits an anderer Stelle schon gesehen, dass es fast immer besser ist, per Identifikator auf ein Element zuzugreifen. Hier ist das auch der Fall. Es gibt eine weitere Methode des document-Objekts, und zwar getElementById(). Sie kennen sie bereits aus Kapitel 18, dort wird Sie für DHTML-Effekte des Netscape 6 eingesetzt. Als Parameter übergeben Sie den Wert des ID-Attributs des entsprechenden HTML-Tags, und die Methode gibt Ihnen eine Referenz auf das Objekt zurück. Im folgenden Code finden Sie das für unser kleines Beispiel einmal umgesetzt. Anhand der Nummer, die an mausklick() übergeben wird, kann der Identifikator der angeklickten Grafik ermittelt werden, und dieser Wert wird dann an getElementById() übergeben.

function mausklick(Nummer){
   var obj = document.getElementById("Ball"+Nummer)
   var gfx = obj.src
   if (gfx.indexOf("ball.gif")>-1)
      obj.src="kreuz.gif"
   else
      obj.removeNode(false)
}

Ihnen ist sicherlich aufgefallen, dass alle Screenshots in diesem Kapitel mit dem Internet Explorer erstellt worden sind, während im restlichen Buch stets der Netscape Navigator zum Einsatz kam. Das hat einen recht einfachen Grund. Der Netscape Navigator 6, der als einziger Netscape-Browser das neue DOM-Konzept unterstützt, ist noch sehr fehleranfällig, und für den Entwickler ziemlich grausam. Auch die Beispiele in diesem Kapitel funktionieren in diesem Browser nicht, im Internet Explorer 5 und 5.5 jedoch schon. Die Unterstützung des Browsers an der Basis, den Surfern nämlich, ist auch noch relativ gering. Zwar wird anerkannt, dass der Browser für viele Plattformen zur Verfügung steht, und dass er Webstandards ziemlich genau unterstützt; die meisten Anwender wollen jedoch noch auf eine stabile Version warten. Und somit bleibt eine saubere DOM-Programmierung noch Zukunftsmusik. Die JavaScript-Programmierung wird sich in diese Richtung bewegen – das steht außer Frage. So lange jedoch der Internet Explorer 4 und (vor allem) der Netscape Navigator 4 noch eine große Verbreitung haben, müssen Sie die Entwicklung auf diese Browser abstimmen, und sich dort mit den Inkompatibilitäten herumschlagen. Dieses Kapitel sollte Ihnen einen ersten Eindruck geben, was in Zukunft alles möglich sein wird, und wie dynamische Webseiten der Zukunft aussehen (können). Sie können sich einen Wissensvorsprung verschaffen, wenn Sie sich schon heute mit dieser Thematik beschäftigen, aber es wird noch eine lange Zeit dauern, bis Sie dieses zusätzliche Wissen auch einsetzen können. Wenn Sie diese Materie interessiert, dann lassen Sie es uns bitte über MyGalileo wissen – in einer möglichen Neuauflage werden wir bei entsprechendem Zuspruch diesen Teil erweitern.

22.4 Fragen & Aufgaben

1.	Das Listing ohne getElementById() hat einen Bug; klicken Sie beispielsweise stets auf die am weitesten rechts stehende Grafik. Was verursacht diesen Bug?
2.	Beheben Sie den Bug aus der vorherigen Aufgabe.
3.	Versuchen Sie, das Skript so umzuschreiben, dass auf die src-Eigenschaft der Grafik nicht zugegriffen wird.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 23 Fehler
			23.1 Fehler abfangen
			23.2 JavaScript Debugger
			23.3 Fragen

Kapitel 23 Fehler

Unsere Probleme sind von Menschen gemacht, darum können sie auch von Menschen gelöst werden

– John F. Kennedy

Motivation

Fehlermeldungen sind der größte Feind eines Programmierers. Versierte Anwender wissen, worum es sich handelt, und der Nimbus der Unfehlbarkeit ist weg. Nicht ganz so gut informierte Benutzer jedoch wissen gar nicht, wie ihnen geschieht, wenn beispielsweise der Internet Explorer ein Warndreieck zeigt, und eventuell noch eine (nichts sagende – wie immer beim IE) Fehlermeldung.

Im Optimalfall treten Fehlermeldungen gar nicht auf, weil jede Eventualität berücksichtigt worden ist und die Programmierung perfekt ist. Das ist jedoch selbst bei kleineren Programmierprojekten eine Illusion und im Web erst recht. Selbst, wenn Sie keinen Fehler bei der Programmierung gemacht haben, es wird immer eine bestimmte Browserversion unter einem bestimmten Betriebssystem geben, die Ihnen einen Strich durch die Rechnung macht und unter bestimmten Umständen eine Fehlermeldung produziert.

Fehlermeldungen abfangen

Seit JavaScript-Version 1.2 gibt es jedoch Möglichkeiten, solche so genannten syntaktischen Fehler (Verstöße gegen die JavaScript-Syntaxregeln) abzufangen, sodass der Benutzer dadurch wenigstens nicht mehr belästigt wird, oder die Fehlermeldung besonders aufbereitet wird. Denn wenn der Benutzer schon auf einen Fehler stößt, dann ist es nur zu Ihrem Vorteil, wenn auch Sie davon erfahren!

Es gibt jedoch auch logische Fehler. Das sind Fehler, die zu keiner Fehlermeldung führen, aber dafür sorgen, dass das Skript ein falsches Ergebnis liefert. Diese Fehler sind erfahrungsgemäß am schwierigsten zu finden, eben weil der Fehler nur am Ergebnis sichtbar ist. Wenn Sie den Netscape Navigator einsetzen – was in Bezug auf Aussagekraft der Fehlermeldungen ohnehin vorteilhaft ist – können Sie mit einem kostenlosen Tool von Netscape dem Fehlerteufel auf die Spur kommen. Der JavaScript Debugger lässt Sie während der Ausführung eines Skripts auf die Werte der Variablen zugreifen, und Sie können den Skriptablauf auch unterbrechen.

23.1 Fehler abfangen

Im Bereich Event-Handler (siehe Kapitel 15) wurde auch kurz onError vorgestellt, der beim Eintreten eines Fehlers aktiv wird. Der Internet Explorer akzeptiert diesen Event-Handler bei praktisch jedem Objekt; der Netscape Navigator akzeptiert dies nur im <BODY>-Tag. Es gibt drei Möglichkeiten, diesen Event-Handler einzusetzen:

	<BODY onError="Code"> – Führt beim Auftreten eines Fehlers den angegebenen Code aus
	window.onerror = Funktionsreferenz – Führt die angegebene Funktion beim Auftreten eines Fehlers aus. Es muss eine Referenz auf die Funktion angegeben werden, also window.onerror = funktion und nicht window.onerror = funktion().
	Nur unter Netscape zuverlässig: Eine Funktion namens onerror() wird definiert und dann automatisch ausgeführt, sobald ein Fehler auftritt.

23.1.1 Keine Fehlermeldung

Keine Fehlermeldung

Wenn die Funktion, die beim Auftreten eines Fehlers ausgeführt werden soll, oder allgemein der Code, der dann zur Ausführung kommt, mit return true endet, wird der Fehler nicht angezeigt, und der Benutzer bleibt unbehelligt.

Dies soll an einem Beispiel kurz demonstriert werden. Normalerweise würde die folgende Anweisung zu einer Fehlermeldung führen, die Variable rei ist nicht definiert. Da es jedoch eine Funktion onerror() gibt, die (immer) den Wert true zurückliefert, wird dieser Fehler verschluckt und nicht ausgegeben:

<HTML>
<HEAD>
<TITLE>Fehler abfangen</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function oe(){
   return true
}
window.onerror = oe
var panta = rei
//--></SCRIPT>
</HEAD>
<BODY>
Na, wo ist der Fehler?
</BODY>
</HTML>

Bug im Internet Explorer 5

Früher, in den guten Zeiten, war es noch möglich, mit window.onerror =null Fehlermeldungen zu deaktivieren. Einige Versionen des Internet Explorer 5 gehen jedoch beflissentlich darüber hinweg (der Internet Explorer 5 »übersieht« ja manchmal auch eine onerror()-Funktion).

23.1.2 Besondere Fehlermeldung

Details der

Fehlermeldung

Wie bereits eingangs erwähnt, kann man auch eine besondere Fehlermeldung ausgeben. An die Fehlerbehandlungsfunktion werden nämlich drei Parameter übergeben: Die Fehlermeldung, die URL des Dokuments, in dem der Fehler auftrat, und die Zeile, in der das fehlerhafte Kommando steht. Mit der folgenden Strategie können Sie also eine angepasste Fehlermeldung ausgeben:

	Zeigen Sie eine etwas »freundlichere« Fehlermeldung für Ihre Nutzer an.
	Beenden Sie die Funktion mit return true, damit der Browser danach die Fehlermeldung nicht anzeigt.

Der folgende Code zeigt dies einmal exemplarisch. Der Fehler wird mittels window.alert() ausgegeben, natürlich mit einem beruhigenden Hinweis.

<HTML>
<HEAD>
<TITLE>Fehler abfangen</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function oe(meldung, url, zeile){
   var txt = "Es ist ein Fehler aufgetreten! Das macht aber
     nichts...\n\n"
   txt += "Meldung: " + meldung + "\n"
   txt += "URL: " + url + "\n"
   txt += "Zeile: " + zeile
   alert(txt)
   return true
}
window.onerror = oe
var panta = rei
//--></SCRIPT>
</HEAD>
<BODY>
Na, wo ist der Fehler?
</BODY>
</HTML>

Abbildung 23.1  Die handgemachte Fehlermeldung

23.1.3 Ausblick: Fehlermeldungen verschicken

Obwohl es sich bei diesem Buch um ein JavaScript-Buch handelt, ist ein Blick über den Tellerrand nicht schlecht. Am günstigsten wäre es doch, wenn eine JavaScript-Fehlermeldung dem Surfer nicht angezeigt wird, aber automatisch via E-Mail an den Autor der Seite (also an Sie) versandt wird.

Ein erster Ansatz ist ziemlich umständlich, und nicht gerade professionell:

	Öffnen Sie beim Auftreten einer Fehlermeldung mit window.open() ein neues Fenster.
	Erstellen Sie mittels (vielen) document.write()-Anweisungen in dem neuen Fenster ein Formular, in dem Sie (z. B.) als versteckte Formularfelder die interessanten Daten eintragen: Fehlermeldung, URL und Zeile.
	Setzen Sie das ACTION-Attribut des Formulars auf mailto:Ihre E–Mail@Ihr-Provider.de.
	Fügen Sie an geeigneter Stelle in das Formular ein Kommando zum Versand des Formularsein:
setTimeout("document.forms[0].submit(); window.close", 1000)

	Das Formular wird nun automatisch via E-Mail versandt, und das neu erschaffene Browserfenster gleich wieder geschlossen.

Der Haken

Toller Trick – aber er hat zwei Haken. Ich habe an anderer Stelle schon darauf hingewiesen, was von ACTION="mailto:..." in Formularen zu halten ist, und der Besucher Ihrer Website wird auch nicht gerade erfreut sein, wenn ungefragt über sein Konto eine E-Mail an Sie versandt wird. Hauptmanko ist jedoch, dass aus Sicherheitsgründen bei den meisten Browsern Formular.submit() nicht funktioniert, wenn ACTION auf mailto:... lautet. Aus diesem Grund finden Sie an dieser Stelle kein komplettes Skript, sondern dürfen sich in einer Übungsaufgabe damit herumschlagen.

Mit serverseitigen Mitteln ist das dagegen kein größeres Problem. Der Mail-Versand läuft auf Ihrem Webserver ab, der Benutzer bekommt (kaum) etwas mit. Es gibt hier elegante und weniger elegante Lösungen, und Sie sehen an dieser Stelle einen Mittelweg, der auf der Grundidee des vorherigen Ansatzes aufbaut. Es wird ein neues Fenster geöffnet, in diesem Fenster wird jedoch ein serverseitiges Skript aufgerufen, das die E–Mail versendet und dann das Fenster wieder schließt.

Welche Programmiersprache?

Das Hauptproblem: Welche serverseitige Programmiersprache wird eingesetzt? Ich habe mich hier für Perl und PHP entschieden. Erstere ist eine lang bewährte Sprache, die aber mehr und mehr an Boden gegenüber jüngeren und einfacher zu erlernende Konkurrenten verliert, wie beispielsweise ASP und eben PHP (die zweite verwendete Sprache). Doch die meisten Webserver unterstützen Perl (vor allem die meisten Hoster). Das Skript lässt sich mit relativ wenig Aufwand in andere Sprachen umschreiben, und bei MyGalileo finden Sie ein paar Beispiele. Es lohnt sich also, das Buch unter http://www.galileo-press.de zu registrieren!

Zunächst der HTML- und JavaScript-Code. Beim Auftreten eines Fehlers wird ein neues Fenster geöffnet. In der URL werden die Fehlerdaten (wie gewohnt: Meldung, URL, Zeile) übergeben. In Kapitel 12, »Formulare II«, haben Sie ja schon gesehen, wie Sie Daten in der Kommandozeile übergeben können. Von besonderer Bedeutung ist noch der Dateiname des serverseitigen Skripts. Perl-Programme liegen meistens im Verzeichnis /cgi-bin, und haben die Endung .pl oder .cgi.

	Sie können dieses Skript nur testen, wenn Sie Ihren Webserver entsprechend konfiguriert haben, worauf an dieser Stelle aus Platzgründen nicht eingegangen werden kann. Wenn Sie ein Webangebot bei einem Hoster unterhalten, erhalten Sie dort weitere Hinweise.

<HTML>
<HEAD>
<TITLE>Fehler abfangen</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
function oe(meldung, url, zeile){
   var perl = "/cgi-bin/fehler.pl?"
   perl += "meldung=" + escape(meldung)  //escape() nicht vergessen!
   perl += "&url=" + escape(url)
   perl += "&zeile=" + escape(zeile)
   window.open(perl, "Fehler", "width=100,height=100")
   return true
}
window.onerror = oe
var panta = rei
//--></SCRIPT>
</HEAD>
<BODY>
Na, wo ist der Fehler?
</BODY>
</HTML>

Nun zur Datei fehler.pl. Dieses Skript muss die folgenden Aufgaben erledigen:

	Die Daten aus der URL auslesen
	Diese Daten per E-Mail verschicken
	Ein HTML-Dokument ausgeben, das im Wesentlichen dafür sorgt, dass das Fenster wieder geschlossen wird

Das folgende Perl-Programm erledigt all diese Aufgaben. Sie müssen das Programm gegebenenfalls an Ihre Verhältnisse anpassen. Wenn Sie UNIX oder Linux einsetzen, müssen Sie in der ersten Zeile den kompletten Pfad zu Ihrem Perl-Interpreter angeben (ist normalerweise /usr/bin/perl, aber manchmal auch /usr/local/bin/perl oder Ähnliches). Das Programm Sendmail, das für den Versand der E-Mail sorgt, liegt in der Regel auch im Verzeichnis /usr/bin, aber auch dies kann sich ändern. Sie können auch den Hauptkonkurrenten von Sendmail, qmail, einsetzen.

#!/usr/bin/perl
$fehler = $ENV'QUERY_STRING';
@namevalue = split(/&/, $fehler);
foreach $i (@namevalue){
   $i =~ tr/+/ /;
   $i =~ s/%(..)/pack("C", hex($1))/eg;
   ($name, $value) = split(/=/, $i);
   $fehler{$name} = $value;
}
open(SENDMAIL, "|/usr/bin/sendmail -t");
print(SENDMAIL "From: betatester\@website.de\n");
print(SENDMAIL "To: bugfixer\@website.de\n");
print(SENDMAIL "Subject: JavaScript-Fehler!\n\n");
print(SENDMAIL "Fehlermeldung: ".$fehler{'meldung'}."\n");
print(SENDMAIL "URL: ".$fehler{'url'}."\n");
print(SENDMAIL "Zeile: ".$fehler{'zeile'}."\n");
close(SENDMAIL);
print <<'EOF';
<HTML>
<HEAD>
<TITLE>Fehler entdeckt!</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
window.close()
//--></SCRIPT>
</HEAD>
<BODY>Moment bitte ...</BODY>
</HTML>
EOF

Tritt nun ein JavaScript-Fehler auf, so öffnet sich für kurze Zeit das neue Browserfenster, eine E-Mail wird versandt, und das Fenster wird wieder geschlossen. So einfach ist das (mehr oder weniger)!

Die PHP-Version sieht in etwa wie Folgt aus:

<?php
$mailtext  = "Fehlermeldung: $meldung\n";
$mailtext .= "URL: $url\n";
$mailtext .= "Zeile: $zeile\n";
mail("bugfixer@website.de", "JavaScript-Fehler!", $mailtext, "");
?>
<HTML>
<HEAD>
<TITLE>Fehler entdeckt!</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
  window.close()
//--></SCRIPT>
</HEAD>
<BODY>Moment bitte ...</BODY>
</HTML>

Die Datei muss die Endung .php haben, und der Webserver muss natürlich für die Unterstützung von PHP korrekt konfiguriert sein!

23.2 JavaScript Debugger

Unter http://developer.netscape.com/software/jsdebug.html stellt Netscape einen kostenlosen Debugger für JavaScript-Programme zur Verfügung. Dieser bietet die Basiseigenschaften eines Debuggers, also das Setzen von Breakpoints und die Anzeige aktueller Variablenwerte während der Ausführung (dazu jeweils später mehr). Das Programm funktioniert mit dem Netscape Navigator ab Version 4.06 (wegen der JDK1.1-Unterstützung) und baut auf der LiveConnect-Schnittstelle auf. Der Debugger selbst ist eine Java-Applikation, die über LiveConnect auf das JavaScript-Programm zugreifen kann.

Installation

Die Installation ist recht schnell bewerkstelligt – lesen Sie unter http://developer.netscape.com/software/jsdebug_license.html die Lizenzbestimmungen durch, und klicken Sie dann auf die Schaltfläche I Accept. Über den SmartUpdate-Mechanismus von Netscape wird die Software installiert (Java-Meldungen, die die Einräumung besonderer Rechte verlangen, müssen mit Grant bestätigt werden). Sodann befindet sich im Programm-Verzeichnis von Netscape (beispielsweise C:\Programme\Netscape\Communicator\Program) ein Unterverzeichnis JSDebug, in dem sich die Startseite des Debuggers befindet: jsdebugger.html.

Abbildung 23.2  Der Bildschirm nach dem Starten des Debuggers

Öffnen Sie diese Datei in Ihrem Webbrowser (wohlgemerkt: der Debugger funktioniert nur mit dem Internet Explorer!), und nach der Bestätigung weiterer Java-Meldungen erscheint das Debugger-Fenster auf dem Bildschirm.

23.2.1 Wo ist der Fehler?

Nun benötigen wir noch ein fehlerhaftes Programm. Kaufen Sie also ein Konkurrenzwerk (just kidding), oder werfen Sie einen Blick auf das folgende kurze Programm:

<HTML>
<HEAD>
<TITLE>Debugger</TITLE>
<SCRIPT LANGUAGE="JavaScript"><!--
var summe = 0
var zaehler = 0
var obergrenze
function ungerade(){
   zaehler++
   var summe = summe + zaehler
   if (zaehler<obergrenze)
     gerade()
}
function gerade(){
   zaehler++
   var summe = summe + zaehler
   if (zaehler<obergrenze)
     ungerade()
}
function sum(n){
   obergrenze = n
   ungerade()
   return summe
}
//--></SCRIPT>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript"><!--
   document.write(sum(100))
//--></SCRIPT>
</BODY>
</HTML>

Das Prinzip des obigen Programms ist relativ einfach. Hauptfunktion ist sum(n), welche die Summe der Zahlen von 1 bis n berechnet. Um das ganze ein wenig zu verkomplizieren, wird folgendermaßen vorgegangen: In der globalen Variablen summe wird das aktuelle Zwischenergebnis gespeichert, in der globalen Variable zaehler merkt sich das Programm, welche Zahlen bis jetzt schon aufsummiert worden sind. Zunächst wird die Funktion ungerade() aufgerufen, welche zunächst den Zähler um 1 erhöht (beim ersten Aufruf: auf 1), und dann den Wert des Zählers zur Zwischensumme addiert. Danach wird die Funktion gerade() aufgerufen, welche genau dasselbe erledigt: Zunächst Zähler erhöhen (beim ersten Aufruf: auf 2), und dann Zählerwert zur Zwischensumme hinzuzählen. Sobald der Zähler die Obergrenze erreicht hat, wird abgebrochen.

Schnelle Lösung

Wenn man der Legende Glauben schenkt, hat Gauß schon im Grundschulalter diese Aufgabe gelöst. Sein Lehrer wollte ihn ein wenig beschäftigen und bat ihn, die Zahlen von 1 bis 100 zu addieren. Der kleine Gauß hat ein wenig herumüberlegt und herausgefunden, dass sich die Summe der Zahlen von 1 bis n mit der Formel n(n+1) berechnen kann, bei n=100 kommt 5050 heraus.

Wenn Sie das Skript im Browser aufrufen (vorher unbedingt den Debugger starten, wie oben beschrieben!), werden Sie jedoch erstaunt feststellen, dass als Ergebnis 0 angezeigt wird. Woran kann das liegen?

Der Debugger weiß hier vielleicht Rat. Wechseln Sie ins Debugger-Fenster, klicken Sie auf die Schaltfläche Open, und klicken Sie dann doppelt auf die gerade geladene URL. Der Quellcode der Seite wird in den Debugger geladen, Skriptelemente sind dadurch durch einen ockerfarbenen Rand gekennzeichnet.

Abbildung 23.3  Code ist mit einem ockergelben Rand gekennzeichnet.

23.2.2 Breakpoints

Um den Debugger wirklich nutzen zu können, müssen Sie einen so genannten Breakpoint setzen. Die wörtliche Übersetzung, Unterbrechungspunkt oder auch Haltepunkt, ist schon sehr nahe an der Wahrheit. Sobald der JavaScript-Interpreter beim Haltepunkt angekommen ist, wird die Skriptausführung unterbrochen, und Sie können beispielsweise auf den aktuellen Wert aller Variablen zugreifen.

Breakpoints beziehen sich immer auf eine Zeile; die Programmausführung wird unterbrochen, bevor der Code in der Zeile ausgeführt wird. Prinzipiell gibt es zwei Möglichkeiten, einen Breakpoint zu setzen:

	Klicken Sie in die entsprechende Zeile, und wählen Sie in der Symbolleiste die Schaltfläche BrkPt oder den Menübefehl Control • Set Breakpoint.
	Klicken Sie in der entsprechenden Zeile in den ockerfarbenen Rand.

Egal, welche der beiden Methoden Sie einsetzen, Sie sehen danach einen roten Punkt links vom Rand, wodurch das Vorhandensein eines Breakpoints angedeutet wird.

In diesem Beispiel sollten Sie den Breakpoint in die Zeile zaehler++ der Funktion ungerade() setzen. Tun Sie das, und laden Sie im Browserfenster das (fehlerhafte) Skript erneut. Nach kurzer Zeit werden Sie im Debuggerfenster feststellen, dass sich im ockerfarbenen Rand ein kleiner Pfeil befindet, der die aktuelle Position der Skriptausführung markiert.

23.2.3 Watches

Es ist nun an der Zeit, die Werte einiger Variablen zu betrachten. Unter Windows • Watches können Sie sogenannte Watches einstellen. Das sind Variablen, deren Wert Sie permanent überwachen möchten. Mit Klick auf die Schaltfläche New können Sie eine neue Watch angeben. Es empfiehlt sich in diesem Beispiel, ein genaueres Augenmerk auf die Variablen summe und zaehler zu werfen. Erstellen Sie also zwei Watches – eine für die Variable summe, und eine für die Variable zaehler. Im Watches-Fenster werden die Variablennamen dann angezeigt. Wenn Sie die Schaltfläche eval wählen, werden die aktuellen Werte all dieser Variablen in der Konsole (rechts unten zu sehen) angezeigt.

Abbildung 23.4  Watches werden in der Konsole angezeigt.

Mit Done können Sie das Watches-Fenster wieder schließen. Sobald sich der Wert einer der Variablen ändert, wird der neue Wert in der Konsole angezeigt. Sie müssen eigentlich nur noch das Programm weiterlaufen lassen und dabei zusehen, was geschieht.

	Sollte die Konsole recht voll und unübersichtlich werden, können Sie den Inhalt mit Edit • Clear Console wieder löschen.

23.2.4 Einzelne Werte anzeigen

Erst ab Debugger-Version 1.1

Anstelle einer Watch können Sie, wenn Sie einen Wert nicht permanent überwachen möchten, sich auch nur den Wert einer beliebigen Variablen einmalig anzeigen lassen. Hierzu dient der Inspector (eine Neuerung, erst ab Version 1.1 des Debuggers). Dort können Sie vereinfacht gesagt eval()-Anweisungen ausführen. Geben Sie im Inspector-Fenster (sie können über das Menü Windows darauf zugreifen) einen Variablen- oder einen Objektnamen ein, und der entsprechende Wert wird Ihnen angezeigt.

Abbildung 23.5  Im Inspector können Sie den Wert einer Variable auswerten.

Objekthierarchien

Besonders interessant ist hier die Möglichkeit, Einsicht in Objekthierarchien zu gewinnen. Geben Sie beispielsweise im Inspector document ein. Sie sehen dann eine Auflistung aller Eigenschaften des document-Objekts, und können sich im Hierarchiebaum weiter nach unten bewegen (beispielsweise in document.forms). Insbesondere bei Mouseover-Effekten ist das sehr praktisch, wenn Sie nicht mit Bildnamen, sondern mit Indizes operieren. Schnell hat man sich verzählt, aber im Inspector sieht man genau, woran es eigentlich hakt.

Abbildung 23.6  Auflistung des document-Objekts

23.2.5 Schrittweise Programmausführung

Sie sehen in der Symbolleiste ganz rechts fünf Schaltflächen, mit denen Sie die Skriptausführung wieder in Gang setzen können. Der Reihe nach haben diese die folgenden Funktionen:

	Run: Das Programm wird weiter ausgeführt, bis es entweder am Ende ankommt oder wieder bei einem Breakpoint stehen bleiben muss.
	Over: Es wird zur nächsten Zeile in der aktuellen Funktion gesprungen. Sollte der Interpreter am Ende der Funktion angelangt sein, verhält sich die Schaltfläche wie Run.
	Into: Es wird zur nächsten Zeile des Programmcodes gesprungen, ganz egal, ob die innerhalb der aktuellen Funktion liegt oder außerhalb.
	Out: Die aktuelle Funktion wird verlassen, und das Programm weiter ausgeführt, bis es endet oder am nächsten Breakpoint stehen bleiben muss.
	Abort: Die Skriptausführung wird unterbrochen (beispielsweise bei einer Endlosschleife).

Beachten Sie nun genau, was geschieht, wenn Sie von der Zeile zaehler++ aus mit Into weiter vorgehen. Anfangs hat zaehler einen Wert von 0 und summe einen Wert von null. Nach der Ausführung des Kommandos zaehler++ hat zaehler den Wert 1, der Wert von summe hat sich nicht geändert. In der nächsten Zeile jedoch ändert sich der Wert von summe. Nicht, wie erhofft auf 1, sondern auf ... NaN, not a number. Warum nur?

Der Fehler im Skript

Mit ein wenig Überlegung ist klar, wo der Fehler liegt. Vor der Anweisung summe = summe + zaehler steht ein var. Dadurch wird summe innerhalb der Funktion ungerade() – und analog dazu auch in gerade() – zu einer lokalen Variablen, deren Wert außerhalb der Funktion nicht sichtbar ist. Die Variable summe ist aber eigentlich als globale Variable konzipiert.

Entfernen Sie sowohl in der Funktion ungerade() als auch in der Funktion gerade() das Schlüsselwort var vor summe, brechen Sie im Debugger die Skriptausführung ab, wählen Sie dann den Menübefehl File • Refresh All, und laden Sie die Seite im Browser neu. Ein Blick in die Konsole verheißt Gutes, denn nun wird summe anständig erhöht. Und wenn Sie nun noch den Breakpoint entfernen (Control • Clear Breakpoint, oder in den ockerfarbenen Bereich klicken) und das Skript durchlaufen lassen, sehen Sie im Browser auch das korrekte Ergebnis – 5050. Wir haben zwar etwas länger gebraucht als der kleine Gauß, aber dafür durften wir ja auch nicht per Hand rechnen.

23.3 Fragen

1.	Erstellen Sie die oben angedeutete Lösung, beim Auftreten einer Fehlermeldung per clientseitigem mailto:-Formular eine E-Mail an Sie zu erzeugen. Aus den bekannten Gründen müssen Sie das Skript ein wenig abändern – Ihr Besucher muss das Formular von Hand verschicken, Sie benötigen also eine Versenden-Schaltfläche.
2.	Was könnten Sie tun, wenn Sie wissen, dass in einer ganz bestimmten Zeile bei ganz bestimmten Browsern ein Fehler auftritt, den Sie einfach nicht beheben können? Oder, anders gefragt: Wie unterdrücken Sie ausschließlich diese Fehlermeldung?
3.	Haben Sie eine Vermutung, wieso der Wert von summe im (falschen) Debugger-Beispiel den Wert null hatte, und nicht den Wert 0?
4.	Versuchen Sie zu bergründen, wozu der Befehl Control • Edit Breakpoint (ist aktiv, wenn sich der Cursor in einer Zeile mit einem Breakpoint befindet) dient.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 24 Lösungen

Kapitel 24 Lösungen

Prüfungen sind deshalb so scheußlich, weil der größte Trottel mehr fragen kann, als der klügste Mensch zu beantworten vermag.

– Charles Caleb Colson

In diesem Kapitel finden Sie die Lösungen zu den Aufgaben der vorhergehenden Kapitel. Aus Platzgründen sind die Lösungen sehr kurz gefasst und meistens ist nur der wichtige Code wiedergegeben. Die Lösungen zu den schwierigsten Aufgaben sind meistens recht lang. Aus diesem Grund finden Sie sie in MyGalileo.

Kapitel 3

1.	Winnie-the-Pooh ist ungültig wegen der Minus-Zeichen, 1Winnie wegen der führenden Ziffer, Winnie Pooh wegen dem Leerzeichen. Die anderen Variablennamen sind gültig.
2.	Mit dem Backslash kann man Anführungszeichen in JavaScript-Zeichenketten entwerten, aber nicht innerhalb von HTML-Tags. Für den HTML-Interpreter endet daher die Zeichenkette nach dem Backslash und nicht nach der schließenden Klammer.
3.	Bei einer do-while-Schleife wird der Anweisungsblock auf jeden Fall mindestens einmal ausgeführt; bei einer while-Schleife nur dann, wenn die Bedingung am Anfang erfüllt ist.
4.	while (Zeichenkette.indexOf(" ")>-1){ io = Zeichenkette.indexOf(" ") Zeichenkette = Zeichenkette.substring(0, io) + "%20" +       Zeichenkette.substring(io+1, Zeichenkette.length) }

Kapitel 4

1.	Es war freigestellt, welches der Beispiele umgeschrieben werden sollte; an dieser Stelle wird das Beispiel mit dem Array vorgeführt. Hierbei muss bedacht werden, dass auf den Dezember der Januar folgt, man benötigt also beispielsweise ein weiteres Formularelement.
var m = new MakeArray(13)

m[0] = "Unbekannter Monat"

m[1] = "Januar"

m[2] = "Februar"

m[3] = "März"

m[4] = "April"

m[5] = "Mai"

m[6] = "Juni"

m[7] = "Juli"

m[8] = "August"

m[9] = "September"

m[10] = "Oktober"

m[11] = "November"

m[12] = "Dezember"

m[13] = "Januar"

monat =  11

document.write("Der nächste Monat heißt: "+ m[monat+1])

2.	Es bleibt nur noch die switch-Anweisung übrig:
switch (monat){

   case 12: var m = "Januar"; break

   case 1: var m = "Februar"; break

   case 2: var m = "März"; break

   case 3: var m = "April"; break

   case 4: var m = "Mai"; break

   case 5: var m = "Juni"; break

   case 6: var m = "Juli"; break

   case 7: var m = "August"; break

   case 8: var m = "September"; break

   case 9: var m = "Oktober"; break

   case 10: var m = "November"; break

   case 11: var m = "Dezember"; break

   default: var m = "Unbekannter Monat"

}

document.write(m)

3.	Die folgende Funktion erfüllt alle Teile der Aufgabenstellung:
function istSchaltjahr(n){

   return (n%4==0&&(n%100!=0||n%400==0))

}

4.	Idee: für alle Zahlen von 2 bis n-1 wird geprüft, ob sie einen Teiler der Zahl darstellen. Es gibt effizientere Algorithmen, diese darzustellen soll aber nicht Teil dieses Buches sein.
function istPrim(n){

   if (n=1)

      return false

   for (var i=2; i<n; i++)

      if (n%i==0)

         return false

   return true

}

5.	Die entsprechenden Funktionen sind Methoden, da sie mit Klammern aufgerufen werden und Parameter haben.
function MakeArray(n,m){

  for (var i=0; i<n; i++)

     this [i] = (m==null)? 0:m

  this.length=n

}

Kapitel 5

1.	Anhand des Werts, der von getTime() zurückgeliefert wird, kann die ungefähre Jahreszahl bestimmt werden (Wert ist die Anzahl der seit dem 1. Januar 1970 verstrichenen Millisekunden), indem der Wert durch 1 000 ¥ 60 ¥ 60 ¥ 24 ¥ 365.25 dividiert wird und das Ergebnis zu 1970 dazugezählt wird. Der Rest geht wie bekannt.
2.	Man benötigt mehrere if-Abfragen, um Dubletten zu verhindern.
   var z1 = Math.floor(49*Math.random())+1

   var z2=z1

   while (z1==z2)

      z2 = Math.floor(49*Math.random())+1

   var z3=z1

   while (z1==z3||z2==z3)

      z3 = Math.floor(49*Math.random())+1

   var z4=z1

   while (z1==z4||z2==z4||z3==z4)

      z4 = Math.floor(49*Math.random())+1

   var z5=z1

   while (z1==z5||z2==z5||z3==z5||z4==z5)

      z5 = Math.floor(49*Math.random())+1

   var z6=z1

   while (z1==z6||z2==z6||z3==z6||z4==z6||z5==z6)

      z6 = Math.floor(49*Math.random())+1

   var zusatz=z1

   while(z1==zusatz||z2==zusatz||z3==zusatz||z4==zusatz||

     z5==zusatz||z6==zusatz)

      zusatz = Math.floor(49*Math.random())+1

3.	Anstelle der document.write()-Anweisungen muss man location.href=zufallsurl verwenden, das war aber auch schon alles.
4.	Nach der Bestimmung von Browserhersteller und Versionsnummer benötigt man lediglich noch folgende Zeilen:
browserurl = (netscapebrowser) ? "nn" : "ie"

location.href = browserurl + versionsnummer + ".html"

Kapitel 6

1.	Es gibt mit JavaScript alert()-Fenster, confirm()-Fenster und prompt()-Fenster. Man verwendet alert() zur Ausgabe von Hinweistexten, während confirm() dem Benutzer eine Ja/Nein-Abfrage präsentiert. Bei prompt() kann der Benutzer einen Text eingeben.
2.	Mit window.back() navigiert man durch die globale History des Fenster, während window.history.back() auf die lokale History des einzelnen Frames beschränkt ist.
3.	Bei history.go(0) bleiben Formulareingaben erhalten (weiches Neuladen), bei location.reload() nicht (hartes Neuladen).
4.	Die drei Möglichkeiten sind:
JavaScript-Neuladen innerhalb des Werbeframes:

setTimeout("location.reload()", 120000)

Rekursives JavaScript-Neuladen von einem anderen Frame aus:

function neuladen(){

   top.werbeframe.location.reload()

   setTimeout("neuladen()", 120000)

}

neuladen()

Die dritte Möglichkeit besteht aus purem HTML:

<META HTTP-EQUIV="REFRESH" CONTENT="120">

Kapitel 7

1.	Diese Aufgabe läßt sich in Anlehnung an Kapitel 6 lösen:
<HTML>

<HEAD>

<TITLE>Laufschrift</TITLE>

<SCRIPT LANGUAGE="JavaScript"><!--

var lauftext = " +++ Read my lips: no tax on beer "

function laufschrift(){

   document.forms[0].lauf.value = lauftext

   lauftext = lauftext.substring(1, lauftext.length) +

     lauftext.substring(0,1)

   setTimeout("laufschrift()", 100)  //Weiter nach einer Zehntelsekunde

}

//--></SCRIPT>

</HEAD>

<BODY onLoad="laufschrift()">

<H3>Laufschrift mit JavaScript</H3>

<FORM>

<INPUT TYPE="TEXT" NAME="lauf" onFocus="this.blur()">

</FORM>

</BODY>

</HTML>

2.	Zur Strategie: Als Zeichensatz sollte eine nichtproportionale Schrift eingestellt werden, und Sie müssen mitzählen, welches Zeichen sich gerade links im Texteingabefeld befindet, um festzustellen, welche News gerade angezeigt wird. Hier nun der entsprechende Code:
<HTML>

<HEAD>

<TITLE>Laufschrift</TITLE>

<SCRIPT LANGUAGE="JavaScript"><!--

var trenn = "  +++  "  //Trennzeichen im Ticker

var position = 0       //globale Variable, zählt die Position

var meldungen = new Array()

meldungen[0] = "Netscape Navigator – einer der ersten Browser"

meldungen[1] = "Internet Explorer – der momentane Marktführer"

meldungen[2] = "Opera – Der Geheimtipp aus dem fernen Norwegen"

var urls = new Array()

urls[0] = "http://home.netscape.com/download"

urls[1] = "http://www.microsoft.com/windows/ie_intl/de/

  download/default.htm"

urls[2] = "http://www.opera.com"

var lauftext = ""

for (var i=0; i<meldungen.length; i++)

  lauftext += meldungen[i] + trenn

function laufschrift(){

  document.forms[0].lauf.value = lauftext

  lauftext = lauftext.substring(1, lauftext.length) + lauftext.substring(0, 1)

  position = (position < lauftext.length-1) ? position + 1 : 0

  setTimeout("laufschrift()", 100)

}

function go(){

  var laenge = 0

  for (var i=0; i<meldungen.length; i++){

    laenge += meldungen[i].length + trenn.length

    if (laenge>position){

      location.href = urls[i]

      return true

    }

  }

}

//--></SCRIPT>

<STYLE><!--

  INPUT {font-family: Courier;}

--></STYLE>

<BODY onLoad="laufschrift()">

<H3>Laufschrift mit JavaScript</H3>

<FORM>

<FONT FACE="Courier New,Courier">

<INPUT TYPE="TEXT" NAME="lauf" onFocus="go()" SIZE="30">

</FONT>

</FORM>

</BODY>

</HTML>

3.	Der Fehler liegt in dieser Zeile:
eval("var radiogroup = f."+i.name)

Erinnern Sie sich daran, dass Sie bei f.elements[] nicht unbedingt einen numerischen Index verwenden müssen, sondern auch das name-Attribut des gewünschten Formularelements übergeben können. Das folgende Kommando macht das Skript wirklich universell:

var radiogroup = f.elements[i.name]

4.	Sie müssen sich eine Namenskonvention für Pflichtfelder einfallen lassen, beispielsweise »NAME-Attribut beginnt mit p_«. Das können Sie dann in der for-in-Schleife ungefähr so überprüfen:
if (i.value==""&&i.name.indexOf("p_")==0)

   ...

5.	<HTML> <HEAD> <TITLE>Navigation mit JavaScript</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- function laden(f){ if (f.auswahl.selectedIndex>0)  location.href = f.auswahl.options[f.auswahl.          selectedIndex].value } //-->  </SCRIPT> </HEAD>  <BODY> <H3>Navigation mit JavaScript</H3>  <FORM> <SELECT NAME="auswahl" onChange="laden(this.form)"> <OPTION>Bitte wählen</OPTION>  <OPTION VALUE="http://www.compaq.de">Compaq</OPTION>  <OPTION VALUE="http://www.dell.de">Dell</OPTION>  <OPTION VALUE="http://www.hewlett-packard.de">HP</OPTION>  </SELECT>  <INPUT TYPE="BUTTON" VALUE="Laden"  onClick="laden(this.form)">   </FORM> </BODY> </HTML>

Kapitel 8

1.	Von C nach H: parent.parent.parent.frames[1].frames[1].frames[1]
Von H nach C: parent.parent.parent.frames[0].frames[2].frames[0] Von A nach I: parent.parent.frames[2] Von I nach A: parent.frames[0].frames[0] Sie dürfen top nicht verwenden, da die Seite laut Aufgabenstellung ja selbst auch in einem Unterframe aufgerufen werden kann.

2.	Sie müssen die Funktion rekursiv wieder aufrufen:
function subframes(frameref){

   if (frameref.frames.length==0)

      return 1

   else{

      var summe = 0

      for (var i=0; i<frameref.frames.length; i++)

         summe += subframes(frameref.frames[i])

      return summe

   }

}

3.	Die Lösung zu dieser Aufgabe finden Sie (aufgrund der Länge und der Verteilung auf mehrere Dateien) in MyGalileo.

Kapitel 9

1.	Sie benötigen zwei Grafiken, eine leer Füllgrafik leer.gif und eine sichtbare Grafik nichtleer.gif.
<HTML><HEAD><TITLE>Hier gehts zum Chat</TITLE>

<SCRIPT LANGUAGE="JavaScript"><!--

function omo(num){

   if (document.images) {

      if (num==0) {

         document.images[0].src="leer.gif"

         document.images[1].src="nichtleer.gif"}

   else {

      document.images[1].src="leer.gif"

      document.images[0].src="nichtleer.gif"}

   }

}

//--></SCRIPT>

</HEAD>

<BODY>

<A HREF="#" onMouseover="omo(0)"><IMG SRC="nichtleer.gif"

  BORDER=0></A>

<HR>

<A HREF="#" onMouseover="omo(1)"><IMG SRC="leer.gif"

  BORDER=0></A>

</BODY></HTML>

2.	Sie müssen hierzu mit Timeouts arbeiten. Jede Sekunde muss sich die Grafik bewegen, außer, der Benutzer fährt mit der Maus darüber. Dann muss der Timeout gelöscht werden und ein neuer gestartet werden. Das komplette Skript finden Sie in MyGalileo.
3.	Der einzige Unterschied im HTML-Code liegt darin, dass die aktuelle Unterkategorie durch die fette Grafik dargestellt wird. Dies kann mit JavaScript erledigt werden, indem der onLoad-Event-Handler jedes <BODY>-Tags auf init() gesetzt wird. Diese Funktion sieht dann folgendermaßen aus:
function init(){

   for (var i=1;i<=urls.length;i++)

      klapp_zu(i)

   var img = eval("document.menu_"+kategorie+"_"+menuepunkt)

   img.src="menu_"+kategorie+"_"+menuepunkt+"_f.gif"

}

4.	Der Trick besteht hier darin, die Funktion fertig() mit Timeouts peridodisch, etwa einmal pro Sekunde, aufzurufen.

Kapitel 10

1.	Das geht analog zur Standard-Fernsteuerung. Die Links haben dann alle das Format <A HREF="#Marke" TARGET="Ziel">...</A>
2.	Die Koordinaten der linken oberen Ecke berechnen sich nach folgender Formel:
x = (Bildschirmbreite – Browserbreite) / 2

y = (Bildschirmhöhe – Browserhöhe) / 2

Damit läßt sich die Funktion einfach schreiben:

function center(){

   var x = (screen.availWidth – window.outerWidth) / 2

   var y = (screen.availHeight – window.outerHeight)

   window.moveTo(x, y)

}

3.	Ganz einfach: Man scrollt sehr weit nach unten; der Browser scrollt dann soweit wie nur möglich:
window.scrollBy(0, 10000)

4.	Wie im Kapitel gezeigt, gibt es keine Fensteroptionen, die das neue Fenster im Internet Explorer 4 in der linken oberen Ecke öffnen. Aber es gibt dennoch einen Ausweg: moveTo() gibt es in dieser Browserversion schon!
var w = window.open("", "w", "height=100,width=100")

w.moveTo(0,0)

Kapitel 11

1.	Man unterscheidet zwischen temporären und permanenten Cookies; Definitionen im Kapitel.
2.	Die bereits bekannten Funktionen getCookie() und setCookie() werden verwendet:
var anzahl = getCookie("Besuche")

if (anzahl=="")

   anzahl = 0

setCookie("Besuche", anzahl+1)

3.	Nicht möglich, da Cookies nicht browserübergreifend gespeichert werden.
4.	Man kann die Zeit messen, die zwischen dem Setzen des Cookies und der Ausführung des nächsten Befehls vergeht. Erhält der Benutzer beim Setzen von Cookies eine Warnmeldung, so wird der nächste JavaScript-Befehl erst dann ausgeführt, wenn der Benutzer die Warnmeldung bestätigt oder das Cookie abgelehnt hat. Die Unterscheidung zwischen Cookie akzeptieren/ablehnen geschieht wie gehabt:
vat t1 = new Date().getTime()

setCookie("test", "test")

var t2 = new Date().getTime()

var test = getCookie("test")

if (t2-t1>100)

   document.write("Warnmeldung<BR>")

else

   document.write("Keine Warnmeldung<BR>")

if (test=="test)

   document.write("Cookie akzeptiert")

else

   document.write("Cookie abgelehnt")

5.	Die (recht lange) Lösung zu dieser Aufgabe finden Sie in MyGalileo.

Kapitel 12

1.	Sie müssen <INPUT TYPE="SUBMIT" VALUE="Zum Download"> ersetzen durch <INPUT TYPE="BUTTON" VALUE="Zum Download" onClick="download()">. Die Funktion download() sieht dann folgendermaßen aus:
function download(){

   var ls = ""

   if (document.forms[0].sommer.checked)

      ls += "&sommer=on"

   if (document.forms[0].othello.checked)

      ls += "&othello=on"

   if (document.forms[0].venedig.checked)

      ls += "&venedig=on"

   if (ls.charAt(0)=="&")

      ls = ls.substring(1, ls.length)

   location.href="download.html?"+ls

}

2.	Die Lösung gestaltet sich analog zu einer Übungsaufgabe aus Kapitel 7, »Formular I«, und wird deshalb hier nicht aufgeführt.
3.	Unter anderem sind die folgenden Kriterien denkbar:
		Genau ein Klammeraffe in der Zeichenkette
		Mindestens ein Punkt nach dem Klammeraffen
		Das dritt-, viert- oder fünftletzte Zeichen muss ein Punkt sein.
4.	Vierbuchstabige Wörter: \w\w\w\w
		Gerade, positive Zahlen: (\d)*[02468]
		Jahreszahlen aus dem 20. Jahrhundert: 19\d\d
		Email-Adressen (einfache Prüfung):  [a-zA-Z0-9_-~]*@[a-zA-Z0-9_-~]*\.[a-zA-Z0-9_-~]* (Zeichenfolge-@-Zeichenfolge-.-Zeichenfolge)
function lohn(s){

   var zeit = /(\d\d):(\d\d)/

   if (zeit.test(s)){

      stunde = s.replace(zeit, "$1")

      minute = s.replace(zeit, "$2")

      return 8*stunde + minute*8/60

}

5.	Dreibuchstabige Wörter werden durch den regulären Ausdruck \w\w\w dargestellt, und beim Aufruf von replace() muss das Dollerzeichen entwertet werden (also \$0). Der Rest läuft wie im Kapitel ab.
6.	Der entsprechende reguläre Ausdruck lautet ganz einfach <[^<]*> – keine weitere öffnende spitze Klammer ist erlaubt.

Kapitel 13

1.	function numsort(a, b){ return a-b }
2.	Das Einfügen in den Konstruktor wird hier nicht vorgeführt, lediglich die Funktion selbst. Die Eigenschaft length muss um Eins verringert werden, und zur Sicherheit wird der Wert des letzten Elements gelöscht.
function arraypop(){

   this[this.length-1] = ""

   this.length--

}

3.	function arrayswap(i, j){  var temp = this[j] this[j] = this[i] this[i] = temp }
4.	function arraysplice(ab, anzahl){  for (var i=ab+anzahl, i<this.length; i++) this[i-anzahl] = this[i] this.length -= anzahl }
5.	Beim Mischen kann die Funktion arraysplice() verwendet werden. Das komplette Listing finden Sie hier:
<HTML>

<HEAD>

<TITLE>Karten spielen mit JavaScript</TITLE>

<SCRIPT LANGUAGE="JavaScript"><!--

//Funktionen des MakeArray-Objekts

function MakeArray(){

   for (var i=0; i<MakeArray.arguments.length; i++)

      this[i] = MakeArray.arguments[i]

   this.length = MakeArray.arguments.length

   this.toString = arraytoString

   this.push = arraypush

   this.sort = arraysort

   this.splice = arraysplice

}

//Methoden

function arraytoString(){

   var returnstring = ""

   for (var i=0; i<this.length-1; i++)

      returnstring += this[i] + ","

   returnstring += this[this.length-1]

   return returnstring

}

function arraypush(){

   for (var i=0; i<arraypush.arguments.length; i++)

      this[this.length+i] = arraypush.arguments[i]

   this.length += arraypush.arguments.length

}

function arraysort(){

   var sortiert = false //Überprüfung, ob sortiert

   while (!sortiert){

      sortiert = true

      for (var i=0; i<this.length-1; i++)

         if (groesser(this[i], this[i+1], arraysort.arguments[0])){

            sortiert = false

            hilfsvariable = this[i]

            this[i]=this[i+1]

            this[i+1] = hilfsvariable

         }

   }

}

function arraysplice(ab, anzahl){

   for (var i=ab+anzahl; i<this.length; i++)

      this[i-anzahl] = this[i]

   this.length -= anzahl

}

function groesser(a, b, arg){

   if (!arg)

      return (a>b)

   else{

      var erg = eval(arg + "(\"" + a + "\", \"" + b + "\")")

      return (erg>0)

   }

}

// *** Das eigentliche Programm ***

//Hilfsvariablen für die Kartenbezeichnungen

var kartenname = new MakeArray("Zwei", "Drei", "Vier", "Fünf",

  "Sechs", "Sieben", "Acht", "Neun", "Zehn", "Bube", "Dame",

  "König", "As")

var farben = new MakeArray("Herz", "Karo", "Pik", "Kreuz")

//Initialisierung des Kartenarrays

var cards = new MakeArray()

for (var i=0; i<13; i++)

   for (var j=0; j<4; j++){

      karte = kartenname[i]+" "+farben[j]

      cards.push(karte)

   }

//Karten mischen

var cards2 = new MakeArray()

while (cards.length>0){

   var zufall = Math.floor(Math.random()*cards.length)

   karte = cards[zufall]

   cards.splice(zufall, 1)

   cards2.push(karte)

}

//Karten auf vier Personen verteilen

var hand1 = new MakeArray()

var hand2 = new MakeArray()

var hand3 = new MakeArray()

var hand4 = new MakeArray()

for (i=0; i<=12; i++)

   hand1.push(cards2[i])

for (i=13; i<=25; i++)

   hand2.push(cards2[i])

for (i=26; i<=38; i++)

   hand3.push(cards2[i])

for (i=39; i<=51; i++)

   hand4.push(cards2[i])

//Karten sortieren

hand1.sort("cardsort")

hand2.sort("cardsort")

hand3.sort("cardsort")

hand4.sort("cardsort")

//Sortierfunktion

function cardsort(a, b){

   var wert_a = a.substring(0, a.indexOf(" "))

   var wert_b = b.substring(0, b.indexOf(" "))

   var index_a = -1; var index_b = -1

   for (var i=0; i<kartenname.length; i++){

      if (kartenname[i]==wert_a)

         index_a = i

      if (kartenname[i]==wert_b)

         index_b = i

   }

   if (index_a>index_b) return 1

   else if (index_a<index_b) return -1

   var farbe_a = a.substring(a.indexOf(" ")+1, a.length)

   var farbe_b = b.substring(b.indexOf(" ")+1, b.length)

   return (farbe_a>farbe_b) ? 1 : 0

}

//--></SCRIPT>

</HEAD>

<BODY>

<H3>Karten spielen mit JavaScript</H3>

<SCRIPT LANGUAGE="JavaScript"><!--

function br() { return "<" + "BR" + ">" }

document.write("Hand 1: " + hand1.toString() + br())

document.write("Hand 2: " + hand2.toString() + br())

document.write("Hand 3: " + hand3.toString() + br())

document.write("Hand 4: " + hand4.toString() + br())

//--></SCRIPT>

</BODY>

</HTML>

Kapitel 15

1.	Vereinfacht gesagt durchwandern Ereignisse beim Netscape Navigator die Objekthierarchie von oben nach unten, beim Internet Explorer von unten nach oben.
2.	Laden Sie das folgende Dokument in Ihren Webbrowser und doppelklicken Sie in das Fenster.
<HTML>

<HEAD>

<TITLE>Neue Mausereignisse</TITLE>

<SCRIPT LANGUAGE="JavaScript"><!--

function mclick() { window.status += "[click]" }

function mup() { window.status += "[mouseup]" }

function mdown() { window.status += "[mousedown]" }

function init(){

   window.status = ''

   with (document){

      onclick = mclick

      onmouseup = mup

      onmousedown = mdown

   }

}

window.onload = init

//--></SCRIPT>

</HEAD>

<BODY>

<H3>Neue Mausereignisse</H3>

</BODY>

</HTML>

3.	Mit handleEvent() kann man ein Ereignis an ein anderes Objekt weiterleiten; routeEvent() sorgt dafür, dass ein mit captureEvents() angefangenes Ereignis dort ausgeführt wird, wofür es bestimmt war.
		a.Der Event-Handler wird mit return false verlassen.
		b.cancelBubble wird auf true gesetzt.
		c.Man ist oben in der Objekthierarchie angekommen.
4.	Die entsprechende JavaScript-Funktion finden Sie im Folgenden abgedruckt, der HTML-Teil wird ausgelassen.
function mclick(e){

   var ev = (window.Event) ? e : window.event

   var ziel = (window.Event) ? ev.target : ev.srcElement

   location.href = ziel.value

}

if (window.Event)

   document.captureEvents(Event.MOUSEUP)

document.onclick = mclick

5.	Die Zeile
} else { //IE

muss geändert werden in

} else if (window.event){

Kapitel 16

1.	Mittels parentLayer.parentLayer.document.
a. von rechts:

var layer_x

function init(){

   if (document.layers){

      layer_x = document.logo.left

      document.logo.left += 500

      //Animation starten

      animate()

   }

}

function animate(){

   if (document.logo.left<layer_x)

      document.logo.left = layer_x

   if (document.logo.left>layer_x){

      document.logo.left -= 3

      setTimeout("animate()", 50)

   }

}

b. von links oben:

var layer_x, layer_y

function init(){

   if (document.layers){

      layer_x = document.logo.left

      layer_y = document.logo.top

      document.logo.left -= 200

      document.logo.top -= 200

      //Animation starten

      animate()

   }

}

function animate(){

   if (document.logo.left>layer_x)

      document.logo.left = layer_x

   if (document.logo.left<layer_x){

      document.logo.left += 3

   if (document.logo.top>layer_y)

      document.logo.top = layer_y

   if (document.logo.top<layer_y){

      document.logo.top += 3

      setTimeout("animate()", 50)

   }

}

2.	Sie stellen eine Überlappung des Textes fest. Dies läßt sich verhindern, wenn eine Hintergrundfarbe definiert wird Beispielsweise könnte man den Inhalt jedes Registers in eine Tabelle legen, die eine weiße Hintergrundfarbe hat.
3.	Wenn Sie irgend etwas in Richtung window.close() versucht haben, haben Sie leider aufs falsche Pferd gesetzt. Dabei ist die Lösung gar nicht so schwer: Die visibility-Eigenschaft muss auf hidden gesetzt werden:
<A HREF="javascript:document.logo.visibility='hidden';"> ...

Kapitel 17

1.	Da der <DIV>-Container kein eigenes Unterobjekt mit document-Eigenschaft ist, kann man ganz einfach mit dem Schlüsselwort document auf das Hauptdokument zugreifen.
2.	a. von rechts:
function init(){

   if (document.all)

      document.all.logo.style.posLeft += 500

   //Animation starten

   animate()

}

function animate(){

   if (document.all.logo.style.posLeft<0)

      document.all.logo.style.posLeft = 0

   if (document.all.logo.style.posLeft>0){

      document.all.logo.style.posLeft -= 3

      setTimeout("animate()", 50)

   }

}

b. von links oben

function init(){

   if (document.all)

      document.all.logo.style.posLeft -= 200

      document.all.logo.style.posTop -= 200

   //Animation starten

   animate()

}

function animate(){

   if (document.all.logo.style.posLeft>0)

      document.all.logo.style.posLeft = 0

   if (document.all.logo.style.posLeft<0){

      document.all.logo.style.posLeft += 3

   if (document.all.logo.style.posTop>0)

      document.all.logo.style.posTop = 0

   if (document.all.logo.style.posTop<0){

      document.all.logo.style.posTop += 3

      setTimeout("animate()", 50)

   }

}

3.	Siehe Lösung zu Aufgabe 16.5:
<A HREF="javascript:document.all.logo.style.visibility='hidden';"> ...

Kapitel 18

1.	Da der <DIV>-Container kein eigenes Unterobjekt mit document-Eigenschaft ist, kann man ganz einfach mit dem Schlüsselwort document auf das Hauptdokument zugreifen.
2.	a. von rechts:
function init(){

   if (document.getElementById)

      document.getElementById("logo").style.left =

         parseInt(document.getElementById("logo").style.left)

           + 500

   //Animation starten

   animate()

}

function animate(){

   if (parseInt(document.getElementById("logo").style.left)<0)

      document.getElementById("logo").style.left = 0

   if (parseInt(document.getElementById("logo").style.left)){

      document.getElementById("logo").style.left -= 3

      setTimeout("animate()", 50)

   }

}

b. von links oben

function init(){

   if (document.getElementById)

      document.getElementById("logo").style.left =

         parseInt(document.getElementById("logo").style.left)

           – 200

      document.getElementById("logo").style.top =

         parseInt(document.getElementById("logo").style.top)

           – 200

   //Animation starten

   animate()

}

function animate(){

   if (parseInt(document.getElementById("logo").style.left)>0)

      document.getElementById("logo").style.left = 0

   if (parseInt(document.getElementById("logo").style.left)<0){

      document.getElementById("logo").style.left =

         parseInt(document.getElementById("logo").style.left) + 3

   if (parseInt(document.getElementById("logo").style.top)>0)

      document.getElementById("logo").style.top = 0

   if (parseInt(document.getElementById("logo").style.top)<0){

      document.getElementById("logo").style.top =

         parseInt(document.getElementById("logo").style.top) + 3

      setTimeout("animate()", 50)

   }

}

3.	Siehe Lösung zu Aufgabe 16.5:
<A HREF="javascript:document.getElementById('logo').style.

  visibility = 'hidden';"> ...

Kapitel 19

1.	Siehe Lösung zu Aufgabe 17.1 und 18.1 – das geht browserübergreifend mit document.
2.	Zwei Funktionen, setzelinks() und setzeoben(), werden eingeführt. Der Rest des Codes geht analog zu den Aufgaben in den vorherigen drei Kapiteln und wird deswegen nicht mehr extra aufgeführt.
function setzelinks(n){

   if (document.all)

      document.all.logo.style.posLeft = n

   else if (document.layers)

      document.logo.left = n

   else if (document.getElementById)

      document.getElementById("logo").style.left = n

}

function setzeoben(n){

   if (document.all)

      document.all.logo.style.posTop = n

   else if (document.layers)

      document.logo.top = n

   else if (document.getElementById)

      document.getElementById("logo").style.top = n

}

3.	Diese Lösung ist die Verbindung der Aufgaben 16.5, 17.3 und 18.3. Aus Übersichtlichkeitsgründen wird das Ausblenden des Werbebanners in eine Funktion ausgegliedert:
function bannerweg(){

   if (document.all)

      document.all.logo.style.visibility = 'hidden'

   else if (document.layers)

      document.logo.visibility = 'hidden'

   else if (document.getElementById)

      document.getElementById("logo").style.visibility = 'hidden'

}

Es muss nur noch der Link entsprechend angepaßt werden:

<A HREF="javascript:bannerweg()"> ...

Kapitel 20

1.	Nein! Diese Verwechslung wird von Anfängern oft gemacht, aber spätestens nach Lektüre des Kapitels dürften einige Unterschiede klar sein.
2.	Java ist plattformunabhängig. Kostspielige Portierungen auf andere Plattformen entfallen also.
3.	Als public deklarierte Methoden können von überall aus aufgerufen werden, auch von JavaScript aus; bei private ist das nicht möglich. Wenn man nicht will, dass jede Eigenschaft der Methode direkt manipuliert wird, sollte man sie als private deklarieren und statt dessen eine public-Methode zum Ändern der Eigenschaft anbieten. Vor allem, wenn Methoden und Eigenschaften direkt zusammenhängen (vergleiche beispielsweise das MakeArray-Objekt), ist es sinnvoll, so genanntes Data Hiding zu betreiben.
4.	Eine Methode besteht darin, ein neues Fenster mit dem Applet zu öffnen. Da der Name des Applets bekannt ist, können Sie mit document.write() HTML-Code mit dem Applet erzeugen. Sie haben dann Zugriff auf alle als public deklarierten Methoden des Applets.
appleturl = "http://www.ihrserver.de/applets/applet.class"

var f = window.open("", "appletwindow")

f.document.open()

f.document.write("<HTML><BODY><APPLET NAME='a' CODE='"

  + appleturl + "'></APPLET></BODY></HTML>")

f.document.close()

//Zugriff ab jetzt mit f.document.a.methode()

Kapitel 22

1.	Als Parameter an mausklick() wird der anfängliche Index der Grafik übergeben. Wird aber beispielsweise die erste Grafik entfernt, so gibt es keine Grafik mit Index 3 mehr, ein Klick auf die am weitesten rechts stehende Grafik führt also zu einer Fehlermeldung.
2.	Eine der (vielen) Möglichkeiten besteht darin, in einem Array den aktuellen Index in childNodes[] der aktuellen Grafik zu speichern. Nach jedem Löschen wird das Array angepaßt.
3.	Auch hier kann man wieder ein Array verwenden, in welchem der aktuelle Status der entsprechenden Grafik gespeichert wird (noch nie angeklickt, einmal angeklickt).

Kapitel 23

1.	Die Lösung zu dieser Aufgabe finden Sie online bei MyGalileo.
2.	Die Nummer der Zeile, in der der Fehler aufgetreten ist, wird als dritter Parameter an die Fehlerbehandlungsfunktion übergeben. Sie können also explizit darauf prüfen, ob der Fehler in der einen bestimmten Zeile aufgetreten ist, und dann die Funktion mit return true verlassen.
3.	Der Debugger hat vermutlich das Programm analysiert und festgestellt, dass eine neue Variable mit Namen summe in der Funktion definiert wird.
4.	Es gibt auch sogenannte bedingte Breakpoints. Beispielsweise können Sie den Debugger instruieren, bei einem bestimmten Breakpoint nur anzuhalten, wenn eine Variable einen bestimmten Wert hat. Die Bedingung ist mit true vorbesetzt, und das ist immer erfüllt, deswegen führen Breakpoints normalerweise immer zur Unterbrechung des Programms, außer Sie ändern das eben um.
<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	Galileo Computing / <openbook> / JavaScript	vor >>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		Kapitel 25 Referenz
			25.1 Das Anchor-Objekt
			25.2 Das Array-Objekt
			25.3 Das Button-Objekt
			25.4 Das Checkbox-Objekt
			25.5 Das Date-Objekt
			25.6 Das document-Objekt
			25.7 Das event-Objekt
			25.8 Das FileUpload-Objekt
			25.9 Das Form-Objekt
			25.10 Das Frame-Objekt
			25.11 Das Hidden-Objekt
			25.12 Das History-Objekt
			25.13 Das Image-Objekt
			25.14 Das Layer-Objekt
			25.15 Das Link-Objekt
			25.16 Das Location-Objekt
			25.17 Das Math-Objekt
			25.18 Das MimeType-Objekt
			25.19 Das Navigator-Objekt
			25.20 Das Number-Objekt
			25.21 Das Object-Objekt
			25.22 Das Option-Objekt
			25.23 Das Password-Objekt
			25.24 Das Plugin-Objekt
			25.25 Das Radio-Objekt
			25.26 Das RegExp-Objekt
			25.27 Das Reset-Objekt
			25.28 Das Screen-Objekt
			25.29 Das Select-Objekt
			25.30 Das String-Objekt
			25.31 Das Submit-Objekt
			25.32 Das Text-Objekt
			25.33 Das Textarea-Objekt
			25.34 Das Window-Objekt
			25.35 Top-Level-Eigenschaften und -Methoden

Kapitel 25 Referenz

Kein Buch ist so schlecht, dass es nicht auch irgendwie nützlich sein könnte.

– Plinius Junior

	In diesem abschließenden Referenzkapitel werden nur die wichtigsten Browser betrachtet. Netscape 6 (basierend auf der »Gecko«-Engine) wurde nicht explizit aufgenommen, denn die einzigen Änderungen sind DOM-bezogen, und dadurch (noch) nicht relevant, solange der Browser noch keinen stabilen Stand erreicht hat.

Seit dem Netscape Navigator 3 bzw. Internet Explorer 4 kennt jedes Objekt die Methode toString(), welche eine Zeichenkettenrepräsentation des Objekts wiedergibt. So wird beispielsweise ein wahrer Boolescher Wert in "true" umgewandelt.

Die Tabelle 25.1 gibt wieder, welche Browser welche JavaScript-Versionen unterstützen. Sofern es in der Implementierung Abweichungen gibt (ein Objekt wird etwa erst ab JavaScript 1.1 unterstützt, aber auch vom Internet Explorer 3), so wird das bei der Beschreibung des Objekts angegeben.

Tabelle 25.1  JavaScript-Versionen und die jeweiligen Browser

JavaScript-Version	ab ...	ab ...
1.0	Netscape Navigator 2	Internet Explorer 3
1.1	Netscape Navigator 3	Internet Explorer 4
1.2	Netscape Navigator 4	Internet Explorer 4 (in Teilen); Internet Explorer 5 (fast vollständig)
1.3	Netscape Navigator 4.06	Internet Explorer 5
1.5	Netscape 6	/

Der Internet Explorer 5 hat nur wenige Methoden oder Eigenschaften des Netscape Navigator 4 übernommen; die meisten neuen Netscape-Funktionen, die im Internet Explorer 5 vorhanden sind, waren schon in Version 4 implementiert.

Bei der Auflistung der Methoden wird nur dann eine Syntax angegeben, wenn die Methode Parameter akzeptiert. Eckige Klammern in der Parameterliste stehen für optionale Werte.

Bei jedem Objekt ist anfangs angegeben, ab welcher JavaScript-Version es unterstützt wird. Bei den Methoden und Eigenschaften ist nur dann eine JavaScript-/Browser-Version angegeben, wenn diese sich von der vorherigen Version unterscheidet.

Tabelle 25.2 enthält die Event-Handler, die von JavaScript erkannt werden.

Tabelle 25.2  Event-Handler

Event-Handler	Beschreibung
onAbort	Abbruch beim Laden (z. B. Grafik)
onBlur	Verlust des Fokus
onClick	Anklicken mit der Maus
onDragDrop	Drag&Drop-Operation
onError	JavaScript-Fehler
onFocus	Erhalt des Fokus
onKeyDown	Niederdrücken einer Taste
onKeyPress	Tastendruck
onKeyUp	Loslassen einer Taste
onLoad	Vollständiges Laden
onMouseDown	Niederdrücken einer Maustaste
onMouseOut	Mauszeiger verläßt Objekt
onMouseOver	Mauszeiger über Objekt
onMouseUp	Loslassen einer Maustaste
onMove	Mausbewegung
onReset	Formular wird zurückgesetzt
onResize	Fenstergröße wird verändert
onSelect	Element wird ausgewählt
onSubmit	Formular wird abgeschickt
onUnload	Dokument wird »entladen« (neues Dokument wird geladen, Fenster wird geschlossen)

Die aktuellen Versionen der Dokumentationen gibt es online bei den jeweiligen Browserherstellern:

Netscape:

http://devedge.netscape.com/docs/manuals/javascript.html

Microsoft:

http://msdn.microsoft.com/scripting/jscript/techinfo/jsdocs.html

http://msdn.microsoft.com/workshop/author/

25.1 Das Anchor-Objekt

JS 1.0

Ab JavaScript 1.0

Das Anchor-Objekt, eine Eigenschaft des document-Objekts, ist ein Array, das alle Textmarken innerhalb eines Dokuments enthält.

25.1.1 Allgemeines

HTML-Tag: <A NAME="Name">

Mit folgendem Beispielcode werden alle Linkziele im Dokument ausgegeben:

<HTML>
<HEAD>
<SCRIPT LANUGAGE="JavaScript"><!--
function zeige_links(){
   var text = ""
   for (var i=0; i<document.anchors[].length)
      text += i + ": " + document.anchors[i] + "\n"
   alert(text)
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="zeige_links()">
...
</BODY>
</HTML>

25.1.2 Eigenschaften

name

JS 1.2

NAME-Attribut der Textmarke; ab JavaScript 1.2; nur Schreibzugriff

text

JS 1.2

Text der Textmarke; ab JavaScript 1.2; nur Schreibzugriff

x

JS 1.2

x-Koordinate der linken oberen Ecke der Textmarke; ab JavaScript 1.2; nur Schreibzugriff

y

JS 1.2

y-Koordinate der linken oberen Ecke der Textmarke; ab JavaScript 1.2; nur Schreibzugriff

Im folgenden Beispiel werden die Textmarken-Eigenschaften ausgegeben:

<HTML>
<HEAD>
<SCRIPT LANUGAGE="JavaScript"><!--
function zeige_eigenschaften(){
   var text = ""
   text += "name: "+document.anchors[0].name
   text += "text: "+document.anchors[0].text
   text += "x: "+document.anchors[0].x
   text += "y: "+document.anchors[0].y
   alert(text)
}
//--></SCRIPT>
</HEAD>
<BODY onLoad="zeige_eigenschaften()">
<A NAME="Textmarke">Galileo Press</A>
</BODY>
</HTML>

25.2 Das Array-Objekt

JS 1.1

Ab JavaScript 1.1

In einem Array werden mehrere Daten abgespeichert und über einen nummerischen Index verwaltet. Beim Netscape Navigator 2 ist das Array-Objekt nur unter UNIX implementiert, beim Internet Explorer 3 nur unvollständig. Die meisten Methoden können aber nachgeahmt werden. Genauere Informationen dazu finden Sie im Kapitel »Arrays«.

25.2.1 Allgemeines

new Array()
new Array(Größe)
new Array(Element1, Element2, ..., ElementN)

Größe – (Anfängliche) Anzahl der Elemente im Array. Diese Methode funktioniert ab JavaScript 1.2 nicht mehr, dort wird jeder Parameter als Array-Element behandelt.

Element1, Element2, ..., ElementN – Anfängliche Elemente im Array

Auf die einzelnen Elemente des Arrays wird über den entsprechenden Index (er beginnt bei 0) zugegriffen: arrayname[3] greift auf das vierte Element zu.

25.2.2 Methoden

concat

JS 1.2

Verbindet zwei oder mehr Arrays; ab JavaScript 1.2.

concat(Array1, Array2, ..., ArrayN)

Array1, Array2, ..., ArrayN – Ein oder mehrere Arrays

Die Methode liefert ein neues Array zurück, das aus den Elementen des aufrufenden Arrays und den als Parameter übergebenen Arrays besteht.

var arr1 = new Array(1, 2, 3)
var conc = arr1.concat(new Array("4", "5", "6"))
//conc enthält nun die Elemente 1, 2, 3, "4", "5", "6")

join

Wandelt die Array-Elemente in eine Zeichenkette um; der Separator kann als Parameter übergeben werden.

join(Separator)

Separator – Trennzeichen

var arr = new Array(1, 2, 3)
var joinarr = arr.join("-")
//joinarr hat nun den Wert "1-2-3"

pop

JS 1.2

Das letzte Element des Arrays wird entfernt und zurückgegeben; ab JavaScript 1.2.

pop()
var arr = new Array(1, 2, 3)
var elem = arr.pop()
//arr hat nun die Elemente 1 und 2; elem den Wert 3

push

JS 1.2/1.3

Fügt ein oder mehrere Zeichen hinten an das Array an. Die Anzahl der Elemente nach dieser Operation (JavaScript 1.3) bzw. das zuletzt hinzugefügte Element (JavaScript 1.2) wird zurückgegeben.

push(Element1, Element2, ..., ElementN)
Element1, Element2, ..., ElementN – Neue Array-Elemente
var arr = new Array(1, 2, 3)
var newlen = arr.push(2, 1)
//arr hat nun die Elemente 1, 2, 3, 2 ,1;
//newlen den Wert 5 (JS1.3) bzw. 1 (JS1.2)

reverse

Kehrt die Reihenfolge der Elemente im Array um.

reverse()
var arr = new Array(1, 2, 3)
var revarr = arr.reverse()
//revarr hat nun die Elemente 3, 2, 1

shift

JS 1.2

Das erste Element des Arrays wird entfernt und zurückgegeben; ab JavaScript 1.2.

shift()
var arr = new Array(1, 2, 3)
var elem = arr.shift()
//arr hat nun die Elemente 2, 3; elem hat den Wert 1

slice

JS 1.2

Entfernt Elemente aus einem Array und liefert die restlichen Elemente als Array zurück. Das ursprüngliche Array wird nicht geändert; ab JavaScript 1.2.

slice(Start[, Ende])

Start – Index des ersten Elements, das entfernt werden soll

Ende – Index des ersten Elements, das nicht mehr entfernt werden soll. Fehlt diese Angabe, so werden alle Elemente ab Start entfernt; ist der Parameter negativ, so wird von hinten gezählt.

var arr1 = new Array(1, 2, 3, 4, 5)
var arr1_1 = arr1.slice(1, 3)
//arr1_1 hat nun die Elemente 1, 4, 5
var arr2 = new Array(1, 2, 3, 4, 5)
var arr2_1 = arr2.slice(3)
//arr2_1 hat nun die Elemente 1, 2, 3
var arr3 = new Array(1, 2, 3, 4, 5)
var arr3_1 = arr3.slice(0, -2)
//arr3_1 hat nun die Elemente 1, 2

sort

JS 1.2

Sortiert die Elemente des Arrays alphanumerisch. Ab JavaScript 1.2 kann eine Sortierfunktion angegeben werden (vgl. Kapitel »Arrays«).

sort([Sortierfunktion])

Sortierfunktion – Funktion, über die man die Reihenfolge der Elemente bestimmen kann, indem bei je zwei Werten zurückgegeben wird, welches Element größer ist.

var arr1 = new Array(5, 3, 11)
arr1.sort()
//arr1 hat nun die Elemente 11, 3, 5 (alphanumerisch)
function numsort(a, b){ return a-b }
var arr2 = new Array(5, 3, 11)
arr2.sort(numsort)
//arr2 hat nun die Elemente 3, 5, 11

splice

JS 1.2

Entfernt Elemente aus einem Array und fügt neue Elemente an (optional); ab JavaScript 1.2; Rückgabewert ab JavaScript 1.3 die entfernten Elemente.

splice(Start, Wie viele[, Element1, Element2, ..., ElementN])

Start – Index des ersten Elements, das entfernt werden soll.

Wie viele – Anzahl der Elemente, die ab Start entfernt werden sollen.

Element1, Element2, ..., ElementN – (Optionale) Elemente, die hinten an das Array angefügt werden sollen.

var arr1 = new Array(1, 2, 3, 4, 5)
var splicearr = arr1.splice(1, 2, 3, 4, 5)
//splicearr hat nun die Elemente 1, 4, 5, 3, 4, 5

unshift

JS 1.2

Fügt ein oder mehr Elemente vorn an das Array an und gibt die neue Länge des Arrays zurück; ab JavaScript 1.2.

var arr = new Array(1, 2, 3)
var unsh = arr.unshift(4, 5)
//arr hat nun die Elemente 4, 5, 1, 2, 3; unsh den Wert 5

25.2.3 Eigenschaften

length

Anzahl der Elemente im Array, wird automatisch angepaßt.

var arr = new Aray(1, 2, 3, 4, 5)
//arr.length hat nun den Wert 5

25.3 Das Button-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird eine Schaltfläche in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.3.1 Allgemeines

HTML-Tag: <INPUT TYPE="BUTTON">

document.forms[Index].elements[index]
document.FormularName.ButtonName

Index – Index im jeweiligen Array

ButtonName – NAME-Attribut der Schaltfläche

25.3.2 Event-Handler

onBlur (JS1.1)
onFocus (JS1.1)
onClick
onMouseDown (JS1.2)
onMouseUp (JS1.2)

25.3.3 Methoden

blur

JS 1.1

Entfernt den Fokus von der Schaltfläche; ab JavaScript 1.1.

click

JS 1.1

Simuliert das Anklicken der Schaltfläche.

focus

Gibt der Schaltfläche den Fokus; ab JavaScript 1.1.

25.3.4 Eigenschaften

form

Referenz auf das Formular, das die Schaltfläche enthält.

name

NAME-Attribut der Schaltfläche.

type

JS 1.1

Zeichenkette mit dem Wert "button"; ab JavaScript 1.1.

value

VALUE-Attribut der Schaltfläche.

25.4 Das Checkbox-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird eine Schaltfläche in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.4.1 Allgemeines

HTML-Tag: <INPUT TYPE="CHECKBOX">

document.forms[Index].elements[Index]
document.FormularName.CheckboxName

Index – Index im jeweiligen Array

CheckboxName – NAME-Attribut der Checkbox

25.4.2 Event-Handler

onBlur (JS1.1)
onFocus (JS1.1)
onClick

25.4.3 Methoden

blur

Entfernt den Fokus von der Checkbox.

click

Simuliert das Anklicken der Checkbox.

focus

Gibt der Checkbox den Fokus.

25.4.4 Eigenschaften

checked

Der Wert ist true, wenn die Checkbox angekreuzt ist, ansonsten false.

defaultChecked

Der Wert ist true, wenn die Checkbox HTML-mäßig angekreuzt ist (durch Parameter CHECKED), ansonsten false.

form

Referenz auf das Formular, das die Checkbox enthält.

name

NAME-Attribut der Checkbox

type

JS 1.1

Zeichenkette mit dem Wert "checkbox"; ab JavaScript 1.1.

value

VALUE-Attribut der Checkbox; wenn sie nicht gesetzt ist, ist der Wert "on".

25.5 Das Date-Objekt

JS 1.0

Ab JavaScript 1.0

JS 1.3

In einer Instanz des Date-Objekts kann ein Datumswert gespeichert werden. Es ist nicht nötig, die aktuelle Systemzeit zu verwenden. Erst ab JavaScript Version 1.3 sind Datumswerte vor dem 1. Januar 1970 möglich.

25.5.1 Allgemeines

new Date()  //erstellt Datumsvariable mit lokaler Zeit
new Date(Millisekunden_seit_1970)
new Date(Jahr, Monat, Tag)
new Date(Jahr, Monat, Tag, Stunden, Minuten, Sekunden,
  Millisekunden)  //vor JS1.3
new Date(Jahr, Monat, Tag, Stunden, Minuten, Sekunden)  //JS1.3
new Date(Datumsstring_im_GMT_Format)

Millisekunden_seit_1970 – Anzahl der seit dem 1. Januar 1970, Mitternacht, verstrichenen Millisekunden (in der Unix-Welt verbreitetes Datumsformat).

Jahr – Jahreszahl des Datumswertes.

Monat – Um eins verringerte Monatszahl des Datumswerts.

Tag – Tageszahl des Datumswertes.

Stunden – Stundenzahl des Datumswertes.

Minuten – Minutenzahl des Datumswertes.

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

Datumsstring_im_GMT_Format – Zeichenkette der Form "Dec 24, 1999 12:34:56"; die Monatsabkürzungen müssen im amerikanischen Format angegeben werden.

25.5.2 Methoden

getDate

Tageszahl des Datumswertes.

getDay

Wochentag des Datumswertes. Dabei steht 0 für Sonntag, 1 für Montag, 6 für Samstag.

getFullYear

JS 1.2

Vollständige Jahreszahl; bei Datumswerten zwischen 1000 und 9999 also vierstellig; ab JavaScript 1.2.

getHours

Stundenzahl des Datumswertes.

getMilliseconds

Millisekundenzahl des Datumswertes.

getMinutes

Minutenzahl des Datumswertes.

getMonth

Um eins verringerte Monatszahl des Datumswertes (0 ist Januar, 11 ist Dezember).

getSeconds

Sekundenzahl des Datumswertes.

getTime

Anzahl der zwischen dem 1. Januar 1970, Mitternacht, und dem Datumswert verstrichenen Millisekunden. Wie im Kapitel »Erste Schritte« gezeigt wurde, kann man so einfach die Differenzen zwischen zwei Datumswerten berechnen.

getTimezoneOffset

Unterschied zwischen der lokalen Zeitzone und Greenwich Mean Time (GMT) in Minuten.

getUTCDate

JS 1.3

Tagesszahl des Datumswertes nach UTC (Universal Time Coordinate); ab JavaScript 1.3.

getUTCDay

JS 1.3

Wochentag des Datumswertes nach UTC; 0 ist Sonntag, 1 ist Montag, 6 ist Samstag; ab JavaScript 1.3.

getUTCFullYear

JS 1.3

Volle (also zwischen 1000 und 9999 vierstellige) Jahreszahl des Datumswerts nach UTC; ab JavaScript 1.3.

getUTCHours

JS 1.3

Stundenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

getUTCMilliseconds

JS 1.3

Millisekundenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

getUTCMinutes

JS 1.3

Minutenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

getUTCMonth

JS 1.3

Um eins verringerte Monatszahl des Datumswertes nach UTC; ab JavaScript 1.3.

getUTCSeconds

JS 1.3

Sekundenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

getYear

Jahresszahl des Datumswertes; Vorgänger von getFullYear(). Die Plattformunterschiede werden im Kapitel »Erste Schritte« beschrieben.

parse

Anzahl der Millisekunden seit dem 1. Januar 1970, Mitternacht, und dem als Parameter übergebenen Datumswert.

Date.parse(Datum_im_GMT_Format)

setDate

Setzt die Tageszahl des Datumswertes.

setDate(Tag)

Tag – Tageszahl des Datumswertes.

setFullYear

JS 1.2

Setzt die vollständige Jahreszahl; bei Datumswerten zwischen 1000 und 9999 also vierstellig; ab JavaScript 1.2.

setFullYear(Jahr)

Jahr – Jahreszahl des Datumswertes

setHours

JS 1.0

Setzt die Stundenzahl des Datumswertes.

setHours(Stunden)  //ab JS1.0
setHours(Stunden, Minuten, Sekunden, Millisekunden)  //JS1.3

Stunden – Stundenzahl des Datumswertes.

Minuten – Minutenzahl des Datumswertes.

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

setMilliseconds

JS 1.3

Setzt die Millisekundenzahl des Datumswertes; ab JavaScript 1.3.

setMilliseconds(Millisekunden)

Millisekunden – Millisekundenzahl des Datumswertes.

setMinutes

JS 1.0

Setzt die Minutenzahl des Datumswertes.

setMinutes(Minuten) //ab JS1.0
setMinutes(Minuten, Sekunden, Millisekunden)  //JS1.3

Minuten – Minutenzahl des Datumswertes.

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

setMonth

Setzt die Monatszahl des Datumswertes (0 ist Januar, 11 ist Dezember).

setMonth(Monat)  //ab JS1.0
setMonth(Monat, Tag)  //JS1.3

Monat – Um eins verringerte Monatszahl des Datumswerts.

Tag – Tageszahl des Datumswertes.

setSeconds

Setzt die Sekundenzahl des Datumswertes.

setSeconds(Sekunden)  //ab JS1.0
setSeconds(Sekunden, Millisekunden)  //JS1.3

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

setTime

Setzt die Datumsvariable; der Parameter ist die Anzahl der zwischen dem 1. Januar 1970, Mitternacht, und dem Datumswert verstrichenen Millisekunden.

setTime(Millisekunden_seit_1970)

Millisekunden_seit_1970 – Anzahl der seit dem 1. Januar 1970, Mitternacht, verstrichenen Millisekunden (in der Unix-Welt verbreitetes Datumsformat).

setUTCDate

JS 1.3

Setzt die Tageszahl des Datumswertes nach UTC (Universal Time Coordinate); ab JavaScript 1.3.

setUTCDate(Tag)

Tag – Tageszahl des Datumswertes.

setUTCFullYear

JS 1.3

Setzt die volle (also zwischen 1000 und 9999 vierstellige) Jahreszahl des Datumswerts nach UTC; ab JavaScript 1.3.

setUTCFullYear(Jahr)

Jahr – Jahreszahl des Datumswertes.

setUTCHours

JS 1.3

Setzt die Stundenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

setUTCHours(Stunden[, Minuten, Sekunden, Millisekunden])

Stunden – Stundenzahl des Datumswertes.

Minuten – Minutenzahl des Datumswertes.

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

setUTCMilliseconds

JS 1.3

Setzt die Millisekundenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

setUTCMilliseconds(Millisekunden)

Millisekunden – Millisekundenzahl des Datumswertes.

setUTCMinutes

JS 1.3

Setzt die Minutenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

setUTCMinutes(Minuten[, Sekunden, Millisekunden])

Minuten – Minutenzahl des Datumswertes.

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

setUTCMonth

JS 1.3

Setzt den Monat des Datumswertes nach UTC (0 entspricht Januar, 11 entspricht Dezember); ab JavaScript 1.3.

setUTCMonth(Monat[, Tag])

Monat – Um Eins verringerte Monatszahl des Datumswerts.

Tag – Tageszahl des Datumswertes.

setUTCSeconds

JS 1.3

Setzt die Sekundenzahl des Datumswertes nach UTC; ab JavaScript 1.3.

setUTCSeconds(Sekunden[, Millisekunden])

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

setYear

Setzt die Jahreszahl des Datumswertes; Vorgänger von getFullYear(). Die Plattformunterschiede werden im Kapitel »Erste Schritte« beschrieben.

setYear(Jahr)

Jahr – Jahreszahl des Datumswertes.

toGMTString

Wandelt die Datumsvariable in eine GMT-Zeichenkette um; Vorgänger von toUTCString().

toLocaleString

Wandelt die Datumsvariable in eine Zeichenkette entsprechend den lokalen Gegebenheiten um. Diese Funktion bedient sich des Betriebssystems des Benutzers, um beispielsweise die Monatsnamen in der jeweiligen Sprache angeben zu können.

toString

JS 1.1

Wandelt die Datumsvariable in eine Zeichenkette um; ab JavaScript 1.1.

toUTCString

JS 1.3

Wandelt die Datumsvariable in eine Zeichenkette nach UTC um; ab JavaScript 1.3.

UTC

Gibt die Anzahl der Millisekunden in einer Datumsvariable seit dem 1. Januar 1970 an, entsprechend UTC (Universal Time Coordinate). Die Methode gibt kein Date-Objekt zurück, sondern nur eine Zahl. Sie wird eher als Methode des Date-Objekts aufgerufen und nicht als Methode einer Instanz des Date-Objekts.

Date.UTC(Jahr, Monat, Tag[, Stunden, Minuten, Sekunden])
   //ab JS1.0
Date.UTC(Jahr, Monat, Tag[, Stunden, Minuten, Sekunden,
  Millisekunden])  //ab JS1.3

Jahr – Jahreszahl des Datumswertes.

Monat – Um eins verringerte Monatszahl des Datumswerts.

Tag – Tageszahl des Datumswertes.

Stunden – Stundenzahl des Datumswertes.

Minuten – Minutenzahl des Datumswertes.

Sekunden – Sekundenzahl des Datumswertes.

Millisekunden – Millisekundenzahl des Datumswertes.

25.6 Das document-Objekt

JS 1.0

Ab JavaScript 1.0

Mit dem document-Objekt kann man auf die HTML-Seite zugreifen und auch HTML-Seiten erzeugen.

25.6.1 Allgemeines

HTML-Tag: <BODY>

25.6.2 Event-Handler

onClick
onDblClick (JS1.2)
onKeyDown (JS1.2)
onKeyPress (JS1.2)
onKeyUp (JS1.2)
onMouseDown (JS1.2)
onMouseUp (JS1.2)

25.6.3 Methoden

captureEvents

JS 1.2

Alle angegebenen Ereignisse werden abgefangen, siehe Kapitel »Events«; ab JavaScript 1.2, nur Netscape.

document.captureEvents(Ereignis1 | Ereignis2 | ... | EreignisN)

Ereignis1, Ereignis2, ..., EreignisN – Ereignisse, z. B. Event.MOUSEUP.

close

Beendet eine mit document.open() gestartete Ausgabe und bringt den Browser dazu, diese Ausgabe zu rendern.

document.open()
document.write("Read my lips")
document.close()

contextual

JS 1.2

Setzt Styles für Elemente innerhalb eines bestimmten Kontextes; ab JavaScript 1.2, nur Netscape.

contextual(Kontext1, Kontext2, ..., KontextN, Stil)

Kontext1, Kontext2, ..., KontextN – Ereignisse, z. B. Event.MOUSEUP.

Stil – Der zu ändernde Style

Aufgrund folgenden Codes werden alle fett gedruckten Zeichen innerhalb eines Absatzes grün angezeigt:

contextual(document.tags.P, document.tags.B).color = "green"

getSelection

JS 1.2

Gibt den gerade markierten Text des Dokuments zurück; ab JavaScript 1.2.

Diese Methode kann nicht von anderen Frames aus aufgerufen werden.

handleEvent

JS 1.2

Ruft den Event-Handler für ein bestimmtes Ereignis auf; ab JavaScript 1.2, nur Netscape.

document.handleEvent(Ereignis)

Ereignis – Ereignisobjekt.

Für Anwendungsbeispiele siehe Kapitel »Events«

open

Initiiert eine Ausgabe von HTML-Code mittels JavaScript; dies wird jedoch erst sichtbar, wenn die Ausgabe mit document.close() beendet wird. Bestehender HTML-Code wird dabei überschrieben, ein Anhängen ist also nicht möglich.

document.open()  //ab JavaScript 1.0
document.open(MIME_Type)  //Netscape, ab Internet Explorer 4
document.open(MIME_Type, ersetzen)  //nur ab Netscape 4

MIME_Type – MIME-Typ der folgenden Daten. In der Regel ist das "text/html" (und der Internet Explorer läßt nur diesen Typ zu), aber möglich sind auch beispielsweise "image/gif" oder "plugIn".

ersetzen – Boolesche Variable, die angibt, ob das neue Dokument das alte in der History-Liste des Browsers ersetzen soll.

document.open()
document.write("Read my lips")
document.close()

releaseEvents

JS 1.2

Deaktiviert ein vorhergehendes captureEvents(); ab JavaScript 1.2, nur Netscape.

document.releaseEvents(Ereignis1 | Ereignis2 | ... | EreignisN)

Ereignis1, Ereignis2, ..., EreignisN – Ereignisse, z. B. Event.MOUSEUP.

Für Anwendungsbeispiele siehe Kapitel »Events«.

routeEvent

JS 1.2

Führt ein abgefangenes Ereignis dort aus, wofür es bestimmt war; ab JavaScript 1.2, nur Netscape.

document.routeEvent(Ereignis)

Ereignis – Ereignisobjekt.

Für Anwendungsbeispiele siehe Kapitel »Events«.

write

Gibt HTML-Code mittels JavaScript aus; dies wird jedoch erst sichtbar, wenn die Ausgabe mit document.close() beendet wird. Ein vorhergehendes document.open() ist optional.

document.write(Text)

Text – Auszugebender Text.

document.open()
document.write("Read my lips")
document.close()

writeln

Gibt HTML-Code mittels JavaScript aus und fügt – im Gegensatz zu document.write() – einen Zeilenvorschub an.

document.writeln([Text])

Text – Auszugebender Text.

Wird kein Parameter angegeben, so wird eine Leerzeile ausgegeben. Diese ist jedoch bei HTML-Dokumenten im Allgemeinen nicht sichtbar.

document.open()
document.write("Read my lips")
document.close()

25.6.4 Eigenschaften

alinkColor

Farbe eines aktiven Links (während er angeklickt wird, bevor der Benutzer die Maustaste wieder losläßt). HTML-Äquivalent: <BODY ALINK="Farbe">. Als Farbe wird entweder ein hexadezimales RGB-Tripel oder ein Farbcode übergeben.

document.alinkColor = "red"
document.alinkColor = "#ff0000"

all

Ermöglicht den Zugriff auf Style-Eigenschaften; ab Internet Explorer 4. Siehe Kapitel »DHTML II«

anchors

Array, das alle Textmarken im Dokument enthält. Siehe Anchor-Objekt.

applets

Array, das alle Applets im Dokument enthält. Zu Interaktion mit Java siehe Kapitel »Java«.

bgColor

Hintergrundfarbe des Dokuments. HTML-Äquivalent: <BODY BGCOLOR= "Farbe">. Als Farbe wird entweder ein hexadezimales RGB-Tripel oder ein Farbcode übergeben.

document.bgColor = "white"
document.bgColor = "#ffffff"

classes

JS 1.2

Erzeugt eine Style-Sheet-Klasse, die im HTML-Code angesprochen werden kann; ab JavaScript 1.2, nur Netscape.

<STYLE TYPE="text/javascript">
   classes.GalileoBlau.all.color = "blue"
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
   document.classes.GalileoBlau.all.color = "blue"
</SCRIPT>

cookie

Zeichenkette, die alle Cookies enthält, auf die von der HTML-Seite aus zugegriffen werden darf. Für Anwendungen siehe Kapitel »Cookies«.

domain

JS 1.1

Enthält den Domainnamen des Servers, auf dem die aktuelle HTML-Seite liegt; ab JavaScript 1.1.

Aufgrund von Sicherheitsbestimmungen hat man von JavaScript aus von einem Dokument mit dem Domainnamen www.server.de keinen Zugriff auf gewisse Objekte in einem anderen Frame mit dem Domainnamen www2.server.de; hier sollte man document.domain auf server.de setzen, damit der Zugriff wieder funktioniert.

embeds

JS 1.1

Array, das alle mit dem <EMBED>-Tag eingefügten Daten enthält (bzw. zumindest deren Anzahl); ab JavaScript 1.1.

alert("Dieses Dokument enthält "
 + document.embeds.length + " eingebettete Dateien")

fgColor

(Vordergrund-)farbe des Dokuments. HTML-Äquivalent: <BODY COLOR= "Farbe">. Als Farbe wird entweder ein hexadezimales RGB-Tripel oder ein Farbcode übergeben.

document.fgColor = "black"
document.fgColor = "#000000"

forms

Array, das alle Formulare in einem HTML-Dokument enthält. Siehe Kapitel »Formulare I«.

document.forms[Index]
document.forms["FormularName"]
document.FormularName

Index – Nummer des Formulars im Dokument (bei mehreren Formularen); die Zählung beginnt bei 0.

FormularName – NAME-Attribut des Formulars.

height

JS 1.2

Höhe eines Dokuments (in Pixeln); ab JavaScript 1.2

ids

JS 1.2

Erzeugt einen Style-Sheet-Identifikator; ab JavaScript 1.2.

Siehe Kapitel »DHTML I«.

images

JS 1.1

Array, das alle Grafiken innerhalb eines HTML-Dokuments enthält; ab JavaScript 1.1 (und Internet Explorer 3 für Macintosh).

document.images[Index]
document.images["BildName"]
document.BildName

Index – Nummer der Grafik im Dokument; die Zählung beginnt bei 0.

BildName – NAME-Attribut der Grafik.

Siehe Kapitel »Images«

lastModified

Datum der letzten Änderung der Datei als Zeichenkette.

Dieser Wert wird aus dem HTTP-Header gewonnen, und die Daten darin werden zumeist vom Server aus dem Änderungsdatum der Datei auf dem Server bestimmt.

document.write("Letzte Änderung: "+document.lastModified)

layers

JS 1.2

Array, das alle Layer innerhalb eines HTML-Dokuments enthält; ab JavaScript 1.2, nur Netscape.

document.layers[Index]
document.layers["LayerName"]
document.LayerName

Index – Nummer des Layers im Dokument; Zählung beginnt bei 0.

LayerName – NAME-Attribut des Layers.

siehe Kapitel »DHTML I«

linkColor

Linkfarbe des Dokuments. HTML-Äquivalent: <BODY LINK="Farbe">. Als Farbe wird entweder ein hexadezimales RGB-Tripel oder ein Farbcode übergeben.

document.linkColor = "blue"
document.linkColor = "#0000ff"

links

Array, das alle Hyperlinks innerhalb eines HTML-Dokuments enthält.

document.links[Index]

Index – Nummer des Links im Dokument; Zählung beginnt bei 0.

siehe Link-Objekt.

plugins

JS 1.1

Array, das alle Plugins innerhalb eines HTML-Dokuments enthält; ab JavaScript 1.1, nur Netscape.

siehe Kapitel »Musik«

referrer

URL der Seite, von der aus die aktuelle Seite aufgerufen wurde; entspricht der Umgebungsvariablen HTTP_REFERER.

document.write("Sie kommen von "+document.referer)

Bei manchen Versionen des Internet Explorers 3 und 4 ist diese Eigenschaft falsch implementiert (die URL der aktuellen Seite wird zurückgegeben).

tags

JS 1.2

Erzeugt eine Style-Sheet-Klasse für einen gewissen Tag, die im HTML-Code angesprochen werden kann; ab JavaScript 1.2, nur Netscape.

Der folgende Code sorgt dafür, dass alle Level-3-Überschriften in blauer Farbe dargestellt werden:

document.tags.H3.all.color = "blue"

title

Titel des Dokuments; HTML-Äquivalent: <TITLE>Titel</TITLE>; kein Schreibzugriff.

URL

JS 1.1

Die komplette URL des aktuellen Dokuments als Zeichenkette; ab JavaScript 1.1. Ersatz für document.location, nicht zu verwechseln mit window.location.

vlinkColor

Farbe für besuchte Links des Dokuments. HTML-Äquivalent: <BODY VLINK="Farbe">. Als Farbe wird entweder ein hexadezimales RGB-Tripel oder ein Farbcode übergeben.

document.vlinkColor = "red"
document.vlinkColor = "#ff0000"

width

JS 1.2

Breite des Dokuments in Pixeln; ab JavaScript 1.2.

25.7 Das event-Objekt

Ab Netscape Navigator 4 und Internet Explorer 4; unterschiedliche Implementierung; siehe Kapitel »Events«

25.7.1 Netscape-Eigenschaften

data

Array, das die URLs als Zeichenkette enthält, die bei einer Drag&Drop-Operation (dragdrop-Ereignis) auf dem Browserfenster »fallengelassen« werden. Zugriff nur mit UniversalBrowserRead bzw. UniversalBrowserWrite.

height

Höhe des Fensters oder Frames.

layerX

x-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Layers, in dem das Ereignis eingetreten ist.

layerY

y-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Layers, in dem das Ereignis eingetreten ist.

modifiers

Sondertasten, die beim Eintreten des Ereignisses gedrückt waren ((Strg), (Alt), (Shift), (Meta)).

pageX

x-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Dokuments.

pageY

y-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Dokuments.

screenX

x-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Bildschirms.

screenY

y-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Bildschirms.

target

Referenz auf das Objekt, für das das Ereignis bestimmt war.

type

Art des Ereignisses als Zeichenkette (z. B. "click").

which

ASCII-Code der gedrückten Tastaturtaste bzw. Nummer der gedrückten Maustaste.

width

Breite des Fensters oder Frames.

x

Entspricht layerX.

y

Entspricht layerY.

25.7.2 Internet Explorer-Eigenschaften

altKey

Boolescher Wert, der angibt, ob die (Alt)-Taste beim Eintreten des Ereignisses gedrückt war.

button

Nummer der gedrückten Maustaste; Zählung beginnt bei 0.

cancelBubble

Boolescher Wert, der angibt, ob das Event-Bubbling deaktiviert werden soll.

clientX

x-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Browser-Fensters.

clientY

Y-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Browser-Fensters.

ctrlKey

Boolescher Wert, der angibt, ob die (Strg)-Taste beim Eintreten des Ereignisses gedrückt war.

fromElement

Nur bei mouseover/mouseout: Referenz auf das Objekt, von dem der Mauszeiger kommt.

keyCode

Unicode-Wert der Taste, die zum Eintreten des Ereignisses (z. B. keydown) geführt hat.

offsetX

x-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Containers, in dem das Ereignis eingetreten ist.

offsetY

y-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Containers, in dem das Ereignis eingetreten ist.

reason

Gibt das Ergebnis der Datenübertragung bei der Ereignisbehandlung zurück. 0 steht für erfolgreiche Übertragung, 1 für Abbruch der Übertragung und 2 für Übertragungsfehler.

returnValue

Wert, den der Event-Handler zurückgibt. Ist dieser false, so wird die Aktion, die das Ereignis hervorgerufen hat, abgebrochen (beispielsweise der Formularversand).

shiftKey

Boolescher Wert, der angibt, ob die (Shift)-Taste beim Eintreten des Ereignisses gedrückt war.

srcElement

Referenz auf das Objekt, für das das Ereignis bestimmt war.

screenX

x-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Bildschirms.

screenY

y-Koordinate des Mauszeigers relativ zur linken oberen Ecke des Bildschirms.

toElement

Nur bei mouseover/mouseout: Referenz auf das Objekt, zu dem der Mauszeiger geht.

type

Art des Ereignisses als Zeichenkette (z. B. "click").

x

x-Koordinate des Mauszeigers relativ zu dem CSS-positionierten Element, in dem das Ereignis ausgelöst worden ist.

x

y-Koordinate des Mauszeigers relativ zu dem CSS-positionierten Element, in dem das Ereignis ausgelöst worden ist.

25.8 Das FileUpload-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein Datei-Element in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.8.1 Allgemeines

HTML-Tag: <INPUT TYPE="FILE">

document.forms[Index].elements[index]
document.FormularName.FileUploadName

Index – Index im jeweiligen Array.

FileUploadName – NAME-Attribut des Datei-Elements.

25.8.2 Event-Handler

onBlur (JS1.1)
onChange
onFocus (JS1.1)

25.8.3 Methoden

blur

Entfernt den Fokus von dem Datei-Element.

click

Simuliert das Anklicken des Datei-Elements.

focus

Gibt dem Datei-Element den Fokus.

select

Wählt das Eingabefeld des Datei-Elements aus.

25.8.4 Eigenschaften

form

Referenz auf das Formular, das das Datei-Element enthält.

name

NAME-Attribut des Datei-Elements

type

Zeichenkette mit dem Wert "file"; ab JavaScript 1.1

value

VALUE-Attribut des Datei-Elements; kann i. d. R. nicht mit JavaScript gesetzt werden.

25.9 Das Form-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein Formular in JavaScript abgebildet; das Objekt ist ein Element des document-Objekts

25.9.1 Allgemeines

HTML-Tag: <FORM>

document.forms[Index]
document.FormularName

Index – Index im Array.

Formularname – NAME-Attribut des Formulars.

25.9.2 Event-Handler

onReset (JS1.1)
onSubmit

25.9.3 Methoden

reset

JS 1.1

Setzt alle Formularwerte auf die Standardwerte zurück; ab JavaScript 1.1.

<A HREF="document.forms[0].reset()">Formular zurücksetzen</A>

Das Formular muss keine Reset-Schaltfläche enthalten, damit das funktioniert. HTML-Äquivalent: Mausklick auf <INPUT TYPE="RESET">.

submit

Versendet das Formular; HTML-Äquivalent: Mausklick auf <INPUT TYPE="SUBMIT">.

<A HREF="document.forms[0].submit()">Formular versenden</A>

Ein Formular kann auch per Email (mailto:) oder via Usenet (news:/snews:) versandt werden, wodurch aber die E-Mail-Adresse des Versenders bekannt werden würde. Ab Netscape Navigator 3 bzw. Internet Explorer 4 kommt eine Warnmeldung, wenn der Benutzer (mit einer Submit-Schaltfläche) ein Formular an eine solche URL verschicken will. Seit JavaScript 1.1 ist es nicht mehr möglich, ein solches Formular mit submit() zu versenden.

25.9.4 Eigenschaften

action

Die URL der Seite oder des Skripts, an die das Formular verschickt wird; HTML-Äquivalent: <FORM ACTION="Seite_oder_Skript">.

elements

Array mit allen Formularelementen. Die einzelnen Elemente dieses Arrays sind vom jeweiligen Typ des Formularelements, beispielsweise Checkbox oder FileUpload.

alert("Das Formular enthält
"+document.forms[0].elements.length+" Elemente")

encoding

Die MIME-Methode, mit der die Formulardaten verschickt werden; HTML-Äquivalent: <FORM ENCTYPE="MIME_Methode">.

length

Anzahl der Formularelemente; äquivalent zu elements.length.

method

Versendemethode; entweder "post" oder "get".

name

NAME-Attribut des Formulars

target

Bezeichner für das Fenster oder den Frame, in dem die Ausgaben der Seite, an die das Formular übergeben wird, erscheinen. HTML-Äquivalent: <FORM TARGET="Bezeichner">.

document.forms[0].target = "_blank"

25.10 Das Frame-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein Frame in JavaScript abgebildet; das Objekt ist ein Element des window-Objekts. Von der Handhabung verhält sich ein Frame genauso wie ein window-Objekt, weswegen auf diesen Teil der Referenz verwiesen wird.

25.11 Das Hidden-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein verstecktes Formularfeld in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.11.1 Allgemeines

HTML-Tag: <INPUT TYPE="HIDDEN">

document.forms[Index].elements[Index]
document.FormularName.FeldName

Index – Index im jeweiligen Array.

FeldName – NAME-Attribut des versteckten Feldes.

25.11.2 Eigenschaften

form

Referenz auf das Formular, das das versteckte Feld enthält.

name

NAME-Attribut des versteckten Felds

type

JS 1.1

Zeichenkette mit dem Wert "hidden"; ab JavaScript 1.1.

value

VALUE-Attribut des versteckten Felds

25.12 Das History-Objekt

JS 1.0

Ab JavaScript 1.0

Die History-Liste eines Fensters.

25.12.1 Allgemeines

Aus offensichtlichen Gründen kann man zwar nicht die einzelnen URLs auslesen, aber man kann innerhalb der History vor- und zurückspringen.

history[Index] (JS1.1)

Index – Index im Array.

25.12.2 Methoden

back

Geht in der History einen Eintrag zurück .

forward

Geht in der History einen Eintrag vorwärts.

go

Geht in der History einen Eintrag vorwärts.

history.go(Delta)
history.go(URL)

Delta – Nummerischer Wert, um wie viele Einträge vor- (positiver Wert) oder zurückgesprungen (negativer Wert) werden soll.

URL – Der nächste History-Eintrag wird angesprungen, der die URL als Teilstring enthält.

25.12.3 Eigenschaften

current

JS 1.1

URL des aktuellen History-Eintrags; Zugriff nur mit UniversalBrowserRead; ab JavaScript 1.1.

length

Anzahl der Einträge in der History-Liste; praktisch die einzige Eigenschaft, die stets gelesen werden kann.

next

JS 1.1

URL des nächsten History-Eintrags; Zugriff nur mit UniversalBrowserRead; ab JavaScript 1.1.

previous

JS 1.1

URL des vorherigen History-Eintrags; Zugriff nur mit UniversalBrowserRead; ab JavaScript 1.1.

25.13 Das Image-Objekt

JS 1.1

Ab JavaScript 1.1 sowie Internet Explorer 3 für Macintosh

Hiermit erhält man Zugriff auf die Grafiken innerhalb eines HTML-Dokuments.

25.13.1 Allgemeines

HTML-Tag: <IMG>

new Image([Höhe, Breite])

Höhe – Höhe der Grafik in Pixeln.

Breite – Breite der Grafik in Pixeln.

document.BildName
document.images[Index]

BildName – NAME-Attribut der Grafik.

Index – Nummer des Bilds (Zählung ab 0).

25.13.2 Event-Handler

onAbort
onError
onKeyDown
onKeyPress
onKeyUp
onLoad

25.13.3 Eigenschaften

border

Dicke des Bildrahmens in Pixeln (BORDER-Attribut).

complete

Boolesche Variable, die angibt, ob ein Bild schon vollständig geladen worden ist.

height

Höhe der Grafik in Pixeln (HEIGHT-Attribut)

hspace

Horizontaler Abstand zwischen Grafik und Text (HSPACE-Attribut)

lowsrc

URL der Grafik, die vor der eigentlichen Grafik geladen werden soll (LOWSRC-Attribut).

name

NAME-Attribut der Grafik.

src

URL der Grafik, absolut oder relativ.

Im folgenden Beispiel wird die Grafik bild2.gif angezeigt, sobald der Benutzer mit dem Mauszeiger über die Grafik bild1.gif fährt.

<HTML>
<HEAD>
<SCRIPT LANUGAGE="JavaScript"><!--
   if (document.images)
      img = new Image(100, 100)
      img.src="bild2.gif"
   function swap(){
      if (document.images)
         document.bild.src = img.src
   }
//--></SCRIPT>
</HEAD>
<BODY>
<A HREF="#" onMouseover="swap()"><IMG SRC="bild1.gif" NAME=
  "bild"></A>
</BODY>
</HTML>

vspace

Vertikaler Abstand zwischen Grafik und Text (VSPACE-Attribut)

width

Breite der Grafik in Pixeln (WIDTH-Attribut)

25.14 Das Layer-Objekt

JS 1.2

Ab JavaScript 1.2; nur Netscape.

Hiermit werden HTML-Layer in JavaScript abgebildet; Eigenschaft des document-Objekts.

25.14.1 Allgemeines

HTML-Tag: <LAYER>

document.LayerName
document.layers[Index]

LayerName – NAME-Attribut des Layers.

Index – Nummer des Layers (Zählung ab 0).

25.14.2 Event-Handler

onMouseover
onMouseout
onFocus
onBlur
onLoad

25.14.3 Methoden

load

Lädt eine neue URL in den Layer.

load(URL, Breite)

URL – URL des Layers.

Breite – Breite des Layers.

moveAbove

Bewegt den Layer über einen als Parameter angegebenen Layer, ohne ihn horizontal oder vertikal zu verschieben.

moveAbove(Layer)

Layer – Referenz auf den Layer, über den der aktuelle Layer geschoben werden soll.

moveBelow

Bewegt den Layer unter einen als Parameter angegebenen Layer, ohne ihn horizontal oder vertikal zu verschieben.

moveBelow(Layer)

Layer – Referenz auf den Layer, unter den der aktuelle Layer geschoben werden soll.

moveBy

Verschiebt einen Layer horizontal und vertikal.

moveBy(hDelta, vDelta)

hDelta – Relative horizontale Verschiebung.

vDelta – Relative vertikale Verschiebung.

moveTo

Verschiebt einen Layer an die angegebene Bildschirmposition.

moveTo(x, y)

x – Neue x-Koordinate der linken oberen Ecke des Layers.

y – Neue y-Koordinate der linken oberen Ecke des Layers.

moveToAbsolute

Verschiebt einen Layer an die angegebene Position auf der Seite.

moveToAbsolute(x, y)

x – neue x-Koordinate der linken oberen Ecke des Layers.

y – neue y-Koordinate der linken oberen Ecke des Layers.

resizeBy

Verändert die Ausmaße eines Layers um einen gewissen Wert, wobei die linke obere Ecke fix bleibt.

resizeBy(hDelta, vDelta)

hDelta – Relative horizontale Veränderung in Pixeln.

vDelta – Relative vertikale Veränderung in Pixeln.

resizeTo

Verändert die Ausmaße eines Layers auf einen gewissen Wert, wobei die linke obere Ecke fix bleibt.

resizeTo(Breite, Höhe)

Breite – Neue Breite des Layers.

Höhe – Neue Höhe des Layers.

25.14.4 Eigenschaften

above

Referenz auf das Layer-Objekt, das vom Z-Index her über dem aktuellen Layer liegt. Ist der aktuelle Layer der Oberste, wird eine Referenz auf das aktuelle Fenster zurückgegeben.

background

Image-Objekt, das die Datei angibt, die als Hintergrundgrafik dient.

document.layers[0].background.src = "hintergrund.gif"

below

Referenz auf das Layer-Objekt, das vom Z-Index her unter dem aktuellen Layer liegt. Ist der aktuelle Layer der unterste, wird null zurückgegeben.

bgColor

Hintergrundfarbe des Layers, entweder mit dem Farbnamen oder dem hexadezimalen RGB-Code festgelegt.

clip.bottom

Die untere Kante des sichtbaren Bereichs des Layers.

clip.height

Die Höhe des sichtbaren Bereichs des Layers.

clip.left

Die linke Kante des sichtbaren Bereichs des Layers.

clip.right

Die rechte Kante des sichtbaren Bereichs des Layers.

clip.top

Die obere Kante des sichtbaren Bereichs des Layers.

clip.width

Die Breite des sichtbaren Bereichs des Layers.

document

Document-Objekt des Layers.

left

x-Koordinate der linken oberen Ecke des Layers relativ zum übergeordneten Layer.

name

ID-Parameter des Layers.

pageX

x-Koordinate der linken oberen Ecke des Layers relativ zur HTML-Seite.

pageY

y-Koordinate der linken oberen Ecke des Layers relativ zur HTML-Seite.

parentLayer

Referenz auf den übergeordneten Layer; sollte der nicht existieren, ist eine Referenz auf das aktuelle Fenster.

siblingAbove

Von allen Layern mit demselben übergeordneten Layer derjenige, der über dem aktuellen Layer liegt (in bezug auf den Z-Index); null, falls nicht vorhanden.

siblingBelow

Von allen Layern mit demselben übergeordneten Layer derjenige, der unter dem aktuellen Layer liegt (in bezug auf den Z-Index); null, falls nicht vorhanden.

src

URL des Layers.

top

y-Koordinate der linken oberen Ecke des Layers relativ zum übergeordneten Layer.

visibility

Gibt an, ob der Layer sichtbar ist. Bei "visible" oder "show" wird der Layer angezeigt, bei "hide" wird er versteckt, bei "inherit" wird die visibility-Eigenschaft des übergeordneten Layers verwendet.

window

Referenz auf das Fenster oder den Frame, das bzw. der den Layer enthält.

x

Äquivalent zu Layer.left.

y

Äquivalent zu Layer.top.

zIndex

Z-Index des Layers.

25.15 Das Link-Objekt

Ab JavaScript 1.0

Hiermit werden HTML-Hyperlinks und Imagemaps in JavaScript abgebildet. Das Objekt ist ein Unterobjekt des document-Objekts.

25.15.1 Allgemeines

HTML-Tag: <A HREF="Ziel_URL">Linktext</A>; <AREA>...</AREA>

document.links[Index]

Index – Nummer des Hyperlinks (Zählung ab 0).

25.15.2 Event-Handler

onClick
onDblClick (JS1.2; auch bei <AREA>)
onMouseOut (auch bei <AREA>)
onMouseOver (JS 1.1; auch bei <AREA>)
onMouseUp (JS1.2)
onMouseDown (JS1.2)

25.15.3 Eigenschaften

hash

Angabe einer Textmarke im Link.

host

Name des Hosts, also inklusive Subdomainname, aber ohne Port.

hostname

Kompletter Host, inklusive Port.

href

Komplette URL.

pathname

Kompletter Pfadname der URL (also ohne Server).

port

Portnummer (Standardwert ist 80).

protocol

Verwendetes Protokoll (z. B. "http:", "ftp:", "file:").

search

Teil der URL ab dem Fragezeichen (inklusive), sofern vorhanden.

target

Zielfenster oder -frame für den Link (TARGET-Attribut).

text

JS 1.2

Linktext; ab JavaScript 1.2.

x

JS 1.2

x-Koordinate der linken oberen Ecke des Links, relativ zur HTML-Seite; ab JavaScript 1.2.

y

JS 1.2

y-Koordinate der linken oberen Ecke des Links, relativ zur HTML-Seite; ab JavaScript 1.2.

25.16 Das Location-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit kann man auf die URL des aktuellen Dokuments zugreifen.

25.16.1 Methoden

reload

Lädt das Dokument neu; ab JavaScript 1.1.

location.reload(keinCache)

keinCache – Boolescher Wert, der angibt, ob die Seite mit einem sogenannten »unconditional GET« vom Webserver geholt werden soll (also kein Caching) oder nicht.

replace

JS 1.1

Lädt eine neue URL und ersetzt die alte URL in der History-Liste; ab JavaScript 1.1.

location.replace(URL)

URL – URL des zu ladenden Dokuments.

Der Netscape Navigator 2 kennt die Methode location.assign(), die dasselbe erledigt; sie ist aber nicht dokumentiert, so dass Sie folgendes verwenden sollten:

if (!location.replace)
   location.replace = location.assign

25.16.2 Eigenschaften

hash

Textmarke in der URL.

host

Name des Hosts, also inklusive Subdomainname, aber ohne Port.

hostname

Kompletter Host, inklusive Port.

href

Komplette URL.

pathname

Kompletter Pfadname der URL (also ohne Server).

port

Portnummer (Standardwert ist 80).

protocol

Verwendetes Protokoll (z. B. "http:", "ftp:", "file:").

search

Teil der URL ab dem Fragezeichen (inklusive), sofern vorhanden.

25.17 Das Math-Objekt

JS 1.0

Ab JavaScript 1.0

Im Math-Objekt sind mathematische Funktionen und Konstanten gespeichert.

25.17.1 Methoden

abs

Absolutbetrag einer Zahl (-5 wird zu 5, 5 bleibt 5).

Math.abs(Zahl)

Zahl – Eine Zahl.

acos

Arkuskosinus einer Zahl (Umkehrfunktion des Kosinus).

Math.acos(Zahl)

Zahl – Eine Zahl.

asin

Arkussinus einer Zahl (Umkehrfunktion des Sinus).

Math.asin(Zahl)

Zahl – Eine Zahl.

atan

Arkustangens einer Zahl (Umkehrfunktion des Tangens).

Math.atan(Zahl)

Zahl – Eine Zahl.

atan2

Arkuskosinus einer Zahl, die durch Division der beiden Parameter gebildet wird.

Math.acos(y, x)

x, y – Jeweils eine Zahl.

ceil

Kleinste Zahl größer oder gleich dem gegebenen Parameter (entspricht der Gauß-Klammer).

Math.ceil(Zahl)

Zahl – Eine Zahl.

cos

Kosinus einer Zahl.

Math.acos(Zahl)

Zahl – Eine Zahl.

exp

Potenz einer Zahl zur Basis e (Eulersche Zahl).

Math.exp(Zahl)

Zahl – Der Exponent.

floor

Größte Zahl kleiner oder gleich als der gegebene Parameter.

Math.floor(Zahl)

Zahl – Eine Zahl.

log

Logarithmus einer Zahl zur Basis e (natürlicher Logarithmus).

Math.log(Zahl)

Zahl – Eine Zahl.

max

Die größere von zwei Zahlen.

Math.max(Zahl1, Zahl2)

Zahl1, Zahl2 – Zwei Zahlen.

min

Die kleinere von zwei Zahlen.

Math.min(Zahl1, Zahl2)

Zahl1, Zahl2 – Zwei Zahlen.

pow

Berechnet die Potenz einer Zahl zu einer Basis.

Math.pow(Basis, Exponent)

Basis – Die Basis.

Exponent – Der Exponent.

random

Eine Zufallszahl zwischen 0 und 1; beim Netscape Navigator 2 nur unter UNIX.

Math.random()

round

Rundet eine Zahl zur nächsten ganzen Zahl.

Math.round(Zahl)

Zahl – Eine Zahl.

sin

Sinus einer Zahl.

Math.sin(Zahl)

Zahl – Eine Zahl.

sqrt

Quadratwurzel einer Zahl.

Math.sqrt(Zahl)

Zahl – Eine Zahl.

tan

Tangens einer Zahl.

Math.tan(Zahl)

Zahl – Eine Zahl.

25.17.2 Eigenschaften

E

Die Eulersche Konstante, etwa 2,7.

document.write(Math.E)

LN10

Logarithmus von 10 zur Basis e, etwa 2,3.

LN2

Logarithmus von 2 zur Basis e, etwa 0,7.

LOG10E

Logarithmus von E zur Basis 10, etwa 0,4.

LOG2E

Logarithmus von E zur Basis 2, etwa 1,4.

PI

Die Zahl p, etwa 3,1.

SQRT1_2

Kehrwert der Quadratwurzel 2, etwa 0,7.

SQRT2

Quadratwurzel von 2, etwa 1,4.

25.18 Das MimeType-Objekt

JS 1.1

Ab JavaScript 1.1, nur Netscape

Das Objekt ist eine Eigenschaft des navigator- und des plugin-Objekts (siehe auch Kapitel »Musik«).

25.18.1 Eigenschaften

description

Umgangssprachliche Beschreibung der mit dem MIME-Typ verknüpften Daten.

enabledPlugin

Das Plugin für einen bestimmten MIME-Typ; kann zur Überprüfung verwendet werden, ob ein Plugin installiert ist.

if (navigator.mimeTypes["application/x-flash"]){
   if (navigator.mimeTypes["application/x-flash"].enabledPlugin)
      document.write("Flash Player installiert")
} else
   document.write("Flash Player nicht installiert")

suffixes

Die von einem MIME-Typ unterstützten Dateiendungen; durch Kommata voneinander getrennt.

type

Bezeichnung des MIME-Typs.

25.19 Das Navigator-Objekt

JS 1.0

Ab JavaScript 1.0

25.19.1 Methoden

javaEnabled

Startet die Java Virtual Machine (VM), sofern vorhanden, und gibt zurück, ob der Browser die Java-Unterstützung aktiviert hat.

plugins.refresh

JS 1.1

Aktualisiert die Plugin-Liste des Browsers und macht so einen Neustart des Browsers unnötig; JavaScript 1.1, nur Netscape.

navigator.plugins.refresh(neuLaden)

neuLaden – Beim Wert true wird zusätzlich auch das aktuelle Dokument neu geladen.

preference

JS 1.2

Ein signiertes Skript kann so Benutzereinstellungen lesen und verändern; ab JavaScript 1.2, nur Netscape.

navigator.preference(Bezeichner[, Wert])

Bezeichner – Name der Benutzereinstellung, die geändert werden soll.

Wert – Neuer Wert für die Benutzereinstellung.

savePreferences

Speichert die aktuellen Benutzereinstellungen in dem Profil des Benutzers.

taintEnabled

Gibt einen Booleschen Wert zurück, der angibt, ob das Tainting (das alte Sicherheitsmodell des Netscape Navigator 3) aktiviert ist oder nicht; nur Netscape Navigator 3, danach entfernt.

25.19.2 Eigenschaften

appCodeName

Codename des Browsers (z. B. "Mozilla").

appName

Der Name des Browsers (z. B. "Netscape").

appVersion

Versionsinformation des Browsers.

language

JS 1.2

Angabe der Sprachversion des Browsers; JavaScript 1.2, nur Netscape.

mimeTypes

Array mit allen vom Browser unterstützten MIME-Typen.

platform

Plattforminformationen über den Browser (z. B. Win32).

plugins

Array mit allen im Browser installierten Plugins.

userAgent

Browser-Identifikator, der im HTTP-Header mitgesandt wird (Umgebungsvariable USER_AGENT).

25.20 Das Number-Objekt

JS 1.1

Ab JavaScript 1.1

Das Objekt gestattet den Zugriff auf nummerische Variablen und Funktionen.

25.20.1 Allgemeines

new Number(Wert)

Wert – Nummerischer Wert für die Objektinstanz.

25.20.2 Eigenschaften

MAX_VALUE

Die größte von JavaScript darstellbare Zahl.

document.write(Number.MAX_VALUE)

MIN_VALUE

Die kleinste positive von JavaScript darstellbare Zahl.

document.write(Number.MIN_VALUE)

NaN

Spezialwert »Not A Number«.

NEGATIVE_INFINITY

Ausdruck für »Minus unendlich«.

POSITIVE_INFINITY

Ausdruck für »Plus unendlich«.

25.21 Das Object-Objekt

JS 1.0

Ab JavaScript 1.0

Das Object-Objekt ist das primitive Basisobjekt aller hier vorgestellten Objekte. Die Methoden und Eigenschaften dieses Objekts stehen auch bei fast allen anderen hier vorgestellten Objekten zur Verfügung. Mit Ausnahme von toString() werden diese Eigenschaften und Methoden im Praxiseinsatz kaum verwendet und tauchen daher bei den anderen Objekten nicht auf.

25.21.1 Allgemeines

new Object()

25.21.2 Methoden

JS 1.1

eval

Wertet JavaScript-Code im Kontext des angegebenen Objekts aus; ab JavaScript 1.1.

eval(Code)

Code – Der JavaScript-Code.

toSource

JS 1.3

Gibt den Quellcode des Objekts zurück; ab JavaScript 1.3.

toString

Gibt eine Zeichenketten-Repräsentation des Objekts zurück.

unwatch

JS 1.2

Entfernt einen Überwachungspunkt von einer Objekteigenschaft, nützlich beim Debuggen eines Skripts; ab JavaScript 1.2.

unwatch(Eigenschaft)

Eigenschaft – Überwachte Eigenschaft.

valueOf

JS 1.1

Primitiver Wert des Objekts, wird vom JavaScript-Interpreter intern verwendet; ab JavaScript 1.1.

watch

JS 1.2

Überwacht eine Objekteigenschaft und ruft bei Änderung der Eigenschaft eine Funktion auf; ab JavaScript 1.2.

watch(Eigenschaft, Funktion)

Eigenschaft – Zu überwachende Eigenschaft.

Funktion – Bei Änderung aufzurufende Funktion.

25.21.3 Eigenschaften

constructor

Referenz auf die Funktion, die den Prototyp einer Funktion erzeugt.

prototype

JS 1.2

Prototyp des Objekts, kann zum Hinzufügen von Eigenschaften oder Methoden verwendet werden; ab JavaScript 1.2.

25.22 Das Option-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird eine Option in einer Auswahlliste eines HTML-Formulars in JavaScript dargestellt.

25.22.1 Allgemeines

HTML-Tag: <OPTION VALUE="Wert">Text</OPTION>

document.forms[Index].elements[index].options[Index]

Index – Index im jeweiligen Array.

25.22.2 Eigenschaften

defaultSelected

JS 1.1

Boolescher Wert, der angibt, ob die Option vom HTML-Code her standardmäßig ausgewählt ist oder nicht; ab JavaScript 1.1.

index

Der Index im options-Array.

length

Anzahl der Optionen.

selected

Boolescher Wert, der angibt, ob die Option ausgewählt ist oder nicht.

text

Text einer Option; kann ab JavaScript 1.1 geändert werden.

value

VALUE-Attribut der Option.

25.23 Das Password-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein Passwortfeld in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.23.1 Allgemeines

HTML-Tag: <INPUT TYPE="PASSWORD">

document.forms[Index].elements[index]
document.FormularName.PasswortfeldName

Index – Index im jeweiligen Array.

PasswortfeldName – NAME-Attribut des Passwortfelds.

25.23.2 Event-Handler

onBlur (JS1.1)
onFocus (JS1.1)

25.23.3 Methoden

blur

Entfernt den Fokus von dem Passwortfeld.

focus

Gibt dem Passwortfeld den Fokus.

select

Wählt das Passwortfeld aus.

25.23.4 Eigenschaften

defaultValue

VALUE-Attribut des Passwortfelds.

form

Referenz auf das Formular, das das Passwortfeld enthält.

name

NAME-Attribut des Passwortfelds.

type

JS 1.1

Zeichenkette mit dem Wert "password"; ab JavaScript 1.1.

value

Aktueller Wert (Text) im Passwortfeld.

25.24 Das Plugin-Objekt

JS 1.1

Ab JavaScript 1.1, nur Netscape

Array, das alle im Browser installierten Plugins enthält; Eigenschaft des navigator-Objekts.

25.24.1 Eigenschaften

description

Beschreibung des Plugins.

filename

Dateiname des Plugins auf der Festplatte.

length

Anzahl der installierten Plugins.

name

Name des Plugins.

25.25 Das Radio-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein Radiobutton in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.25.1 Allgemeines

HTML-Tag: <INPUT TYPE="RADIO">

document.forms[Index].elements[index]
document.FormularName.RadioName

Index – Index im jeweiligen Array.

RadioName – NAME-Attribut des Radiobuttons.

25.25.2 Event-Handler

onBlur (JS1.1)
onClick
onFocus (JS1.1)

25.25.3 Methoden

blur

Entfernt den Fokus von dem Radiobutton.

click

Simuliert das Anklicken des Radiobuttons.

focus

Gibt dem Radiobutton den Fokus.

25.25.4 Eigenschaften

checked

Wert true, wenn der Radiobutton ausgewählt ist, ansonsten false.

defaultChecked

Wert true, wenn der Radiobutton HTML-mäßig angekreuzt ist (durch den Parameter CHECKED), ansonsten false.

form

Referenz auf das Formular, das den Radiobutton enthält.

name

NAME-Attribut der Gruppe aus Radiobuttons.

type

JS 1.1

Zeichenkette mit dem Wert "radio"; ab JavaScript 1.1.

value

VALUE-Attribut des Radiobuttons.

25.26 Das RegExp-Objekt

JS 1.2

Ab JavaScript 1.2 und Internet Explorer 4

Das Objekt gestattet den Zugriff auf reguläre Ausdrücke; siehe Kapitel »Formulare II«.

25.26.1 Allgemeines

new RegExp(Muster[, Parameter])
/muster/Parameter

Muster – Suchmuster

Parameter – Leere Zeichenkette, "i" (nicht zwischen Groß- und Kleinschreibung unterscheiden), "g" (globale Suche) oder "gi" ("g" und "i").

Weitere Informationen über die verschiedenen Sonderzeichen im Suchmuster finden Sie im Kapitel »Formulare II«.

25.26.2 Eigenschaften

global

Boolescher Wert, der angibt, ob die "g"-Option beim regulären Ausdruck gesetzt ist.

ignoreCase

Boolescher Wert, der angibt, ob die "i"-Option beim regulären Ausdruck gesetzt ist.

input

Die Zeichenkette, die auf das Muster überprüft wird. Ist diese (statische) Eigenschaft gesetzt und wird bei exec() oder text() kein Eingabestring übergeben, so wird diese Eigenschaft verwendet.

RegExp.input = "Galileo Press"

lastIndex ($_)

Startposition für die nächsten Suchoperationen in der Zeichenkette.

lastMatch ($&)

Der letzte Treffer.

lastParen ($+)

Der letzte Treffer innerhalb runder Klammern.

leftContext ($’)

Zeichenkette links vom gefundenen Muster.

multiline ($*)

Boolescher Wert, der angibt, ob die Suche nicht bei einem Zeilensprung Halt macht.

rightContext ($’)

Zeichenkette rechts vom gefundenen Muster.

source

Suchmuster.

25.26.3 Methoden

compile

Kompiliert ein RegExp-Objekt während der Skriptausführung um; lohnt sich bei wiederholter Verwendung.

compile(Muster[, Parameter])

Muster – Suchmuster.

Parameter – "", "g", "i" oder "gi".

exec

Durchsucht eine Zeichenkette nach einem Muster und gibt die Ergebnisse in einem Array zurück.

exec(Zeichenkette)

Zeichenkette – Zu durchsuchende Zeichenkette.

test

Boolescher Wert, der angibt, ob das Muster in der als Parameter übergebenen Zeichenkette vorkommt.

test(Zeichenkette)

Zeichenkette – Zu durchsuchende Zeichenkette.

25.27 Das Reset-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird eine Zurücksetzen-Schaltfläche in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.27.1 Allgemeines

HTML-Tag: <INPUT TYPE="RESET">

document.forms[Index].elements[index]
document.FormularName.ResetName

Index – Index im jeweiligen Array.

ResetName – NAME-Attribut der Zurücksetzen-Schaltfläche.

25.27.2 Event-Handler

onBlur (JS1.1)
onFocus (JS1.1)
onClick

25.27.3 Methoden

blur

JS 1.1

Entfernt den Fokus von der Zurücksetzen-Schaltfläche; ab JavaScript 1.1.

click

Simuliert das Anklicken der Zurücksetzen-Schaltfläche.

focus

JS 1.1

Gibt der Zurücksetzen-Schaltfläche den Fokus; ab JavaScript 1.1.

25.27.4 Eigenschaften

form

Referenz auf das Formular, das die Zurücksetzen-Schaltfläche enthält.

name

NAME-Attribut der Zurücksetzen-Schaltfläche.

type

JS 1.1

Zeichenkette mit dem Wert "reset"; ab JavaScript 1.1.

value

VALUE-Attribut der Zurücksetzen-Schaltfläche; wenn es nicht gesetzt ist, ist der Wert "Reset".

25.28 Das Screen-Objekt

JS 1.2

Ab JavaScript 1.2

Das Objekt gestattet den Zugriff auf die Bildschirmmaße.

25.28.1 Eigenschaften

availHeight

Die zur Verfügung stehende Höhe des Bildschirms (also ohne Taskleiste von Windows oder KDE).

availLeft

Die x-Koordinate des sich am weitesten links befindlichen verfügbaren Bildschirmpunktes (ist nicht 0, wenn beispielsweise Office-Leiste links).

availTop

Die y-Koordinate des sich am weitesten oben befindlichen verfügbaren Bildschirmpunktes (ist nicht 0, wenn beispielsweise Task-Leiste oben).

availWidth

Die zur Verfügung stehende Breite des Bildschirms (also ohne Office-Leiste etc.).

colorDepth

Die Farbtiefe der verwendeten Palette (sofern vorhanden; ansonsten des Systems) in Bit. Ein Wert von 8 entspricht 28  = 256 Farben.

height

Höhe des Bildschirms in Pixeln.

pixelDepth

Die Farbtiefe des Systems in Bit. Ein Wert von 8 entspricht 28  = 256 Farben.

width

Breite des Bildschirms in Pixeln.

25.29 Das Select-Objekt

JS 1.0/1.1

Ab JavaScript 1.0; ab JavaScript 1.1 kann man einzelne Optionen hinzufügen und entfernen.

Hiermit wird eine Auswahlliste in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.29.1 Allgemeines

HTML-Tag: <SELECT>

document.forms[Index].elements[index]
document.FormularName.SelectName

Index – Index im jeweiligen Array.

SelectName – NAME-Attribut der Auswahlliste.

25.29.2 Event-Handler

onBlur (JS1.1)
onChange
onFocus (JS1.1)

25.29.3 Methoden

blur

Entfernt den Fokus von der Auswahlliste.

focus

Gibt der Auswahlliste den Fokus.

25.29.4 Eigenschaften

form

Referenz auf das Formular, das die Auswahlliste enthält.

length

Anzahl der Optionen in der Auswahlliste.

name

NAME-Attribut der Auswahlliste.

options

Ein Array, das die Optionen der Auswahlliste enthält (siehe Option-Objekt).

selectedIndex

Index der gerade ausgewählten Option (Zählung beginnt bei 0); bei mehreren ausgewählten Optionen (<SELECT MULTIPLE>) der Index der Ersten. Sollte keine Option ausgewählt sein, hat die Eigenschaft den Wert -1.

type

JS 1.1

Zeichenkette mit dem Wert "select-multiple" oder "select-one", je nachdem, ob der HTML-Parameter MULTIPLE gesetzt ist oder nicht; ab JavaScript 1.1.

25.30 Das String-Objekt

JS 1.0/1.1

Ab JavaScript 1.0 (durch Anführungszeichen); als instanziierbares Objekt ab JavaScript 1.1.

25.30.1 Allgemeines

new String(Zeichenkette)

Zeichenkette – Wert des Strings.

25.30.2 Methoden

anchor

Erzeugt den HTML-Code für eine Textmarke mit dem angegebenen Namen.

anchor(Name)

Name – Name der Textmarke.

var anch = "Textmarke".anchor("TM")
//anch hat nun den Wert <A NAME="TM">Textmarke</A>

big

Erzeugt den HTML-Code für fett gedruckten Text.

var bigtext = "Fett".big()
//bigtext hat nun den Wert <BIG>Fett</BIG>

blink

Erzeugt den HTML-Code für blinkenden Text; nur Netscape.

var blinktext = "Blink".blink()
//blinktext hat nun den Wert <BLINK>Blink</BLINK>

bold

Erzeugt den HTML-Code für fett gedruckten Text.

var boldtext = "Fett".bold()
//boldtext hat nun den Wert <B>Fett</B>

charAt

Gibt das Zeichen an der angegebenen Stelle zurück.

charAt(Position)

Position – Position des gewünschten Zeichens; Zählung beginnt bei 0.

charCodeAt

Gibt den Zeichencode des Zeichens an der ersten (oder der angegebenen) Stelle zurück.

charCodeAt([Position])

Position – Position des gewünschten Zeichens; falls nicht angegeben, wird das erste Zeichen genommen.

concat

An den String werden zwei oder mehr Zeichenketten angehängt.

concat(String1, String2[, String3, ..., StringN])

String1, ..., StringN – Zeichenketten.

var King = "I".concat(" have", " a", " dream")
 //King hat nun den Wert "I have a dream"

fixed

Erzeugt den HTML-Code für nichtproportionalen Text.

var fixtext = "Fixed".fixed()
//fixtext hat nun den Wert <TT>Fixed</TT>

fontcolor

Erzeugt den HTML-Code für farbigen Text.

fontcolor(Farbe)

Farbe – Textfarbe als Farbname oder hexadezimaler RGB-Wert.

var colortext = "Rot".fontcolor("red")
//boldtext hat nun den Wert <FONT COLOR="red">Rot</FONT>

fontsize

Erzeugt den HTML-Code für Text in einer bestimmten Schriftgröße.

fontsize(Größe)

Größe – Schriftgröße als Wert von 1 bis 7.

var sizetext = "Größe 3".fontsize(3)
//sizetext hat nun den Wert <FONT SIZE=3>Größe 3</FONT>

fromCharCode

JS 1.2

Erzeugt eine Zeichenkette, die Zeichencodes der einzelnen Zeichen werden als Parameter übergeben; ab JavaScript 1.2.

fromCharCode(Code1, ..., codeN)

Code1, ..., CodeN – Unicode-Wert der einzelnen Zeichen.

indexOf

Gibt die erste Position in der Zeichenkette zurück, ab der eine andere Zeichenkette vorkommt.

indexOf(Teilstring[, Start])

Teilstring – Die zu suchende Zeichenkette.

Start – Position, ab der gesucht wird.

Die Zählung beginnt bei 0; ist die Zeichenkette nicht vorhanden, so gibt die Methode -1 zurück.

italics

Erzeugt den HTML-Code für kursiven Text.

var italtext = "Kursiv".italics()
//italtext hat nun den Wert <I>Kursiv</I>

lastIndexOf

Gibt die letzte Position in der Zeichenkette zurück, ab der eine andere Zeichenkette vorkommt.

lastIndexOf(Teilstring[, Start])

Teilstring – Die zu suchende Zeichenkette.

Start – Position, ab der gesucht wird (von hinten).

Ist die Zeichenkette nicht vorhanden, so gibt die Methode -1 zurück.

link

Erzeugt den HTML-Code für einen Hyperlink.

link(URL)

URL – Ziel-URL des Links.

var galileo = "Galileo Press".link("http://www.galileo-press.de")
//galileo hat nun den Wert
<A HREF="http://www.galileo-press.de">Galileo</A>

match

JS 1.2

Eine Zeichenkette wird auf ein Muster durchsucht, und die Ergebnisse werden als Array zurückgegeben; ab JavaScript 1.2 und Internet Explorer 4.

match(RegExp)

RegExp – Regulärer Ausdruck.

replace

JS 1.2

Eine Zeichenkette wird auf ein Muster durchsucht, und dieses wird durch eine andere Zeichenkette ersetzt; ab JavaScript 1.2: Netscape Navigator 4.0 und Internet Explorer 5.5.

split(RegExp[, Ersatz])

RegExp – Regulärer Ausdruck.

Ersatz – Zeichenkette, die die gefundenen Muster ersetzt, oder Verarbeitungsfunktion.

search

JS 1.2

Diese Methode durchsucht eine Zeichenkette nach einem Muster und gibt als Boolesche Variable zurück, ob sie fündig geworden ist; ab JavaScript 1.2 und Internet Explorer 4.

search(RegExp)

RegExp – Regulärer Ausdruck.

slice

Entfernt eine Zeichenkette aus einer anderen Zeichenkette.

slice(Start[, Ende])

Start – Index des ersten Zeichens, das entfernt werden soll.

Ende – Erstes Zeichen, das nicht mehr entfernt werden soll; falls nicht angegeben, wird der gesamte Rest der Zeichenkette entfernt.

Die Funktion entfernt die Zeichen aus dem Originalstring und gibt die entfernten Zeichen zurück.

small

Erzeugt den HTML-Code für klein gedruckten Text.

var smalltext = "Klein".small()
//smalltext hat nun den Wert <SMALL>Klein</SMALL>

split

JS 1.2

Teilt eine Zeichenkette anhand eines Trennzeichens in einzelne Zeichenketten auf, die in einem Array zurückgegeben werden; ab JavaScript 1.2 und Internet Explorer 4.

split([Trennzeichen, Limit])

Trennzeichen – Trennzeichen, das die einzelnen Stücke voneinander trennt; wenn nicht angegeben, wird die Zeichenkette nicht aufgeteilt.

Limit – Maximale Anzahl der Einzelstücke; wenn nicht angegeben, dann unbegrenzt.

strike

Erzeugt den HTML-Code für durchgestrichenen Text.

var striketext = "Durch".strike()
//striketext hat nun den Wert <STRIKE>Durch</STRIKE>

sub

Erzeugt den HTML-Code für tiefgestellten Text.

var subtext = "Tief".sub()
//subtext hat nun den Wert <SUB>Tief</SUB>

substr

JS 1.2

Gibt eine Teilzeichenkette zurück, ohne (im Gegensatz zu slice()) die Originalzeichenkette zu verändern; ab JavaScript 1.2.

substring(Start, Länge)

Start – Position des ersten Zeichens der Teilzeichenkette.

Länge – Länge der Teilzeichenkette.

var gp = "Galileo".substring(2, 3)
//gp hat nun den Wert "lil"

substring

Gibt eine Teilzeichenkette zurück, ohne (im Gegensatz zu slice()) die Originalzeichenkette zu verändern.

substring(Start, Ende)

Start – Position des ersten Zeichens der Teilzeichenkette.

Ende – Position des ersten Zeichens, das nicht mehr zur Teilzeichenkette gehört.

var gp = "Galileo".substring(2, 5)
//gp hat nun den Wert "lil"

sup

Erzeugt den HTML-Code für hochgestellten Text.

var subtext = "Hoch".sup()
//subtext hat nun den Wert <SUP>Hoch</SUP>

toLowerCase()

Wandelt eine Zeichenkette in Kleinbuchstaben um.

toUpperCase()

Wandelt eine Zeichenkette in Großbuchstaben um.

25.30.3 Eigenschaften

length

Anzahl der Zeichen im String.

25.31 Das Submit-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird eine Versende-Schaltfläche in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.31.1 Allgemeines

HTML-Tag: <INPUT TYPE="SUBMIT">

document.forms[Index].elements[index]
document.FormularName.SubmitName

Index – Index im jeweiligen Array.

SubmitName – NAME-Attribut der Versende-Schaltfläche.

25.31.2 Event-Handler

onBlur (JS1.1)
onClick
onFocus (JS1.1)

25.31.3 Methoden

blur

JS 1.1

Entfernt den Fokus von der Versende-Schaltfläche; ab JavaScript 1.1.

click

Simuliert das Anklicken der Versende-Schaltfläche.

focus

JS 1.1

Gibt der Versende-Schaltfläche den Fokus; ab JavaScript 1.1.

25.31.4 Eigenschaften

form

Referenz auf das Formular, das die Versende-Schaltfläche enthält.

name

NAME-Attribut der Versende-Schaltfläche.

type

JS 1.1

Zeichenkette mit dem Wert "submit"; ab JavaScript 1.1.

value

VALUE-Attribut der Versende-Schaltfläche; wenn es nicht gesetzt ist, ist der Wert "Submit Query".

25.32 Das Text-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein Textfeld in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.32.1 Allgemeines

HTML-Tag: <INPUT TYPE="PASSWORD">

document.forms[Index].elements[index]
document.FormularName.TextName

Index – Index im jeweiligen Array.

TextName – NAME-Attribut des Textfeldes.

25.32.2 Event-Handler

onBlur (JS1.1)
onChange (JS1.1)
onFocus (JS1.1)
onKeyDown (JS1.2/IE4)
onKeyPress (JS1.2/IE4)
onKeyUp (JS1.2/IE4)
onSelect (JS1.1)

25.32.3 Methoden

blur

Entfernt den Fokus von dem Eingabefeld.

focus

Gibt dem Eingabefeld den Fokus.

select

Wählt den Text im Eingabefeld aus.

25.32.4 Eigenschaften

defaultValue

VALUE-Attribut des Eingabefelds.

form

Referenz auf das Formular, das das Eingabefeld enthält.

name

NAME-Attribut des Eingabefelds.

type

JS 1.1

Zeichenkette mit dem Wert "text"; ab JavaScript 1.1.

value

Aktueller Wert (Text) im Eingabefeld.

25.33 Das Textarea-Objekt

JS 1.0

Ab JavaScript 1.0

Hiermit wird ein mehrzeiliges Textfeld in einem Formular in JavaScript abgebildet; das Objekt ist ein Element des Form-Objekts.

25.33.1 Allgemeines

HTML-Tag: <INPUT TYPE="PASSWORD">

document.forms[Index].elements[index]
document.FormularName.TextName

Index – Index im jeweiligen Array.

TextName – NAME-Attribut des Textfeldes.

25.33.2 Event-Handler

onBlur (JS1.1)
onChange (JS1.1)
onFocus (JS1.1)
onKeyDown (JS1.2/IE4)
onKeyPress (JS1.2/IE4)
onKeyUp (JS1.2/IE4)
onSelect (JS1.1)

25.33.3 Methoden

blur

Entfernt den Fokus von dem Textfeld.

focus

Gibt dem Textfeld den Fokus.

select

Wählt den Text im Textfeld aus.

25.33.4 Eigenschaften

defaultValue

VALUE-Attribut des Textfelds.

form

Referenz auf das Formular, das das Textfeld enthält.

name

NAME-Attribut des Textfelds.

type

JS 1.1

Zeichenkette mit dem Wert "textarea"; ab JavaScript 1.1.

value

Aktueller Wert (Text) im Textfeld.

25.34 Das Window-Objekt

JS 1.0

Ab JavaScript 1.0.

Hiermit werden Fenster (oder auch Frames; dann Frames-Objekt) in JavaScript abgebildet. Das window-Objekt steht an oberster Stelle in der Objekt-Hierarchie.

25.34.1 Allgemeines

HTML-Tag: <BODY> oder <FRAME>

25.34.2 Event-Handler

onBlur (JS1.1)
onDragDrop (JS1.2/IE4)
onError (JS1.1)
onFocus (JS1.1)
onLoad
onMove (JS1.2/IE4)
onResize (JS1.2/IE4)
onUnload

25.34.3 Methoden

alert

Gibt ein modales Warnfenster aus.

alert(Nachricht)

Nachricht – Text im Warnfenster.

back

JS 1.2

Lädt die Seite, die in der History des aktuellen Fensters vor der aktuellen Seite kommt; ab JavaScript 1.2/IE5.

blur

JS 1.1

Nimmt den Fokus vom aktuellen Fenster; ab JavaScript 1.1.

captureEvents

JS 1.2

Alle angegebenen Ereignisse werden abgefangen, siehe Kapitel »Events«; ab JavaScript 1.2, nur Netscape.

captureEvents(Ereignis1 | Ereignis2 | ... | EreignisN)

Ereignis1, Ereignis2, ..., EreignisN – Ereignisse, z. B. Event.MOUSEUP.

clearInterval

JS 1.2

Löscht einen mit setInterval() gesetzten Timeout; ab JavaScript 1.2.

clearInterval(ID)

ID – von setInterval() zurückgegebene ID.

clearTimeout

Löscht einen mit setTimeout() gesetzten Timeout.

clearTimeout(ID)

ID – von setTimeout() zurückgegebene ID.

close

Schließt das Fenster. Wenn es nicht mit JavaScript geöffnet worden ist, erscheint zuvor aus Sicherheitsgründen eine Warnmeldung für den Benutzer.

confirm

Gibt ein modales Hinweisfenster mit zwei Schaltflächen (OK und Abbrechen) aus. Klickt der Benutzer auf OK, wird true zurückgegeben, ansonsten false.

confirm(Nachricht)

Nachricht – Text im Hinweisfenster.

back

JS 1.2

Lädt die Seite, die in der History des aktuellen Fensters vor der aktuellen Seite kommt; ab JavaScript 1.2/IE5.

disableExternalCapture

JS 1.2

Deaktiviert ein vorhergehendes enableExternalCapture(); ab JavaScript 1.2, nur Netscape.

enableExternalCapture

JS 1.2

Gestattet es einem Skript in einem anderen Frame, Ereignisse in diesem Fenster/Frame abzufangen, obwohl es auf einem anderen Server liegt; benötigt UniversalBrowserWrite; ab JavaScript 1.2, nur Netscape.

find

Sucht eine Zeichenkette im aktuellen Browser-Fenster; ab JavaScript 1.2/IE5.

find([Zeichenkette[, grossklein, rückwärts]])

Zeichenkette – Die zu suchende Zeichenkette.

grossklein – Boolescher Wert, der angibt, ob zwischen Groß- und Kleinschreibung unterschieden werden soll (true) oder nicht (false).

rückwärts – wenn true, dann wird vom Ende des Dokuments aus gesucht.

Wenn die Zeichenkette gefunden wird, gibt die Funktion true zurück, ansonsten false. Wird keine Zeichenkette angegeben, wird das Suchen-Dialogfenster des Browsers aufgerufen.

focus

JS 1.1

Gibt dem aktuellen Fenster den Fokus; ab JavaScript 1.1.

forward

JS 1.2

Lädt die Seite, die in der History des aktuellen Fensters nach der aktuellen Seite kommt; ab JavaScript 1.2/IE5.

handleEvent

JS 1.2

Ruft den Event-Handler für ein bestimmtes Ereignis auf; ab JavaScript 1.2, nur Netscape.

handleEvent(Ereignis)

Ereignis – Ereignisobjekt.

home

JS 1.2

Lädt die im Browser eingestellte Startseite; ab JavaScript 1.2/IE5.

moveBy

JS 1.2

Verschiebt ein Fenster horizontal und vertikal; ab JavaScript 1.2.

moveBy(hDelta, vDelta)

hDelta – Relative horizontale Verschiebung.

vDelta – Relative vertikale Verschiebung.

moveTo

JS 1.2

Verschiebt ein Fenster an die angegebene Bildschirmposition; ab JavaScript 1.2.

moveTo(x, y)

x – Neue x-Koordinate der linken oberen Ecke des Fensters.

y – Neue y-Koordinate der linken oberen Ecke des Fensters.

open

Öffnet ein neues Fenster.

open(URL[, Fenstername[, Optionen]])

URL – Die URL des neuen Fensters oder "", wenn leeres Dokument.

Fenstername – name-Eigenschaft des neuen Fensters, dient auch als TARGET-Attribut für Hyperlinks.

Optionen – Eigenschaften für das neue Fenster, die im Format "Eigenschaft1=yes,Eigenschaft2=Wert,Eigenschaft3=no" angegeben werden. Nicht genannte Eigenschaften sind in der Regel auf no gesetzt. Äquivalent zu yes ist 1, äquivalent zu no ist 0.

Tabelle 25.3  Eigenschaften für neue Fenster

Option	Boolesch/ Nummerisch	JavaScript-Version, Signiertes Skript	Beschreibung
alwaysLowered	B	1.2/SS (nur Netscape)	Fenster liegt immer hinter anderen offenen Fenstern.
alwaysRaised	B	1.2/SS (nur Netscape)	Fenster liegt immer über anderen offenen Fenstern.
channelmode	B	1.2 (nur Internet Explorer)	Channel-Leiste
dependent	B	1.2 (nur Netscape)	Das neue Fenster ist vom öffnenden Fenster abhängig; wird das öffnende Fenster geschlossen, schließt sich auch das neue Fenster.
directories	B	1.0	Directory-Leiste (What’s New etc.)
fullscrean	B	1.2 (nur Internet Explorer)	Vollbild (Browser maximiert)
height	N	1.0	Höhe des Fensters
hotkeys	B	1.2 (nur Netscape)	Falls no oder 0, werden Tastenkürzel (außer Beenden) im neuen Fenster deaktiviert.
innerHeight	N	1.2 (nur Netscape)	Höhe des verfügbaren Bereichs
innerWidth	N	1.2 (nur Netscape)	Breite des verfügbaren Bereichs
left	N	1.2 (nur Internet Explorer)	x-Koordinate der linken oberen Ecke
location	B	1.0	Adressleiste
menubar	B	1.0	Menüleiste
outerHeight	N	1.2 (nur Netscape)	Höhe des Fensters (Nachfolger von height)
outerWidth	N	1.2 (nur Netscape)	Breite des Fensters (Nachfolger von width)
personalbar	B	1.2 (nur Netscape)	»Personal Toolbar«
resizable	B	1.0	Fenster in der Größe nicht veränderbar, falls no oder 0
screenX	N	1.2 (nur Netscape)	x-Koordinate der linken oberen Ecke
screenY	N	1.2 (nur Netscape)	y-Koordinate der linken oberen Ecke
scrollbars	B	1.0	Scrolleisten
status	B	1.0	Statuszeile
titlebar	B	1.0	Titelleiste
toolbar	B	1.0	Werkzeugleiste
top	N	1.2 (nur Internet Explorer)	y-Koordinate der linken oberen Ecke
width	N	1.0	Breite des Fensters
z-lock	B	1.2/SS (nur Netscape)	Fenster liegt über anderen Fenstern.

Die Methode gibt eine Referenz auf das neue Fenster zurück.

print

JS 1.2

Ruft den Druck-Dialog des Browsers für den aktuellen Frame bzw. das aktuelle Fenster auf; ab JavaScript 1.2/IE5.

prompt

Zeigt ein Eingabefenster an; der Benutzer kann einen Text eingeben, der dann von der Funktion zurückgegeben wird.

prompt(Nachricht)

Nachricht – Hinweistext im Eingabefenster. Wird dieser nicht angegeben, erscheint "<undefined>".

releaseEvents

JS 1.2

Deaktiviert ein vorhergehendes captureEvents(); ab JavaScript 1.2, nur Netscape.

releaseEvents(Ereignis1 | Ereignis2 | ... | EreignisN)

Ereignis1, Ereignis2, ..., EreignisN – Ereignisse, z. B. Event.MOUSEUP.

resizeBy

JS 1.2

Verändert die Ausmaße eines Fensters um einen gewissen Wert, wobei die linke obere Ecke fix bleibt; ab JavaScript 1.2.

resizeBy(hDelta, vDelta)

hDelta – Relative horizontale Veränderung in Pixeln.

vDelta – Relative vertikale Veränderung in Pixeln.

Ohne ein signiertes Skript ist die minimale Fenstergröße 100 x 100 Pixel.

resizeTo

JS 1.2

Verändert die Ausmaße eines Fensters auf einen gewissen Wert, wobei die linke obere Ecke fix bleibt; ab JavaScript 1.2.

moveTo(Breite, Höhe)

Breite – Neue Breite des Fensters.

Höhe – Neue Höhe des Fensters.

Ohne ein signiertes Skript ist die minimale Fenstergröße 100 x 100 Pixel.

routeEvent

JS 1.2

Führt ein abgefangenes Ereignis dort aus, wofür es bestimmt war; ab JavaScript 1.2, nur Netscape.

routeEvent(Ereignis)

Ereignis – Ereignisobjekt.

scroll

JS 1.1

Scrollt den Inhalt des Fensters bzw. Frames an die angegebene Position; ab JavaScript 1.1.

scroll(x, y)

x – x-Koordinate der Stelle im Dokument, die sich nach dem Scrollen in der linken oberen Ecke des Fensters befinden soll.

y – y-Koordinate der Stelle im Dokument, die sich nach dem Scrollen in der linken oberen Ecke des Fensters befinden soll.

scrollBy

JS 1.2

Scrollt den Fensterinhalt um einen gewissen Wert; ab JavaScript 1.2.

scrollBy(hDelta, vDelta)

hDelta – Relative horizontale Veränderung in Pixeln.

vDelta – Relative vertikale Veränderung in Pixeln.

scrollTo

JS 1.2

Scrollt den Inhalt des Fensters bzw. Frames an die angegebene Position; ab JavaScript 1.2.

scrollTo(x, y)

x – x-Koordinate der Stelle im Dokument, die sich nach dem Scrollen in der linken oberen Ecke des Fensters befinden soll.

y – y-Koordinate der Stelle im Dokument, die sich nach dem Scrollen in der linken oberen Ecke des Fensters befinden soll.

Die Funktionsweise von scrollTo() ist identisch mit der von scroll().

setHotKeys

JS 1.2

Schaltet Tastenkürzel in einem Fenster ohne Menü ein oder aus; ab JavaScript 1.2, nur Netscape.

setHotKeys(anaus)

anaus – true=an, false=aus.

setInterval

JS 1.2

Führt eine Anweisung periodisch aus; ab JavaScript 1.2 und Internet Explorer 4.

setInterval(Anweisung, Zeitspanne[, Argument1, ..., ArgumentN])

Anweisung – Die Anweisung(en), die ausgeführt werden soll(en).

Zeitspanne – Zeitspanne in Millisekunden, die zwischen den Ausführungen der Anweisung verstreichen soll.

Argument1, ..., ArgumentN – Sofern als Anweisung eine Referenz auf eine Funktion übergeben wird (also der Name, nicht in Anführungszeichen, ohne Klammern), die Argumente, die an die Funktion übergeben werden.

Die Methode liefert einen Identifier zurück, der mit clearTimeout() zum Löschen des Timeouts verwendet werden kann; ansonsten werden die Anweisungen beliebig oft ausgeführt.

setTimeout

Führt eine Anweisung einmal, nach Ablauf einer gewissen Zeitspanne, aus.

setTimeout(Anweisung, Zeitspanne[, Argument1, ..., ArgumentN])

Anweisung – Die Anweisung(en), die ausgeführt werden soll(en).

Zeitspanne – Zeitspanne in Millisekunden.

Argument1, ..., ArgumentN – Sofern als Anweisung eine Referenz auf eine Funktion übergeben wird (also der Name, nicht in Anführungszeichen, ohne Klammern), die Argumente, die an die Funktion übergeben werden.

Die Methode liefert einen Identifier zurück, der mit clearTimeout() zum Löschen des Timeouts verwendet werden kann.

setResizable

JS 1.2

Schaltet die Vergrößerungs- und Verkleinerungsfähigkeit eines Fensters ein oder aus; ab JavaScript 1.2/IE5.

setResizable(anaus)

anaus – true=an, false=aus.

stop

JS 1.2

Bricht das Laden des Fensterinhaltes ab wie die Stop-Schaltfläche in der Werkzeugleiste des Browsers; ab JavaScript 1.2/IE5.

setZOptions

JS 1.2

Mit dieser Option kann das Darstellungsverhalten eines Fensters in Bezug auf andere Fenster (im Vordergrund/im Hintergrund) eingestellt werden; ab JavaScript 1.2, nur Netscape.

setZOptions(Einstellung)

Einstellung – Zeichenkette mit dem Wert "alwaysLowered", "alwaysRaised" oder "z-lock".

showModalDialog

JS 1.3

Zeigt ein modales Fenster an (siehe auch Kapitel 10); ab JavaScript 1.3, nur Internet Explorer.

showModalDialog(URL[, Fenstername[, Optionen]])

URL – Die URL des neuen Fensters oder "", wenn leeres Dokument.

Fenstername – name-Eigenschaft des neuen Fensters, dient auch als TARGET-Attribut für Hyperlinks.

Optionen – Eigenschaften für das neue Fenster, die im Format "Eigenschaft1=yes,Eigenschaft2=Wert,Eigenschaft3=no" angegeben werden. Nicht genannte Eigenschaften sind in der Regel auf no gesetzt. Äquivalent zu yes ist 1, äquivalent zu no ist 0.

showModelessDialog

JS 1.3

Zeigt ein halb-modales Fenster an (ist immer im Vordergrund, aber auf das aufrufende Fenster kann zugegriffen werden); ab JavaScript 1.3, nur Internet Explorer.

showModelessDialog(URL[, Fenstername[, Optionen]])

URL – Die URL des neuen Fensters oder "", wenn leeres Dokument.

Fenstername – name-Eigenschaft des neuen Fensters, dient auch als TARGET-Attribut für Hyperlinks.

Optionen – Eigenschaften für das neue Fenster, die im Format "Eigenschaft1=yes,Eigenschaft2=Wert,Eigenschaft3=no" angegeben werden. Nicht genannte Eigenschaften sind in der Regel auf no gesetzt. Äquivalent zu yes ist 1, äquivalent zu no ist 0.

25.34.4 Eigenschaften

closed

JS 1.1

Boolesche Variable, die angibt, ob das Fenster (das zuvor mit window.open() geöffnet worden ist) geschlossen ist oder nicht; ab JavaScript 1.1.

defaultStatus

Standardtext in der Statuszeile, der angezeigt wird, wenn sich die Maus über keinem Link befindet.

document

Document-Objekt des aktuellen Fensters.

frames

Array, das Referenzen auf alle Frames im aktuellen Fenster enthält, sofern vorhanden.

history

History-Objekt des aktuellen Fensters.

innerHeight

JS 1.2

Höhe des zur Verfügung stehenden Bereichs des Browsers (also ohne Scrollbalken etc.); ab JavaScript 1.2.

innerWidth

JS 1.2

Breite des zur Verfügung stehenden Bereichs des Browsers (also ohne Titelleiste etc.); ab JavaScript 1.2.

length

Anzahl der Frames im aktuellen Fenster.

location

Location-Objekt des Fensters.

locationbar

JS 1.2

Objekt für die Adressleiste des Fensters; die Boolsche Eigenschaft visible gibt an, ob sie sichtbar ist oder nicht; ab JavaScript 1.2.

menubar

JS 1.2

Objekt für die Menüleiste des Fensters, die Boolsche Eigenschaft visible gibt an, ob sie sichtbar ist oder nicht; ab JavaScript 1.2.

name

Identifikator für das Fenster oder den Frame. Er kann unter anderem als Wert für das TARGET-Attribut eines Hyperlinks verwendet werden.

offscreenBuffering

JS 1.2

Boolescher Wert, der angibt, ob die Aktualisierungen des Fensterinhaltes in einem Speicherbuffer ausgeführt werden; falls ja, flackert der Bildschirmaufbau weniger, es werden aber mehr Ressourcen benötigt. Der Standardwert ist false; ab JavaScript 1.2.

opener

JS 1.1

Referenz auf das Fenster, welches das aktuelle Fenster via JavaScript geöffnet hat (sofern das der Fall war, ansonsten ist der Wert null); ab JavaScript 1.1 und Internet Explorer 3.

outerHeight

JS 1.2

Höhe des Browser-Fensters (also mit Scrollbalken etc.); ab JavaScript 1.2.

outerWidth

JS 1.2

Breite des Browser-Fensters (also mit Titelleiste etc.); ab JavaScript 1.2.

pageXOffset

JS 1.2

x-Koordinate des Punktes des aktuellen Dokuments, der sich in der linken oberen Ecke des Fensters befindet; ab JavaScript 1.2.

pageYOffset

JS 1.2

y-Koordinate des Punktes des aktuellen Dokuments, der sich in der linken oberen Ecke des Fensters befindet; ab JavaScript 1.2.

parent

Referenz auf das übergeordnete Fenster; ist ein Verweis auf das aktuelle Fenster, falls kein Frame.

personalbar

JS 1.2

Objekt für die »Personal Toolbar« des Fensters; die Boolesche Eigenschaft visible gibt an, ob sie sichtbar ist oder nicht; ab JavaScript 1.2.

screenLeft

JS 1.2

x-Koordinate der linken oberen Ecke des Fensters, relativ zum Bildschirm; ab JavaScript 1.2, nur Internet Explorer 5.

screenTop

JS 1.2

y-Koordinate der linken oberen Ecke des Fensters, relativ zum Bildschirm; ab JavaScript 1.2, nur Internet Explorer 5.

screenX

JS 1.2

x-Koordinate der linken oberen Ecke des Fensters, relativ zum Bildschirm; ab JavaScript 1.2, nur Netscape.

screenY

JS 1.2

y-Koordinate der linken oberen Ecke des Fensters, relativ zum Bildschirm; ab JavaScript 1.2, nur Netscape.

scrollbars

JS 1.2

Objekt für die Scrolleisten des Fensters; die Boolesche Eigenschaft visible gibt an, ob sie sichtbar sind oder nicht; ab JavaScript 1.2.

self

Referenz auf das aktuelle Fenster bzw. den aktuellen Frame.

status

Text in der Statuszeile. Im Gegensatz zu defaultStatus wird dieser Text nur so lange angezeigt, bis beispielsweise die Maus über einen Link fährt; Verläßt die Maus den Link wieder, wird wieder defaultStatus angezeigt.

statusbar

Objekt für die Statusleiste des Fensters; die Booelsche Eigenschaft visible gibt an, ob sie sichtbar ist oder nicht; ab JavaScript 1.2.

toolbar

Objekt für die Werkzeugleiste des Fensters; die Boolesche Eigenschaft visible gibt an, ob sie sichtbar ist oder nicht; ab JavaScript 1.2.

top

Referenz auf das oberste Fenster in der Frame-Hierarchie. Ist das aktuelle Fenster selbst das oberste Fenster, so zeigt diese Eigenschaft auf das Fenster selbst.

25.35 Top-Level-Eigenschaften und -Methoden

JS 1.0

Ab JavaScript 1.0

Diese Eigenschaften und Methoden stehen ohne Objekt zur Verfügung.

25.35.1 Methoden

escape

Wandelt eine Zeichenkette in ein URL-fähiges Format um, Sonderzeichen werden durch %XX ersetzt (XX=Hexadezimalcode).

eval

Interpretiert als Parameter übergebenen JavaScript-Code und liefert das Ergebnis zurück.

isFinite

JS 1.3

Ab JavaScript 1.3

Ermittelt, ob ein Wert gleich (nummerisch) Unendlich ist (beispielsweise als Ergebnis einer Division durch Null).

isNaN

JS 1.1

Ab JavaScript 1.1 (1.0 nur UNIX)

Ermittelt, ob ein Wert keine Zahl ist (not a number).

parseFloat

Wandelt eine Zeichenkette in eine Fließkommazahl um, liefert bei Mißerfolg NaN zurück.

parseInt

Wandelt eine Zeichenkette in eine ganze Zahl um, liefert bei Mißerfolg NaN zurück.

unescape

Wandelt eine Zeichenkette aus einem URL-fähiges Format wieder in die ursprüngliche Zeichenkette um.

25.35.2 Eigenschaften

Infinity

Unendlich.

NaN

Not a number.

undefined

Undefiniert.

<< zurück	<top>	vor >>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

Die Veröffentlichung der Inhalte oder Teilen davon bedarf der ausdrücklichen schriftlichen Genehmigung von Galileo Press. Falls Sie Interesse daran haben sollten, die Inhalte auf Ihrer Website oder einer CD anzubieten, melden Sie sich bitte bei: stefan.krumbiegel@galileo-press.de

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


JavaScript - Galileo Computing - OpenBook

" >
Inhalt

1 Einleitung

2 Vorbereitung

3 Programmierung I

4 Programmierung II

5 Erste Schritte

6 Fenster I

7 Formulare I

8 Fenster II: Frames

9 Images

10 Fenster III

11 Cookies

12 Formulare II

13 Arrays

14 Musik

15 Events

16 DHTML I: Netscape

17 DHTML II: Internet Explorer

18 DHTML III: Netscape 6

19 DHTML IV: Für alle Browser

20 Java

21 Signierte Skripten

22 DOM

23 Fehler

24 Lösungen

25 Referenz

Index

Download (ca. 2,4 MB)

<< zurück	<openbook>

JavaScript von Christian Wenz

Browserübergreifende Lösungen

		!	A	B	C	D	E	F	G	H	I	J	K	L	M	N	O	P	Q	R	S	T	U	V	W	Y	Z

Stichwortverzeichnis

!

! [1]

- [1]

-- [1]

!= [1]

% [1]

%= [1]

&& [1]

* [1]

*/ [1]

*= [1]

+ [1] , [2]

++ [1]

+= [1]

/ [1]

/* [1]

// [1]

/= [1]

-= [1]

= [1]

== [1]

| [1]

|| [1]

A

ActiveMovie Control [1]

– Methoden [1]

ActivePerl [1]

alert() – s. window-Objekt [1]

Animation [1]

appendChild() [1]

appName – s. navigator-Objekt [1]

appVersion – s. navigator-Objekt [1]

arguments – s. Funktionen [1]

Array-Objekt [1] , [2] , [3] , [4]

– für JavaScript 1.0 [1]

– Index [1]

– length [1] , [2]

– pop() [1]

– push() [1] , [2]

– sort() [1] , [2]

– splice() [1]

– toString() [1]

Arrays [1]

– sortieren [1]

– Sortierfunktion [1]

Auswahllisten [1] , [2]

– options [1]

– selected [1]

– selectedIndex [1] , [2]

– type [1]

– value [1]

B

back() [1] , [2]

BBEdit [1]

Blackjack [1]

blur() [1]

Bookmark [1]

Browser-Erkennung [1]

– Internet Explorer [1]

– Netscape Navigator [1]

– Versionsnummer [1]

BSI [1]

Bubblesort [1]

Bubbling [1] , [2]

Bugs [1]

C

Cache – s. Image-Objekt [1]

ceil() – s. Math-Objekt [1]

charAt() – s. String-Objekt [1]

Checkboxen [1]

– checked [1]

– type [1]

classes-Objekt [1]

clearInterval() – s. window-Objekt [1]

clearTimeout() – s. window-Objekt [1]

Client Sniffer [1]

clientseitige Programmierung [1]

cloneNode() [1]

confirm() – s. window-Objekt [1]

continue [1]

cookie – s. document-Objekt [1]

Cookies [1] , [2] , [3]

– domain [1]

– expires [1]

– lesen [1]

– löschen [1]

– path [1]

– secure [1]

– setzen [1]

– Unterstützung prüfen [1]

Copy & Paste [1]

createElement() [1]

CSS [1] , [2]

D

Date-Objekt [1]

– erzeugen [1]

– getDate() [1]

– getFullYear() [1]

– getHours() [1]

– getMilliseconds() [1]

– getMinutes() [1]

– getMonth() [1]

– getSeconds() [1]

– getTime() [1]

– getYear() [1] , [2]

– toGMTString() [1]

default – s. switch-Anweisung [1]

DHTML [1] , [2]

disablePrivilege() [1]

document-Objekt

– all [1] , [2]

– all.style [1]

– cookie [1] , [2]

– forms [1]

– getElementById [1] , [2]

– images [1] , [2]

– layers [1]

– style [1]

– write() [1] , [2] , [3] , [4]

DOM [1] , [2] , [3] , [4] , [5]

DOM-Baum [1]

do-while-Schleifen [1] , [2] , [3]

Drag&Drop [1] , [2] , [3] , [4] , [5]

Drucken [1]

E

ECMA-262 [1] , [2]

ECMAScript [1] , [2]

E-Commerce [1]

Eigenschaften – s. Objekte [1]

elements [1]

else – s. if-else-Anweisung [1]

enablePrivilege() [1] , [2]

encodeURI() [1]

encodeURIComponent() [1]

Entities [1]

Ereignisbehandlung [1]

Ereignisse [1]

– abfangen [1]

– browser-unabhängig [1]

– Bubbling [1]

– Internet Explorer [1]

– Mausklicks [1]

– Netscape [1]

– Sondertasten [1]

– Tastatureingaben [1] , [2]

escape() [1]

eval() [1] , [2] , [3] , [4] , [5] , [6]

Event-Handler [1] , [2] , [3]

– mouseup [1]

– onAbort [1]

– onBlur [1] , [2]

– onChange [1] , [2] , [3]

– onClick [1] , [2] , [3] , [4]

– onDblclick [1] , [2]

– onError [1] , [2]

– onFocus [1] , [2] , [3]

– onKeydown [1] , [2]

– onKeypress [1] , [2]

– onKeyup [1] , [2]

– onLoad [1] , [2] , [3]

– onMousedown [1] , [2] , [3]

– onMousemove [1] , [2]

– onMouseout [1] , [2] , [3]

– onMouseover [1] , [2] , [3]

– onMouseup [1] , [2]

– onSelect [1]

– onSubmit [1]

– onUnload [1]

Event-Objekt [1] , [2] , [3] , [4]

– cancelBubble [1]

– CLICK [1]

– clientX [1]

– clientY [1]

– keyCode [1]

– MOUSEDOWN [1]

– MOUSEUP [1]

– pageX [1]

– pageY [1]

– srcElement [1] , [2]

– target [1] , [2]

– type [1] , [2]

– which [1]

externe Datei [1]

F

FAQ [1]

Fehler

– abfangen [1]

– detaillierte Meldung [1]

Fehlersuche [1]

Fenster-Eigenschaften [1] , [2]

– center [1]

– dependent [1]

– dialogHeight [1]

– dialogLeft [1]

– dialogTop [1]

– dialogWidth [1]

– directories [1]

– height [1]

– help [1]

– innerHeight [1]

– innerWidth [1]

– left [1]

– menubar [1]

– outerHeight [1]

– outerWidth [1]

– resizeable [1]

– screenX [1] , [2]

– screenY [1] , [2]

– scrollbars [1]

– status [1] , [2]

– toolbar [1]

– top [1]

– width [1]

firstChild [1]

floor() – s. Math-Objekt [1]

for-in-Schleifen [1]

Form-Objekt

– elements [1] , [2]

Formularüberprüfung [1]

– automatisch [1]

for-Schleifen [1] , [2]

Frames [1] , [2]

– drucken [1]

– mehrere gleichzeitig ändern [1]

– mit JavaScript füllen [1]

Funktionen [1]

– Anzahl Parameter [1]

– arguments [1]

– Parameter [1]

– return [1]

G

Gauß [1]

Gecko [1] , [2]

getDate() – s. Date-Objekt [1]

getFullYear() – s. Date-Objekt [1]

getHours() – s. Date-Objekt [1]

getMilliseconds() – s. Date-Objekt [1]

getMinutes() – s. Date-Objekt [1]

getMonth() – s. Date-Objekt [1]

getSeconds() – s. Date-Objekt [1]

getYear() – s. Date-Objekt [1]

GIF

– animiert [1]

– transparent [1]

go() – s. history-Objekt [1]

H

hasChildNodes() [1]

history-Objekt [1]

– back() [1]

– forward() [1]

– go() [1] , [2]

HotJava [1] , [2]

href – s. location-Objekt [1]

HTML-Tags

– A HREF [1] , [2]

– A STYLE [1]

– A TARGET [1] , [2] , [3]

– APPLET [1]

– BGSOUND [1]

– BR [1]

– DIV [1] , [2] , [3] , [4]

– DIV STYLE [1] , [2]

– EMBED [1]

– EMBED AUTOSTART [1]

– EMBED NAME [1]

– EMBED SRC [1]

– FORM [1]

– FORM ACTION [1]

– FORM METHOD=GET [1]

– FORM NAME [1]

– FRAME [1]

– FRAME SRC [1]

– FRAMESET [1] , [2]

– FRAMESET COLS [1]

– FRAMESET ROWS [1]

– HR [1]

– IMG NAME [1] , [2]

– INPUT TYPE=CHECKBOX [1]

– INPUT TYPE=HIDDEN [1]

– INPUT TYPE=PASSWORD [1]

– INPUT TYPE=RADIO [1]

– INPUT TYPE=TEXT [1] , [2]

– LAYER [1] , [2]

– MARQUEE [1]

– NOFRAMES [1]

– NOSCRIPT [1]

– OPTION [1]

– SCRIPT [1]

– SCRIPT EVENT FOR [1]

– SCRIPT LANGUAGE [1] , [2] , [3] , [4]

– SCRIPT SRC [1] , [2] , [3]

– SELECT [1]

– SELECT MULTIPLE [1]

– STYLE [1] , [2]

– TEXTAREA [1]

HTTP [1]

HTTP-Header [1] , [2]

HTTPS [1]

I

ids-Objekt [1]

if-else-Anweisung [1]

Image-Objekt [1]

– Cache [1] , [2]

– complete [1]

– Kompatibilität [1]

– src [1] , [2]

indexOf() – s. String-Objekt [1]

insertBefore() [1]

isNaN() [1] , [2]

J

Jahr-2000-Problem [1]

Jahrtausendwechsel [1]

JAR [1]

Java [1] , [2]

– Datentypen [1]

– Klassen [1]

– Vector [1]

– Virtual Machine [1]

javaEnabled() – s. navigator-Objekt [1]

JavaScript 1.5 [1]

JavaScript Debugger [1]

– Abort [1]

– Breakpoint [1]

– Inspector [1]

– Installation [1]

– Into [1]

– Konsole [1]

– Out [1]

– Over [1]

– Run [1]

– Watch [1]

JavaScript-Protokoll [1] , [2]

JPEG [1]

JScript [1] , [2]

K

Kontrollstrukturen [1]

L

lastChild [1]

Laufschrift [1]

Layer [1]

– bewegen [1]

– immer sichtbar [1]

– verstecken [1]

layers-Objekt

– document [1]

– left [1] , [2]

– parentLayer [1]

– posLeft [1]

– posTop [1]

– top [1] , [2]

– visibility [1]

length [1] , [2] , [3]

LiveAudio [1] , [2]

– Methoden [1]

LiveScript [1]

location-Objekt [1] , [2]

– href [1] , [2] , [3]

– protocol [1]

– reload() [1] , [2]

– replace() [1]

– search [1] , [2] , [3] , [4]

M

MagicCookie [1]

Math-Objekt [1] , [2]

– ceil() [1]

– floor() [1]

– random() [1]

– round() [1]

Methoden – s. Objekte [1]

MIME-Typ [1] , [2]

mimeTypes-Objekt

– description [1]

– enabledPlugin [1]

– suffixes [1]

– type [1]

modale Fenster [1] , [2]

Modulo-Rechnung [1]

Mozilla [1] , [2]

Muster – s. Regulaere Ausdruecke] [1]

Muster – s. Reguläre Ausdrücke- s. Regulaere Ausdruecke] [1]

MyGalileo [1] , [2] , [3] , [4] , [5]

N

Navigation [1]

navigator-Objekt [1]

– appName [1]

– appVersion [1]

– javaEnabled() [1] , [2]

– mimeTypes – s. mimeTypes-Opjekt [1]

– plugins – s. plugins-Objekt [1]

– userAgent [1] , [2]

Netscape 6 [1] , [2]

– DHTML [1]

– DOM [1]

– Ereignisbehandlung [1]

– Erkennung [1]

– Objektzugriff [1]

Newsgroups [1]

nextSibling [1]

nodeName [1]

nodeType [1]

NoteTab [1]

null [1] , [2]

O

Object Signing Tool [1]

Objekte [1] , [2]

– eigene erstellen [1]

– Eigenschaften [1] , [2]

– Konstruktor [1]

– Methoden [1] , [2]

– this [1]

onBlur – s. Event-Handler [1] , [2]

onChange – s. Event-Handler [1]

onClick – s. Event-Handler [1] , [2]

onError [1]

onError – s. Event-Handler [1]

onFocus – s. Event-Handler [1] , [2]

onLoad – s. Event-Handler [1]

onMouseout – s. Event-Handler [1]

onMouseover – s. Event-Handler [1]

onSelect – s. Event-Handler [1]

onSubmit – s. Event-Handler [1]

onUnload – s. Event-Handler [1]

OOP [1]

opener – s. window-Objekt [1]

Opera [1] , [2]

Operatoren

– arithmetische [1]

– Boolesche [1]

– für Zeichenketten [1]

Option-Objekt [1]

P

parentNode [1]

parseFloat() [1] , [2]

parseInt [1]

parseInt() [1]

Perl [1]

Plugin [1]

plugins-Objekt

– filename [1]

– refresh() [1]

Positionierung

– absolute [1]

– relative [1] , [2]

previousSibling [1]

Privileg [1] , [2]

Programmer's File Editor [1]

prompt() – s. window-Objekt [1]

protocol – s. location-Objekt [1]

Punkt vor Strich [1]

Q

Query-String [1]

R

Radiobuttons [1]

– checked [1]

– name [1]

– type [1]

Radiobuttons – s. HTML-Tags [1]

random() – s. Math-Objekt [1]

RegExp-Objekt [1]

– exec() [1]

– match() [1]

– test() [1]

Reguläre Ausdrücke [1]

– Match [1]

– Metazeichen [1]

– Muster [1]

reload() – s. location-Objekt [1] , [2]

removeNode() [1]

replace() – s. location-Objekt [1]

replaceNode() [1]

return – s. Funktionen [1]

return false [1] , [2] , [3] , [4]

return true [1] , [2] , [3] , [4] , [5] , [6]

round() – s. Math-Objekt [1]

S

Schleifen [1]

screen-Objekt

– availHeight [1]

– availWidth [1]

Scrollen [1]

selectedIndex

– Auswahllisten [1]

self [1] , [2] , [3]

serverseitige Programmierung [1]

setAttribute() [1]

setInterval() – s. window-Objekt [1]

setTimeout() – s. window-Objekt [1]

Short Evaluation [1] , [2]

Signiertes Skript [1] , [2]

SmartUpdate [1] , [2] , [3]

Sortierfunktion – s. Array-Objekt [1]

split() – s. String-Objekt [1]

SSI [1]

StarOffice [1]

status – s. window-Objekt [1]

Statuszeile [1]

String-Objekt [1]

– charAt() [1]

– fromCharCode() [1]

– indexOf() [1] , [2]

– length [1] , [2]

– replace() [1]

– Sonderzeichen [1]

– split() [1] , [2]

– substring() [1] , [2]

substring() – s. String-Objekt [1]

switch-Anweisung [1]

– default [1]

T

tags-Objekt [1]

Tastatureingaben – s. Ereignisse [1]

this [1] , [2] , [3]

Timeout [1] , [2] , [3]

top [1]

toString() [1]

U

Ultraedit [1]

unescape() [1]

UniversalBrowserAccess [1] , [2]

UniversalBrowserRead [1] , [2]

UniversalBrowserWrite [1] , [2]

UniversalFileAccess [1]

UniversalFileRead [1]

UniversalFileWrite [1]

UniversalPreferencesRead [1]

UniversalPreferencesWrite [1]

UniversalSendMail [1]

URI [1]

userAgent – s. navigator-Objekt [1]

V

var [1] , [2]

var – s. Variablen [1]

Variablen [1]

– Boolsche [1]

– Deklaration [1]

– globale [1] , [2] , [3]

– lokale [1] , [2]

– Namensgebung [1]

– numerische [1]

– Typenumwandlung [1]

– vertauschen [1]

– Zeichenketten [1]

VBScript [1]

Verisign [1]

Verlauf – s. history-Objekt [1]

W

W3C [1]

Währungsrechner [1]

Warenkorb

– mit Cookies [1]

Webmail [1]

Werbebanner [1]

while-Schleifen [1] , [2]

window-Objekt [1] , [2]

– alert() [1] , [2] , [3] , [4]

– back() [1]

– blur() [1]

– Bubbling [1]

– captureEvents() [1] , [2] , [3] , [4] , [5]

– clearInterval() [1]

– clearTimeout() [1]

– close() [1] , [2]

– closed [1]

– confirm() [1]

– forward() [1]

– frames [1]

– handleEvent() [1]

– innerWidth [1]

– moveBy() [1]

– moveTo() [1]

– name [1]

– open() [1]

– open() – s. Fenster-Eigenschaften [1]

– opener [1] , [2]

– outerHeight [1]

– outerWidth [1]

– pageXOffset [1]

– pageYOffset [1]

– print() [1]

– prompt() [1] , [2]

– releaseEvents() [1]

– routeEvent() [1]

– scroll() [1]

– setInterval() [1] , [2]

– setTimeout() [1] , [2]

– showModalDialog() [1]

– status [1]

Windows Media Player [1]

write() [1]

write() – s. document-Objekt [1]

Y

Y2K [1]

Y2K – s. Jahr-2000-Problem [1]

Z

Zeichenkette – s. String-Objekt [1]

Zigbert [1]

ZIP [1]

Zufall [1] , [2]

<< zurück	<top>
 Zum Katalog

JavaScript
(4. Aufl.)
 bestellen

 Ihre Meinung?

Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps

	Webseiten
	CSS-Praxis
	Kompendium Informations- technik
	Der eigene Webserver
 Empfehlung

	PC-Netzwerke
 Shopping

Versandkostenfrei bestellen in Deutschland und Österreich
Info

 MyGalileo

Der Service für registrierte Leser:

 Info

Copyright © Galileo Press GmbH 2001 - 2002

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

[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de


Page not found

· link is :

""

· in page :

"D:\xampplite\htdocs\aragri\HILFE\galileocomputing_javascript\javascriptindex.htm"


Page not found

· link is :

""

· in page :

"D:\xampplite\htdocs\aragri\HILFE\galileocomputing_javascript\javascriptindex.htm"


Page not found

· link is :

""

· in page :

"D:\xampplite\htdocs\aragri\HILFE\galileocomputing_javascript\javascriptindex.htm"