| ## Dynamische Navigationsleiste
| Hinweise zu diesem Beispiel Quelltext mit Erläuterungen Anzeigebeispiel: So sieht's aus

## Hinweise zu diesem Beispiel

Auf vielen Web-Seiten nimmt die Navigation eigentlich viel zu viel Platz weg. Da wird oft ein Drittel des Anzeigefensters geopfert, um eine oder zwei Handvoll Links zu anderen Projektseiten anzubieten. Mit diesen Platzproblemen macht das Beispiel auf dieser Seite Schluss. Bei dieser Lösung gehört die Web-Seite der freien inhaltlichen Gestaltung und dem Text. Die Navigation blendet sich nur dann ein, wenn der Anwender es will. Dazu muss er auch nicht extra irgendwo hinklicken. Er bewegt einfach die Maus Richtung linken Fensterrand, und schon blendet sich dort die Navigationsleiste ein. Bewegt er die Maus wieder weg vom linken Fensterrand, blendet sich die Navigationsleiste automatisch wieder aus. Diesen Effekt kennen viele Anwender in ähnlicher Form von der Windows-Taskleiste und sind deshalb damit vertraut.

Das Beispiel funktioniert mit den Browsern ab der 4er-Generation. Das Beispiel zeigt vor allem, wie man das Problem der unterschiedlichen Event-Handling-Modelle bei den Browsern in den Griff bekommen kann. Das Beispiel benutzt ferner die DHTML-Bibliothek, um auf Elemente zuzugreifen.

## Quelltext mit Erläuterungen

Das Beispiel zeigt eine vollständige HTML-Datei mit der dynamischen Navigation. Wenn Sie die Navigation auf mehreren Seiten haben wollen, müssen Sie den JavaScript-Code entweder in alle Seiten einbauen, oder sie lagern ihn in eine externe JavaScript-Datei aus und binden diese einfach nur ein.

Die Datei `dhtml.js`, in der die Funktionen der DHTML-Bibliothek enthalten sind, muss vorhanden sein und sich im Beispiel im gleichen Verzeichnis befinden wie die HTML-Datei.

### Beispiel:

Anzeigebeispiel: So sieht's aus ( DHTML-Bibliothek)

    <html><head><title>Test</title>
    <script type="text/javascript" src="dhtml.js"></script>
    <script type="text/javascript">
    <!--
    function Menue() {
     if(DOM) {
       if(MS)
         getElem("id","Nav",null).style.top = document.body.scrollTop + 50;
       else
         getElem("id","Nav",null).style.top = window.pageYOffset + 50;
     }
     if(DOM || MS) {
       if (!DOM) getElem("id","Nav",null).style.top = document.body.scrollTop + 50;
       if (OP) getElem("id","NavLinks",null).style.pixelTop = NavLinksPos;
       getElem("id","Nav",null).style.visibility = "visible";
     }
     else if(NS) {
      getElem("id","Nav",null).visibility = "show";
      getElem("id","Nav",null).top = window.pageYOffset + 50;
     }
    }

    function noMenue() {
     if(DOM || MS)
      getElem("id","Nav",null).style.visibility = "hidden";
     if(NS)
      getElem("id","Nav",null).visibility = "hide";
    }

    function handleMove(ev) {
     if(!MS) {
       Event = ev;
       if(Event.screenX < 270)
         Menue();
       else if(Event.screenX > 420)
         noMenue();
     }
    }

    function MShandleMove() {
     if(MS) {
      if(window.event.clientX < 270)
        Menue();
      else if(window.event.clientX > 420)
        noMenue();
      }
    }

    function Event_init() {
     if(DOM && !MS && !OP) {
      getElem("tagname","body",0).addEventListener("mousemove", handleMove, true);
     }
     if(NS) {
      document.captureEvents(Event.MOUSEMOVE);
      document.onmousemove=handleMove;
     }
     if (DOM && OP) {
        document.onmousemove=handleMove;
        NavLinksPos=42; //Position des Bereiches NavLinks
        getElem("id","NavLinks",null).style.pixelTop=NavLinksPos;

     }
     if (MS) getElem("tagname","body",0).onmousemove=MShandleMove;
    }
    //-->
    </script>
    <style type="text/css">
    <!--
    body { margin-left:50px; margin-top:20px; margin-right:50px; }
    #Nav { position:absolute; top:50px; left:0px; padding:0px; visibility:hidden; margin:0px; }
    #NavLinks { position:absolute; top:42px; left:42px; padding:0px; }
    a.nav:link    { color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
    a.nav:visited { color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
    a.nav:hover   { color:#FFFFFF; background-color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
    a.nav:active  { color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
    -->
    </style>
    </head>
    <body onLoad="Event_init()" background="navigation_back.gif" bgcolor="#FFFFFF">

    <div id="Nav">
     <img src="navigation.gif" width="250" height="450" border="0" alt="">
     <div id="NavLinks">
     <style type="text/css">
      <!--
       a.nav:link    { color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
       a.nav:visited { color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
       a.nav:hover   { color:#FFFFFF; background-color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
       a.nav:active  { color:#000080;
          font-family:Tahoma,sans-serif; font-weight:bold; font-size:10pt; text-decoration:none; }
       -->
      </style>
      <a class="nav" href="http://selfhtml.teamone.de/"><b>SELFHTML</b></a><br>
      <a class="nav" href="http://selfaktuell.teamone.de/"><b>SELFHTML aktuell</b></a><br>
      <a class="nav" href="http://selfforum.teamone.de/"><b>SELFHTML Forum</b></a><br>
      <a class="nav" href="http://selfaktuell.teamone.de/artikel/"><b>Feature Artikel</b></a><br>
     </div>
    </div>

    <h1>Die Seite mit der pfiffigen Navigation</h1>

    <p>Einfach mit die Maus Richtung linken Fensterrand bewegen.
    Um das Men&uuml; wieder wegzubekommen, Maus wieder zum rechten Fensterrand bewegen.</p>

    <p>Und jetzt kommen noch etliche leere Abs&auml;tze, damit auch sichtbar wird,
    da&szlig; das Men&uuml; immer an der gleichen Stelle angezeigt wird, egal wie weit man
    scrollt.</p>

    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
    <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>

    <p>Na, das d&uuml;rfte reichen :-)</p>

    </body></html>

### Erläuterung:

Im sichtbaren HTML-Bereich der Datei ist zunächst ein größerer `div`-Bereich notiert, der mit Hilfe von CSS-Eigenschaften absolut positioniert ist (die Angaben dazu stehen im `style`-Bereich im Dateikopf) und dabei auch die Angabe `visibility:hidden` enthält. Das bedeutet, alles, was sich in diesem Bereich befindet, wird zunächst einmal gar nicht angezeigt. Innerhalb dieses Bereichs mit dem id-Namen `Nav` ist zunächst eine Grafik notiert (`navigation.gif`) und anschließend ein weiterer, absolut positionierter `div`-Bereich, wobei aber dort CSS-Zuweisungen wie `top:42px` oder `left:42px` als relativ zur oberen linken Ecke des Eltern-`div`-Bereichs zu interpretieren sind. Die Grafik navigation.gif ist einfach eine optische Unterlage für den nachfolgenden `div`-Bereich, der die eigentlichen Verweise der Navigationsleiste enthält.

Der Rest des in der Datei notierten statischen HTML-Codes ist für das Beispiel irrelevant. Die vielen Textabsätze mit dem erzwungenen Leerzeichen `&npsp;` dazwischen dienen nur dazu, viel Dokumenthöhe zu erzeugen, so dass man in der Datei scrollen kann. Denn es soll demonstriert werden, dass die dynamische Navigationsleiste immer an der gleichen Stelle erscheint, auch wenn im Dokument gescrollt wird.

Im einleitenden `<body>`-Tag der Datei ist der Event-Handler `onLoad` notiert. Wenn das Dokument vollständig geladen ist, wird die Funktion `Event_init()` aufgerufen. `Event_init()` stößt die Überwachung der Mausbewegungen im Dokument an. Denn nur wenn eine solche Überwachung stattfindet, kann die Navigationsleiste dynamisch eingeblendet werden.

Event-Handling ist leider ein schwieriges Kaptiel, da die Implementierungen bislang doch noch recht unterschiedlich sind. Das Beispiel versucht es erst mal nach der neueren DOM-Syntax. Die Abfrage `if(DOM && !MS && !OP)` stellt sicher, dass der Internet Explorer und Opera 5.12 in diesen Ausführungszweig noch nicht gelangen, da beide in der Version 5.x zwar DOM-Elementzugriffe, aber noch kein Event-Handling nach DOM-Syntax interpretieren. In den entsprechenden Zweig gelangt aber Netscape 6.x, der die Methode `addEventListener()` versteht, mit der nach DOM-Syntax ein Funktion bestimmt wird, die aufgerufen wird, wenn ein bestimmtes Ereignis eintritt. Im Beispiel wird das Ereignis `mousemove` überwacht. Während der Anwender im Dokumentbereich die Maus bewegt, bewirkt diese "Registrierungs-Anweisung", dass dann so oft es geht die Funktion `handleMove()` aufgerufen wird. Zur Bestimmung des zu überwachenden Elementes wird die Funktion `getElem()` der DHTML-Bibliothek aufgerufen.

Mit `if(NS)` fragt die Funktion `Event_init()` ab, ob ein Netscape-Browser der 4er-Generation am Werk ist. Dort gibt es ebenfalls eine "Registrierung" für Ereignisse. Mit `document.captureEvents(Event.MOUSEMOVE)` wird das Ereignis "Mausbewegung" registriert, und mit `document.onmousemove=handleMove` wird die Funktion `handleMove()` aufgerufen, wenn das Ereignis eintritt.

Der Anweisung `if (DOM && OP)` folgen DHTML-fähige Opera-Browser. Hier erfolgt die Initialisierung der Eventüberwachung mit `document.onmousemove=handleMove`. Da Opera 5 unter Windows offensichtlich die Position des Div-Bereich `NavLinks` vergisst, wird die im Stylessheet-Bereich festgelegte Position in der Variablen `NavLinksPos` gespeichert. Anschließend wird der Bereich `NavLinks` neu positioniert. Damit auch ältere Versionen von Opera 5 damit zurecht kommen, wird die Eigenschaft `pixelTop` verwendet. Zur Bestimmung des Elementes wird die Funktion `getElem()` der DHTML-Bibliothek aufgerufen.

Beim Internet Explorer gestaltet sich die Ereignisbehandlung leider etwas anders. Mit `if (MS)` wird in der Funktion `Event_init()` der für den MS Internet Explorer gültige Bereich abgearbeitet. Auch hier wird wieder die Funktion `getElem()` der DHTML-Bibliothek verwendet. Im Gegensatz zu den anderen Browsern wird hier die Funktion `MShandleMove()` aufgerufen, wenn das Ereignis eintritt. Dort wird mit `if(MS)` sichergestellt, dass kein anderer Browser als ein Internet Explorer am Werk ist. Abhängig davon wird mit `window.event.clientX` der Abstand des Mauszeigers vom linken Fensterrand ermittelt. Wenn er geringer ist als 270 Pixel, wird die Funktion `Menue()` aufgerufen. Wenn er höher als 420 Pixel ist, die Funktion `noMenue()`. Genau das Gleiche passiert auch in der Funktion `handleMove()`, in die die Netscape-Browser gelangen. Dort wird der Abstand des Mauszeigers vom linken Fensterrand allerdings mit der `screenX`-Eigenschaft abgefragt. Das sind die tausend kleinen Unterschiede zwischen den Browsern, die Programmierer zum Wahnsinn treiben können. Immerhin wird irgendwann diese ganze `if`-Weiche entfallen und alle Browser werden die DOM-Syntax verstehen.

Die Funktion `Menue()` blendet die Navigationsleiste ein, und die Funktion `noMenue()` sorgt dafür, dass die Navigationsleiste nicht oder nicht mehr sichtbar ist. Beide Funktionen führen zu diesem Zweck wieder diverse `if`-Abfragen zur DHTML-Modellunterscheidung durch und ändern letztendlich hauptsächlich die CSS-Eigenschaft `visibility` (Sichtbarkeit) des großen `div`-Bereichs mit dem Id-Namen `Nav`. Die Funktion `Menue()` sorgt allerdings außerdem dafür, dass der von ihr auf sichtbar geschaltete Navigationsbereich auch immer schön im sichtbaren Bereich des Dokuments angezeigt wird, egal, wohin der Anwender im Dokument gescrollt hat. Dazu muss die Funktion die aktuelle Pixelposition der "Klopapierrolle" ermitteln, die ein langes Dokument darstellt. Auch dabei ist die Syntax leider wieder völlig unterschiedlich bei den Browsern. Beim Internet Explorer kommt die Funktion über die Eigenschaft `document.body.scrollTop` an den gewünschten Wert, und bei Netscape-Browsern und Opera über `window.pageYOffset`. Zu dem ermittelten Wert werden noch mal 50 Pixel dazugezählt, denn in dem `div`-Bereich mit dem Id-Namen `Nav` ist ja als `top`-Angabe, also als Startposition von oben gesehen, ebenfalls der Wert 50 angegeben.
Da Opera 5 beim Ändern der Fenstergröße mit JavaScript gesetzte Positionen "vergisst", wird vor jedem Einblenden des Menues dem Bereich `NavLinks` die in der Variablen `NavLinksTop` gespeicherte Position zugewiesen.

Vielleicht fragen Sie sich jetzt noch, woher die Werte `270` und `420` für die Mausposition vom linken Fensterrand kommen, die über den Aufruf von `Menue()` und `noMenue()` entscheiden. Dazu kann man nicht viel mehr sagen als dass es mit verschiedenen Browsern ausgetestete Erfahrungswerte sind. In der Regel funktioniert es beispielsweise nicht mehr, wenn der kleinere Wert kleiner als `250` ist. Warum, bleibt rätselhaft. Aber diese Rätselhaftigkeiten gehören leider zum Alltag der DHTML-Programmierung, solange die JavaScript-Interpreter der Browser immer noch nicht ausgereift sind.

### Beachten Sie:

Erklären Sie dem Anwender auf der ersten Seite, wo Sie eine solche Navigation verwenden, kurz mit einem Satz das Handling der Navigation. Seien Sie sich auch im Klaren darüber, dass Anwender mit nicht DHTML-fähigen Browsern oder deaktiviertem JavaScript so wie das Beispiel oben notiert ist überhaupt keine Möglichkeit zur Navigation haben. Um zumindest Anwendern, die JavaScript deaktiviert haben, ein Navigieren zu ermöglichen, könnten Sie beispielsweise an einer geeigneten Stelle im normalen Text einen noscript-Bereich notieren, in dem Sie die Navigationsverweise noch mal notieren.

| Laufende Datums-/Uhrzeitanzeige
| Allgemeine DHTML-Bibliothek

© 2001 selfhtml@teamone.de