SELFHTML/Quickbar Dynamisches HTML Lösungen für die Praxis

| ## Verschiebbare Seitenelemente
| Verschiebbare Seitenelemente - das Beispiel

## Verschiebbare Seitenelemente - das Beispiel

Anzeigebeispiel: So sieht's aus

Dieses Beispiel realisiert eine HTML-Datei, in der verschiedene Bereiche für den Anwender mit der Maus frei verschiebbar sind, so wie Fenster in einer grafischen Benutzeroberfläche. Die Bereiche können sich dabei auch beliebig überlappen. Der zuletzt angeklickte und zurechtgeschobene Bereich ist automatisch im Vordergrund. Das Beispiel ist so geschrieben, daß die Funktionalität bei Netscape 4.x und MS Internet Explorer 4.x in etwa gleich ist. An diesem Beispiel können Sie auch erkennen, daß der Programmieraufwand für "schicke" Features schnell höher werden kann.

Hinweis: Zur besseren Orientierung enthält das Beispiel Verweise zu den entsprechenden Erläuterungen, z.B. 1*. Diese Verweise gehören nicht zum Quellcode. Falls Sie das Beispiel in einen Editor kopieren, müssen Sie diese Verweise löschen. Andernfalls erhalten Sie JavaScript-Fehlermeldungen.

### Beispiel:

    <html>
    <head>
    <style type="text/css">
     layer { padding:10px }
    </style>
    3* <script language="JScript">
    <!--
    var max = 4;
    var Merker = 0;
    9* function Merken()
    {
     if(window.event.srcElement.id == "div1" && Merker == 0) Merker = 1;
     else if(window.event.srcElement.id == "div2" && Merker == 0) Merker = 2;
     else if(window.event.srcElement.id == "div3" && Merker == 0) Merker = 3;
     else if(Merker > 0) Merker = 0;
    }
    10* function Plazieren()
    {
     if(window.event.srcElement.id == "div1" && Merker == 1)
     {
      document.all.div1.style.zIndex = max; max+=1;
      document.all.div1.style.left = window.event.x - 100;
      document.all.div1.style.top = window.event.y - 125;
     }
     if(window.event.srcElement.id == "div2" && Merker == 2)
     {
      document.all.div2.style.zIndex = max; max+=1;
      document.all.div2.style.left = window.event.x - 150;
      document.all.div2.style.top = window.event.y - 200;
     }
     if(window.event.srcElement.id == "div3" && Merker == 3)
     {
      document.all.div3.style.zIndex = max; max+=1;
      document.all.div3.style.left = window.event.x - 200;
      document.all.div3.style.top = window.event.y - 90;
     }
    }
    // -->
    </script>
    7* <script for="document" Event="onclick()" language="JScript">
     Merken();
    </script>
    8* <script for="document" Event="onmousemove()" language="JScript">
     Plazieren();
    </script>
    </head>
    <body bgcolor=#FFFFFF>

    1* <div id="div1" style="position:absolute; top:150px; left:30px;
    width:200px; height:250px; background-color:#DDFFDD; color:#006600;
    font-family:Arial; font-size:9pt; font-weight:bold; padding:10px;">
    2* <layer id="lay1" width=200 height=250 bgcolor=#DDFFDD>
    Hier steht der Inhalt von Bereich 1.
    </layer>
    </div>

    <div id="div2" style="position:absolute; top:30px; left:300px;
    width:300px; height:400px; background-color:#FFDDDD; color:#660000;
    font-family:Arial; font-size:9pt; font-weight:bold; padding:10px;">
    <layer id="lay2" width=300 height=400 bgcolor=#FFDDDD>
    Hier steht der Inhalt von Bereich 2.
    </layer>
    </div>

    <div id="div3" style=position:"absolute; top:180px; left:100px;
    width:400px; height:180px; background-color:#DDDDFF; color:#000066;
    font-family:Arial; font-size:9pt; font-weight:bold; padding:10px;">
    <layer id="lay3" width=400 height=180 bgcolor=#DDDDFF>
    Hier steht der Inhalt von Bereich 3.
    </layer>
    </div>

    4* <script language="JavaScript">
    <!--
    var maxlay = 4;
    if(document.layers)
    { Gruen = document.layers[0]; Rot = document.layers[1]; Blau = document.layers[2];
       InitGruen(); InitRot(); InitBlau();
    }
    function InitGruen()
    5* { Gruen.captureEvents(Event.CLICK);
      Gruen.onclick=StartGruen; Gruen.onload=GruenReset;
    }
    function InitRot()
    { Rot.captureEvents(Event.CLICK);
      Rot.onclick=StartRot; Rot.onload=RotReset;
    }
    function InitBlau()
    { Blau.captureEvents(Event.CLICK);
      Blau.onclick=StartBlau; Blau.onload=BlauReset;
    }
    function StartGruen()
    { Gruen.zIndex = maxlay; maxlay+=1;
      6* Gruen.captureEvents(Event.MOUSEMOVE|Event.CLICK);
      Gruen.onmousemove=ZiehGruen; Gruen.onclick=EndGruen;
    }
    function EndGruen()
    { Gruen.onmousemove=0; Gruen.releaseEvents(Event.MOUSEMOVE); InitGruen(); }
    function GruenReset()
    { Gruen.captureEvents(Event.CLICK|Event.MOUSEMOVE); }
    function ZiehGruen(Ereignis)
    { Gruen.left = Ereignis.pageX - 100; Gruen.top = Ereignis.pageY  - 240; }
    function StartRot()
    { Rot.zIndex = maxlay; maxlay+=1;
      Rot.captureEvents(Event.MOUSEMOVE|Event.CLICK);
      Rot.onmousemove=ZiehRot; Rot.onclick=EndRot;
    }
    function EndRot()
    { Rot.onmousemove=0; Rot.releaseEvents(Event.MOUSEMOVE); ; InitRot(); }
    function RotReset()
    { Rot.captureEvents(Event.CLICK|Event.MOUSEMOVE); }
    function ZiehRot(Ereignis)
    { Rot.left = Ereignis.pageX - 150; Rot.top = Ereignis.pageY - 390; }
    function StartBlau()
    { Blau.zIndex = maxlay; maxlay+=1;
      Blau.captureEvents(Event.MOUSEMOVE|Event.CLICK);
      Blau.onmousemove=ZiehBlau; Blau.onclick=EndBlau;
    }
    function EndBlau()
    { Blau.onmousemove=0; Blau.releaseEvents(Event.MOUSEMOVE); ; InitBlau(); }
    function BlauReset()
    { Blau.captureEvents(Event.CLICK|Event.MOUSEMOVE); }
    function ZiehBlau(Ereignis)
    { Blau.left = Ereignis.pageX - 200; Blau.top = Ereignis.pageY - 170; }
    // -->
    </script>

    </body>
    </html>

### Erläuterung:

Etwa in der Mitte des obigen Beispiels, unterhalb des öffnenden `<body>`-Tags, werden insgesamt drei Bereiche definiert (1*). Alle drei Bereiche werden zunächst als `<div>`-Bereiche definiert. Die drei Bereiche erhalten die id-Namen `"div1"`, `"div2"` und `"div3"`. Mit Hilfe von Style-Sheet-Angaben zur Positionierung werden die Bereiche im Anzeigefenster genau plaziert. Die Bereiche überlappen sich dabei. Da keine spezielle Schichtreihenfolge festgelegt wird, liegt der zuletzt definierte Bereich zunächst über den beiden anderen Bereichen. Es handelt sich bei dieser Anordnung jedoch nur um den Ausgangszustand, den der Anwender später ändern kann.

Innerhalb der drei `<div>`-Bereiche finden Sie im obigen Beispiel jeweils drei entsprechende `<layer>`-Bereiche (2*). Diese Form der Verschachtelung hat sich als praktikabel erwiesen. Denn der MS Internet Explorer ignoriert das `<layer>`-Tag, interpretiert jedoch den Inhalt, der zwischen `<layer>` und `</layer>` steht. Netscape dagegen interpretiert zwar zuerst das `<div>`-Tag, freut sich dann aber über das innere `<layer>`-Tag, mit dem er bei Dynamischem HTML letztlich doch besser klar kommt. Die `<layer>`-Bereiche im Beispiel haben keine Angaben zu den Werten `left=` und `top=`. Dadurch beginnen sie einfach links oben innerhalb der übergeordneten `<div>`-Bereiche.

Das gesamte Handling zum Verschieben der Bereiche für den Fall, daß der Anwender mit der Maus darauf klickt und anschließend die Maus bewegt, ist in dem Beispiel in zwei Script-Bereichen untergebracht. Beide Script-Bereiche sind streng voneinander getrennt. Einer der beiden Bereiche steht im Dateikopf - das ist der Scriptbereich für den MS-Internet Explorer (3*). Dieser Script-Bereich ist mit der Angabe `language="JScript"` ausgezeichnet. Dadurch wird erreicht, daß Netscape diesen Bereich komplett ignoriert. Der andere Script-Bereich ist unterhalb der drei `<div>`-Bereiche notiert (4*). Dieser Script-Bereich ist mit `language="JavaScript"` ausgezeichnet, wird also von Netscape und vom MS Internet Explorer wahrgenommen. Da der MS Internet Explorer in diesem Bereich allerdings nichts zu suchen hat, werden die Anweisungen, die gleich am Anfang des Script-Bereichs außerhalb jeder Funktion stehen, durch die Abfrage `if(document.layers)` nur Netscape zugänglich gemacht.
Das strenge Trennen der Script-Bereiche in diesem Beispiel macht insofern Sinn, als das Behandeln von Ereignissen wie Mausaktionen des Anwenders in Netscape und im MS Internet Explorer so unterschiedlich gelöst sind, daß es schwierig wäre, mit Hilfe einzelner if-Abfragen innerhalb der gleichen Code-Bereiche zu arbeiten.

Das Handling für Netscape entspricht in etwa dem, das im Beispiel zum Event-Objekt bei Netscape genauer beschrieben wird. Mit `captureEvents(Event.CLICK)` werden alle drei `<layer>`-Bereiche initialisiert (5* ). Das CLICK-Ereignis wird also für die drei Bereiche überwacht. Wenn es eintritt, also wenn der Anwender mit der Maus auf einen der Bereiche klickt, wird für den betreffenden Bereich eine Funktion aufgerufen. Wenn beispielsweise der grüne Bereich angeklickt wird, wird die Funktion `StartGruen` aufgerufen. Diese "Start"-Funktionen überwachen mit `captureEvents(Event.MOUSEMOVE)` das Ereignis "Anwender bewegt Maus", und mit `captureEvents(Event.CLICK)` das Ereignis "Anwender klickt erneut auf den Bereich" (6*). Beim Bewegen der Maus wird der Bereich verschoben, beim erneuten Klicken wird der Bereich an der aktuellen Stelle gelassen. Dazu werden zum Bewegen Funktionen wie `ZiehGruen` und zum beendenden Klicken Funktionen wie `EndGruen` aufgerufen. Am Ende so einer Funktion, etwa am Ende der Funktion `EndGruen`, wird wieder die Initialisierung aufgerufen. Dadurch wird wieder über einen neuen Verschiebewunsch des Anwenders gewacht.

Zum Handling für den MS Internet Explorer kommt das Event-Objekt bei Microsoft zum Einsatz. Dazu werden im Dateikopf des Beispiels zwei spezielle Scriptbereiche definiert (7* und 8*). Diese Scripts mit ihrer speziellen Syntax überwachen dokumentübergreifend die beiden Anwenderaktionen "Mausklick" - `onclick()` - und "Mausbewegung" - `onmousemove()`. Wenn der Anwender mit der Maus ins Anzeigefenster klickt, wird die Funktion `Merken()` aufgerufen (9*). Diese Funktion verwaltet eine global definierte Variable namens `Merker`. Wenn der Merker den Wert 0 hat, wird der Mausklick als Anfangsklick interpretiert, dem ein Bewegen des Bereichs folgen kann. Wenn der Merker einen höheren Wert hat als 0, wird der Klick als Endklick interpretiert. Danach ist kein Bewegen des Bereichs möglich.
Wenn die Maus bewegt wird, wird die Funktion `Plazieren()` aufgerufen (10*). Ist der Merker größer als 0, wird sein Wert ausgelesen und der entsprechende Bereich neu positioniert.

Erwähnt werden sollte noch, wie das Positionieren eines der verschiebbaren Bereiche beim Bewegen der Maus programmiert ist. Das Bewegen der Bereiche wird durch Zuordnen der aktuellen Position des Bereichs zur aktuellen Position der Maus realisiert. Beim MS Internet Explorer geschieht dies innerhalb der Funktion `Plazieren()`, beispielsweise mit folgenden Anweisungen:
`document.all.div1.style.left = window.event.x - 100;`
`document.all.div1.style.top = window.event.y - 125;`
Bei Netscape geschieht die vergleichbare Zuordnung innerhalb der `Zieh*`-Funktionen, etwa innerhalb der Funktion `ZiehGruen`, und zwar durch Anweisungen wie:
`Gruen.left = Ereignis.pageX - 100;`
`Gruen.top = Ereignis.pageY - 240;`
Abgesehen von der unterschiedlichen Syntax fällt auf, daß die Angaben für den Wert der neuen oberen linken Ecke "von links" nicht in beiden Fällen gleich ist. Der y-Wert ist im einen Fall 125, im anderen 240. Die x-Werte sind dagegen in beiden Fällen mit 100 angegeben. Die 100 bedeutet: 100 Pixel links ("minus") von der aktuellen Mausposition. Da der grüne Bereich, um den es dabei geht, eine Breite von 200 Pixeln hat, bleibt die Maus beim Bewegen dadurch immer horizontal in der Mitte des Bereichs. Analog dazu ist es beim MS Internet Explorer auch für den vertikalen Wert. Der Wert der neuen oberen linken Ecke "von oben" liegt 125 Pixel oberhalb der aktuellen Mausposition. Da der Bereich 250 Pixel hoch ist, ist das also auch hier genau die Mitte. Leider würde der gleiche Wert bei Netscape Probleme aufwerfen, sobald der Layer an der Stelle, an der sich die Maus befindet, irgendwelche Inhalte hat, also Text, Grafiken usw. Deshalb wurde bei Netscape als Wert für "von oben" 240 gewählt. Bei der Bereichshöhe von 250 Pixeln bleibt die Maus während des Bewegens also ziemlich weit unten im Bereich, dort, wo keine Inhalte mehr stehen.

weiter: | Bilderbuch zum Umblättern
zurück: | Datums-/Uhrzeitanzeige

SELFHTML/Quickbar Dynamisches HTML Lösungen für die Praxis

© 1998 Stefan Münz, muenz@csi.com