Anzeige
Tutorialbeschreibung

Praxisfälle für JavaScript/DOM - Navigation im Explorer-Stil

Praxisfälle für JavaScript/DOM - Navigation im Explorer-Stil

In Kapitel 7 wurden zwar schon diverse für die Praxis nützliche Scripts vorgestellt, dochdie Beispiele hatten dort unterstützenden Charakter, um bestimmte Sprachkonzepte zuerläutern. In diesem Kapitel sollen die Beispiele im Vordergrund stehen. Das Kapitel zeigt,wie praxistypische Scripts entstehen und was dabei berücksichtigt werden sollte.Wir konzentrieren uns auf drei wirklich nützliche Anwendungen, die JavaScript auch fürprofessionelle Seiten salonfähig macht. Das Kapitel hat Workshop-Charakter. 


Das nun folgende Tutorial ist ein Auszug aus dem Buch: Professionelle Websites von Stefan Münz.
Die Veröffentlichung des Kapitels erfolgt mit freundlicher Genehmigung von Pearson Education.


2 Navigation im Explorer-Stil


An kaum eine Form der Navigation haben sich Anwender in den letzten Jahren so gewöhnt wie an diejenige im Stil des Windows Explorers. Längst findet sich diese Art des Auswählens in allen erdenklichen Anwendungen wieder, egal ob Vektorgrafikprogramm, Programmieroberfläche, elektronische Steuererklärung oder Bookmarks im Browser.

In HTML gibt es von Haus aus kein Element, das eine solche Navigation realisiert (leider, denn eigentlich darf von einer Sprache, die »Hypertext« im Namen trägt, durchaus erwartet werden, dass sie mehr Möglichkeiten zur Realisierung einer Navigation bietet als einfache Hyperlinks).

Im Rahmen des CSS-Praxiskapitels (Abschnitt 5.2) lernten Sie bereits Möglichkeiten kennen, eine attraktive Navigation für eigene Websites zu realisieren, und zwar allein mit HTML und CSS. Für explorerartige Menüs geht es nicht ohne ein Minimum an JavaScript. Wir werden in unserem Beispiel mit überraschend wenig JavaScript auskommen. Das Beispiel erfüllt auch noch einige andere wichtige Kriterien:

- Das HTML-Markup der Navigation soll strukturell sinnvoll sein, so dass es auch bei nicht grafischen Browsern ordentlich aussieht. Gerade weil Projekte, die ein baumartiges Menü anbieten, in der Regel aus sehr vielen Unterseiten bestehen, ist ein strukturell gut nachvollziehbarer Aufbau der Navigation wichtig. Wir werden in unserem Beispiel mit verschachtelten Aufzählungslisten arbeiten.
- Die Navigation soll auch bei deaktiviertem JavaScript einwandfrei und ohne Zusatzaufwand funktionieren. Auch das ist bei unserem Beispiel der Fall.
- Das Auf- und Zuklappen von Teilbäumen soll aus Anwendersicht schnell reagieren und auch bei größeren Menüstrukturen nicht zu merklichen Verzögerungen führen.
- Der aktuelle Menüzustand (auf- und zugeklappte Teilbäume) soll an die nächste aufgerufene Seite übergeben werden, so dass er beim Seitenwechsel erhalten bleibt. Andernfalls wäre es für den Anwender mühsam, sich nach jedem Seitenwechsel wieder erneut durch die Struktur zu klicken.
- Das Script soll wiederverwendbar sein, d.h. auf beliebige andere Menüstrukturen anwendbar.

2.1 Das Beispiel


Navigationsstrukturen dieser Art bieten sich vor allem für größere technische Dokumentationen, für wissenschaftliche Abhandlungen und für systematische Darstellungen von Wissensgebieten an. In unserem Beispiel zeigen wir dies anhand eines kleinen Ausschnitts der Systematik der Tierwelt (Fauna).

Bilder

Abbildung 8.2: Angedeutete Fauna-Systematik mithilfe eines explorerartigen Menüs

2.2 Quelltexte und Erläuterungen

Zunächst der Quelltext des HTML-Dokuments. Der JavaScript-Code wird in eine externe Datei ausgelagert, da er ja auf allen Seiten wiederverwendet werden soll:

Listing 8.3: HTML-Quelltext mit verschachtelter Aufzählungsliste für Explorer-Menü
Bilder

Bevor wir auf die Details eingehen, ein Wort zum Thema »Vermeidung von Frames«. Da die Menüstruktur doch recht umfangreich ist und bei Verzicht auf Frames auf jeder Seite wiederholt werden muss, entsteht natürlich eine Menge vielfach wiederholter HTMLQuellcode. Solange mit statischen HTML-Dateien gearbeitet wird, ist es ohne Frames tatsächlich nicht vermeidbar, den Code auf jeder Unterseite zu wiederholen. Sobald jedoch serverseitige Techniken, egal ob Server Side Includes (SSI), PHP oder eine andere Scriptsprache zum Einsatz kommen, kann der entsprechende Code in ein Template ausgelagert werden, dass dann einfach nur dynamisch integriert wird. Auf diese Möglichkeiten gehen wir jedoch erst in Zusammenhang mit serverseitigen Techniken ein.

Der body-Bereich unseres Beispiels besteht aus zwei div-Bereichen namens navigation und content. Ein Ausschnitt aus der CSS-Datei zeigt, wie das Seitenlayout sich grundsätzlich zusammensetzt:

Bilder

Der Bereich für die Navigation ist absolut positioniert und erhält eine großzügige Breite von 400 Pixel. Das ist für stark verzweigte Baumstrukturen durchaus angemessen. Falls der Inhalt zu breit ist, wird er abgeschnitten (overflow:hidden). Der hellgrüne Bereich mit dem Schatteneffekt, der als Hintergrund der Navigation dient, ist durch ein Hintergrundbild realisiert. Der Bereich content bleibt im normalen Textfluss, damit seine Breite sich an der zur Verfügung stehenden Breite des Browserfensters orientieren kann. Sein linker Rand beträgt 430 Pixel, da 400 Pixel davon dem Bereich für die Navigation gehören.

Der Bereich navigation besteht aus einer umfangreichen verschachtelten Aufzählungsliste, also aus ul- und li-Elementen. Das äußerste ul-Element erhält den id-Namen root. Dies wird vom Script ausgewertet und ist daher Pflicht.

Zur Erinnerung noch einmal das Prinzip verschachtelter Aufzählungslisten in HTML:

<ul>
<li>Listenpunkt</li>
<li>Unterliste:
<ul>
<li>Listenpunkt</li>
Navigation im Explorer-Stil 415
<li>Listenpunkt</li>
</ul>
</li>
</ul>

Eine untergeordnete Liste beginnt also damit, dass ein li-Element der übergeordneten Liste mit einem »Überschriftentext« für die Unterliste beginnt. Daran anschließend wird die innere ul-Liste komplett notiert. Abschließend wird das schließende </li>-Tag notiert. Untergeordnete Listen müssen also als Elementinhalt eines li-Elements der übergeordneten Liste notiert werden.

In unserem Beispiel erhält jedes ul-Element sowohl einen id-Namen (id=) als auch eine Klasse (class=), z.B.:

<ul id="ul_faunawelt_intern" class="opened">

Allen ul-Elementen der Navigation wird der Klassenname opened zugewiesen. In CSS ist für diese Klasse Folgendes definiert:

ul.opened {
display:block;
}

Das mag trivial erscheinen, da es der Default-Einstellung entspricht. Im Script werden wir jedoch über den Klassennamen das Auf- und Zuklappen von Teilbäumen realisieren und deshalb wird in der CSS-Datei bereits folgende »Parallelklasse« eingerichtet:

ul.closed {
display:none;
}

Für beide Klassen werden im Beispiel außerdem folgende Gemeinsamkeiten festgelegt:

ul.closed, ul.opened {
font-size:12px;
list-style-type:none;
font-weight:bold;
line-height:16px;
}

Der id-Name jedes ul-Elements sollte den Teilbaum, den die jeweilige ul-Liste enthält, möglichst sprechend charakterisieren. Außerdem – und das ist für unser Script wichtig – muss der Name mit ul_ beginnen. Als Alternative zu sprechenden id-Namen können Sie natürlich auch ein Namensschema wie ul_section_1_1, ul_section_1_2 usw. verwenden. Letzteres hat jedoch den Nachteil, dass es weniger änderungsfreundlich ist, wenn mal neue Seiten eingefügt werden sollen.

Betrachten wir nun ein li-Element, welches eine untergeordnete ul-Liste eröffnet, im Zusammenhang:

<li id="faunawelt_intern">
<a class="folder" onclick="toggle('faunawelt_intern'),true">
<img src="opened.gif" alt="" id="img_faunawelt_intern">
FAUNA-WELT intern</a>
<ul id="ul_faunawelt_intern" class="opened">
...
</ul>
</li>

Jedes li-Element, das eine untergeordnete ul-Liste enthält, erhält ebenfalls einen id- Namen. Und zwar den gleichen id-Namen wie die ul-Liste, nur ohne voranstehendes ul_. Im Code-Ausschnitt hat das li-Element den id-Namen faunawelt_intern und die innere ul-Liste folgerichtig den id-Namen ul_faunaweld_intern. Dieser Zusammenhang muss bei allen inneren Listen nach der gleichen Regel hergestellt werden, damit unser Script korrekt arbeitet.

Das Gleiche gilt für weitere Regeln zum Aufbau des einleitenden Teils des li-Elements vor der inneren ul-Liste. Dieser Teil besteht aus einem a-Element, welches den Klassennamen folder erhalten muss. Diese Klasse ist in CSS wie folgt definiert:

a.folder {
cursor:pointer;
}

Da kein href-Attribut notiert ist, wird kein echter Link angezeigt. Der li-Eintrag soll ja auch kein echter Link sein, sondern beim Anklicken lediglich den inneren Teilbaum aufbzw. wieder zuklappen. Damit er als anklickbar erkennbar ist, erscheint der Mauscursor beim Überfahren wie bei einem Hyperlink.

Das so definierte a-Element bei li-Texten, welche eine untergeordnete ul-Liste einleiten, muss außerdem einen Event-Handler onclick= erhalten. Dieser muss als Wertzuweisung einen Aufruf der JavaScript-Funktion toggle() erhalten. Als erster Parameter muss der Funktion der id-Name des li- Elements übergeben werden und als zweiter der Wert true.

Der Elementinhalt des a-Elements besteht aus einer Grafikreferenz, gefolgt von dem eigentlichen Eintragstext. Die Grafik erhält den Dateinamen opened.gif. Sie sollte ein geöffnetes Ordnersymbol darstellen und in der Höhe nicht mehr als 14 Pixel haben. Das img-Element der Grafikreferenz erhält ebenfalls zwingend einen id-Namen, und zwar wieder den gleichen Basisnamen wie das li- Element, jedoch angeführt von der Zeichenfolge img_. Auch das ist für das Script wichtig.

Bleiben noch diejenigen li-Elemente, die echte Links zu aufrufbaren Seiten enthalten. Ein Beispielauszug:

<li><img src="doc.gif" alt="">
<a class="nav" href="/index.php?id=002">Über uns</a></li>

Der Elementinhalt besteht hierbei aus einer Grafik namens doc.gif, welche ein Seitensymbol enthalten und ebenfalls nicht höher als 14 Pixel sein sollte. Anschließend folgt der Link zur Seite. Er erhält den Klassennamen nav. Für diese Klasse ist in CSS im Beispiel Folgendes definiert:

a.nav {
font-weight:bold;
font-style:italic;
}
a.nav:link, a.nav:visited, a.nav:hover, a.nav:active {
color:rgb(8,108,8);
text-decoration:none;
}

Wie aus den vorangehenden Beschreibungen deutlich wird, haben wir eine Menge »Intelligenz « bereits in den HTML-Code verlagert. Das ist erstens die Voraussetzung für ein schlankes JavaScript und zweitens wertet es den HTML-Code semantisch auf, indem durch id- und Klassennamen die inneren Bezüge verdeutlicht werden.

Damit zum Inhalt des Scripts, welches im Beispiel in eine externe Datei namens explorer.js ausgelagert wurde:

Listing 8.4: JavaScript für Explorer-Menü
Bilder


Im HTML-Code wird die Verbindung zum JavaScript an zwei Stellen hergestellt. Im einleitenden <body>-Tag ist onload="init_nav()" notiert. Die Funktion init_nav() ist im Script als Erste von insgesamt vier Funktionen notiert. Sie geht zunächst in einer for-Schleife alle ul-Elemente durch und erfragt in einer if-Bedingung, ob das jeweils aktuell betrachtete ul- Element den Klassennamen opened hat. Ist das der Fall, so wird das Elementobjekt des Elternelements des aktuellen ul- Elements in einer Variablen namens id gespeichert. Bei allen ul-Elementen außer der äußersten ul-Liste ist das Elternelement das li-Element, welches die innere ul-Liste einleitet. Dessen Elementobjekt wird in id gespeichert. Anschließend wird die Funktion toggle() aufgerufen. Ihr wird als erster Parameter die Variable id übergeben und als zweiter Parameter der Wert false. Auf Letzteren kommen wir später noch zurück.

Die Funktion toggle() tut Folgendes: Wenn ein Teilbaum der Navigation aufgeklappt ist, schließt sie ihn. Ist er dagegen geschlossen, klappt sie ihn auf. Dazu benutzt sie die Klassennamen, welche die ul-Listen mit dem jeweiligen Teilbaum enthalten. In HTML – wir erinnern uns – haben wir bewusst alle ul-Elemente von Teilbäumen mit dem Klassennamen opened ausgestattet. In CSS bewirkt dieser display:block also eine normale Anzeige. Der Grund ist, dass bei ausgeschaltetem JavaScript der gesamte Navigationsbaum aufgeklappt angezeigt werden soll. Im Script möchten wir jedoch anfänglich einen Zustand herstellen, der den Baum zunächst zugeklappt darstellt. Genau das leistet die for- Schleife in init_nav(), die alle betroffenen Elemente ermittelt und durch Aufruf von toggle() dafür sorgt, dass diese zugeklappt werden.

Damit aber nicht genug. Nachdem die for-Schleife abgearbeitet ist, wird abgefragt, ob die Eigenschaft window.name eine Länge von mehr als 0 Zeichen hat. In Abschnitt 7.3.12 wurde diese Default-Eigenschaft vorgestellt und gezeigt, wie sich damit JavaScript-Informationen seitenübergreifend speichern lassen. Unser Script benutzt diese Eigenschaft, um den aktuellen Auf- Zuklappzustand der Navigation zu speichern und wieder laden zu können. Allein diesem Zweck dienen die beiden letzten Funktionen im Script, save_nav() und load_nav(). Die Funktion toggle() ruft gegebenenfalls save_nav() auf, um den aktuellen Menüzustand zu speichern, und init_nav() ruft load_nav() auf, um einen gespeicherten Menüzustand wiederherzustellen. Ist in window.name also etwas gespeichert, dann kommt load_nav() zum Einsatz.

Die zweite Schnittstelle zwischen HTML und dem JavaScript-Code sind die Pseudo-Links in den li- Elementen, welche eine untergeordnete ul-Liste enthalten. Zur Erinnerung nochmals der Beispielauszug:

<li id="faunawelt_intern">
<a class="folder" onclick="toggle('faunawelt_intern',true)">
<img src="opened.gif" alt="" id="img_faunawelt_intern">
FAUNA-WELT intern</a>
<ul id="ul_faunawelt_intern" class="opened">
...
</ul>
</li>

Im Event-Handler onclick= wird toggle() aufgerufen. Dabei wird als erster Parameter der id-Name des li-Elements übergeben und als zweiter der Wert true. Der zweite Parameter bestimmt, ob toggle() den aktuellen Menüzustand in window.name speichern lassen soll oder nicht. In init_nav() wird toggle() mit false aufgerufen. In diesem Fall wird nichts gespeichert. Da beim Anklicken von Ordner-Links jedoch eine vom Anwender bewirkte Zustandsveränderung im Menü eintritt, wird true übergeben, damit der neue Zustand gespeichert wird.

Die Funktion toggle() greift auf zwei Elemente zu: auf das ul-Element des untergeordneten Teilbaums und auf die Grafikreferenz, die je nach Aufklappzustand des Teilbaums entweder ein geöffnetes oder ein geschlossenes Ordnersymbol darstellen soll. Da sie als ersten Parameter den id- amen des den Teilbaum öffnenden li-Elements übergeben bekommt, kann sie auf Basis der vereinbarten Regel durch Voranstellen von ul_ bzw. img_ die id-Namen der betroffenen Elemente selbst ermitteln. Das Herzstück des Auf-/Zuklappeffekts ist das if-else-Konstrukt innerhalb von toggle(). Ist der aktuelle Klassenname des inneren ul-Elements opened, wird er in closed geändert, und andernfalls umgekehrt: closed wird zu opened. Da der Klasse closed in CSS mit display:none zugewiesen wurde, verschwindet die Anzeige des Teilbaums, sobald diese Klasse zugewiesen ist. Damit sich auch das Ordnersymbol entsprechend ändert, wird durch Zuweisen einer anderen Grafik an das src-Attribut der Grafikreferenz im öffnenden li-Element der Klappeffekt zusätzlich visualisiert.

Die Funktionen save_nav() und load_nav() haben wie schon erwähnt nichts unmittelbar mit der Funktionalität des Auf-/Zuklappeffekts zu tun. In save_nav() besorgt eine for- Schleife die Zuweisung von id-Namen zu aktuellen Klassennamen und fügt die Einzelwerte durch Kommata getrennt zu einer Zeichenkette zusammen. Diese wird am Ende in window.name gespeichert. In load_nav() wird window.name wieder ausgelesen und die darin gespeicherte Zeichenkette wird durch Anwendung der Zeichenkettenmethode split() wieder in ihre Einzelwerte zerlegt. Ähnlich wie in toggle() werden die ermittelten Klassennamen den zugehörigen, über id-Namen ermittelten Elementen zugewiesen, jedoch nicht nur einem einzigen Element, sondern allen Elementen des Menüs. Auf diese Weise wird nach Aufruf einer anderen Seite der Menüzustand wiederhergestellt, der nach Verlassen der letzten Seite aktuell war.

Fazit
Das Beispiel zeigt, dass man in Zeiten des DOM nicht mehr viel JavaScript benötigt und außerdem noch ein sauberes HTML-Markup einsetzen kann, um die allseits beliebten Baumnavigationen zu realisieren.


 

 

Das Tutorial ist ein Auszug aus dem Buch von Stefan Münz:

Professionelle Websites - Programmierung, Design und Administration von Webseiten
Addison-Wesley, 2. Auflage, 1136 Seiten, gebunden, komplett in Farbe, mit DVD

Die Veröffentlichung des Kapitels erfolgt mit freundlicher Genehmigung von
Pearson Education.

Mehr Informationen zu diesem wunderbaren Fachbuch für Webmaster und Webentwickler
gibt es hier: Professionelle Websites

Alle Teile des Buches: 

1 Intro
2 HTML und CSS
3 Dynamische Seiten mit JavaScript/DOM
4 Die Server-Seite
5 PHP und MySQL
6 XML
7 Betrieb von Websites
8 Referenz
Bilder

DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von MaoMao
  • 09.01.2013 - 17:02

Gute Tutorial leicht erklärt.

x
×
×