Neues Navigationsmenü

Inhaltsverzeichnis

 

1. Funktionsbeschreibung Inhalt

Heute hab ich der Seite einmal eine bessere Navigation verpaßt. Zwar gibt ja schon sehr viele Navigationsplugins, aber trotz zweitägiger Suche habe keines gefunden, das folgende Funktionalitäten ermöglicht:

  1. Es werden in jedem Nav-Baum (Seiten, Kategorien, usw.) beim Laden der Seite nur die Ebene1-Elemente angezeigt.
  2. Sollte ein Element „Kinder“ haben, so muss das irgendwie kenntlich gemacht werden (z.B. ein „Plus“-Icon).
  3. Wenn ich mit der Maus über ein solches Eltern-Element drüberfahre, sollen sich die Kinder der nächsten Ebene aufklappen. Ich möchte nicht erst noch auf das Eltern-Element klicken müssen, das behindert die Navigation. Drüberfahren muss reichen.
  4. Die beschriebene Funktion sollte möglichst bei allen Elementen (also auch in der 5. Ebene) funktionieren.
  5. Optional: Wenn möglich ohne Javascript

Nun ja, folgendes kam dabei heraus: WordPress ordnet die Navigation mittels Unordered Lists (<ul>-Tag) und verpaßt den Elementen in der Sidebar unterschiedliche CSS-Klassen.

  • Jede Ebene ist für sich in ein <ul>-Tag sortiert, die Liste enthält als <li> alle Navigationspunkte der jeweiligen Ebene (also ein UL für Ebene 1, je eines für Ebene 1.1 und 1.2, usw.)
  • Die <ul> der Kinder-Ebene wird innerhalb des <li>-Tags der Elternebene plaziert.
  • Es haben alle Nav-Punkte z.B. der „Seiten“-Navigation mindestens die CSS-Klasse „page_item“ und „page-item-$id“ (beachte den Unterschied im Trennzeichen: Underscore „_“ und Minus „-„!). Im Blog-Menü lauten sie entsprechend „cat_item“ und „cat-item-$id“.

2. CSS-Teil Inhalt

Wir können das Aufklappen und den aufgeklappten Baum beim neu laden der Seite also alleine über CSS ohne JavaScript lösen:

/* PAGES Allgemein */
.page_item a { display:inline; } /* Um die Bilder in die gleiche Zeile zu rutschen */
.page_item ul { list-style:none; } /* keine Bullets vor irgendwelchen Listen */
.page_item ul li { list-style:none; } /* same here */
/* -- */

/* CSS::Aufklappen Ebene 1 */
/* Anmerkung zu CSS: Leider wirken sich die nächsten drei Zeilen
auf *alle* Knoten aus, egal wie verschachtelt sie sein mögen.
Deswegen müssen wir weiter unten für jeden der drei Fälle hier
noch spezifizieren, dass eine Ebene weiter drunter eben *nicht*
eingeblendet werden soll.
Oder anders: Hier wird der gesamte Baum eingeblendet; weiter
unten blenden wir die Kinder wieder aus. */
.page_item ul { display:none; } /* Alle Unterebenen per default zugeklappt */
.page_item:hover ul { display:inherit; } /* beim Hovern einblenden */
.page_item:hover img { display:none; } /* Plus ausblenden */

/* CSS::Aufklappen Ebene 2 */
.page_item ul li img { display:inline; }
.page_item:hover ul li ul { display:none; }
.page_item:hover ul li img { display:inline; } /* Plus ausblenden */

/* CSS::Aufklappen Ebene 3 */
.page_item ul li ul { display:none; }
.page_item ul li:hover ul {	display:inherit; }
.page_item ul li:hover img {	display:none; }

/* CSS::Erhalten Ebene 1 */
.current_page_item ul { display:inherit; }
.current_page_item img { display:none; }

/* CSS::Erhalten Ebene 2 */
.current_page_ancestor ul { display:inherit; }
.current_page_ancestor img { display:none; }

/* CSS::Erhalten Ebene 2 */
.current_page_ancestor ul li.current_page_ancestor ul { display:inherit; }
.current_page_ancestor ul li.current_page_ancestor img { display:none; }

CSS-Klassen werden nicht rekursiv angewendet, deswegen ist es unbedingt erforderlich, jeden möglichen Pfad im Baum mit Klassen zu versehen. Ich habe dies oben für die Seiten-Navigation mit maximal drei Ebenen erledigt.

Sollte der Benutzer nun vom Eltern-Element wegfahren, um zu einem Kind-Element zu gelangen, so macht das nichts, er ist ja immer noch über dem allumspannenden <li>-Tag drüber. Das Menü bleibt also aufgeklappt.

3. JavaScript-Teil Inhalt

Leider gibt WordPress in einer Ebene nicht aus, ob sich noch Kinder darin befinden. Es ist mir also nicht gelungen, das Plus-Icon oder einen Text alleine auf CSS basierend an das <a>-Tag zu hängen. Meine Idee wäre gewesen, dem <ul>-Tag der Kind-Ebene ein neues Element voranzustellen:

.page_item ul:before {
  content:url("img/plus.gif");
}

Leider wertet der Browser das insofern korrekt aus, als dass der den Content anzeigt, aber nur, wenn das Element sichtbar ist (display=’inherit‘). Außerdem ist das CSS2-Funktionalität, die im Internet-Explorer nicht funktioniert.

Ich komme deswegen nicht um JavaScript-Benutzung:

function addPlussesToTree() {
  var navTree = document.getElementById("sidebar");
  if (!navTree) { return; }
  var myLiTags = navTree.getElementsByTagName("li");
  if (!myLiTags) { return; }
  for (i=0; i<myLiTags.length; i++) {
    if (myLiTags[i].innerHTML.indexOf("<ul")>-1) {
      var imgEl = document.createElement("img");
      imgEl.src = '<?php bloginfo('stylesheet_directory'); ?>/images/icon_plus.gif';
      imgEl.border = "0";
      myLiTags[i].insertBefore(imgEl, myLiTags[i].getElementsByTagName("ul")[0]);
    }
  }
}
addPlussesToTree();

Innerhalb des if-Statements kann eingebaut werden, wie und wo die Information über vorhandene Kindknoten erscheinen soll; bei mir eben nach dem Link als Plus-Icon.

Ich habe dieses Script in meine footer.php meines Themes eingebaut, nachdem ich den absoluten Pfad zu den Images brauche und ich das Script deswegen einmal durch den PHP-Parser schicken muss. JavaScript-Dateien (*.js) nimmt der nämlich nicht.

Falls ein User JavaScript ausgeschaltet hat, so macht das nichts, er sieht eben dann die Plus-Zeichen nicht. Anregungen oder Fragen gerne in die Kommentare…

Bislang keine Kommentare vorhanden.

Einen Kommentar hinterlassen