Galileo Computing <openbook>
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


JavaScript von Christian Wenz
Browserübergreifende Lösungen
JavaScript - Zum Katalog
gp Kapitel 16 DHTML I: Netscape
  gp 16.1 Grundlagen
  gp 16.2 Beispiele
  gp 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.

gp  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.

Galileo Computing

16.1 Grundlagen  downtop

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.


Galileo Computing

16.1.1 Begriffsbestimmung  downtop

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.


Galileo Computing

16.1.2 Cascading Style Sheets  downtop

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 Sheets (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>

Galileo Computing

16.1.3 Positionierung von Elementen  downtop

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.


Galileo Computing

16.1.4 JavaScript Style Sheets  downtop

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
Abbildung


Galileo Computing

16.1.5 Layer  downtop

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:

gp  document.Layername
gp  document.layers[Layerindex]
gp  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
Abbildung

Um nun auf die Schaltfläche im Dokument zuzugreifen, müssen Sie den folgenden Code verwenden:

document.Layer1.document.Layer2.forms[0].elements[0]

Galileo Computing

16.2 Beispiele  downtop

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.


Galileo Computing

16.2.1 Animiertes Logo  downtop

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:

gp  Das Logo wird in einen Layer eingefügt.
gp  Die Positionierung dieses Layers wird auf relativ gesetzt.
gp  Beim Laden der Seite wird der Layer zuerst recht weit nach links bewegt.
gp  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
Abbildung

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.


Galileo Computing

16.2.2 Drag&Drop  downtop

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:

gp  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.
gp  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).
gp  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.
Abbildung


Galileo Computing

16.2.3 Sichtbar und unsichtbar  downtop

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:

gp  Die drei Register werden im HTML-Code definiert und alle an dieselbe Stelle gesetzt.
gp  Das erste Register wird sichtbar gemacht (bzw. bleibt sichtbar), die anderen beiden werden unsichtbar.
gp  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.
Abbildung

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>

Galileo Computing

16.2.4 Neuer Mauszeiger  downtop

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/pics/logo_anim2.gif – aber Sie können auch eine beliebige andere Grafik verwenden. Die folgenden Schritte müssen umgesetzt werden, damit dies funktioniert:

gp  Der Layer mit der Grafik wird im HTML-Code definiert (mit ID="mauszeiger").
gp  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
Abbildung


Galileo Computing

16.2.5 Permanentes Werbebanner  downtop

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:

gp  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).
gp  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
Abbildung

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>

Galileo Computing

16.3 Fragen & Aufgaben  toptop

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.

  

Perl – Der Einstieg




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