SELFHTML

Daniel Thoma:
Menu déroulant

Page d'information: vue d'ensemble

vers le bas Daniel Thoma
vers le bas Remarques sur le sujet
vers le bas Exemple avec explications
vers le bas Liens contextuels

vers le bas 

Daniel Thoma

E-Mail: adresse électronique dthoma@gmx.net

Il s'agit ici d'un article traduit de l'allemand par la rédaction de SELFHTML actuel. Veuillez poser vos questions relatives à cet article uniquement à son auteur, prenant compte que celui-ci ne maîtrise peut-être pas la langue française!

vers le hautvers le bas 

Remarques sur le sujet

Il est déjà possible sur la toile de trouver d'innombrables menus DHTML offrant une structure arborescente déroulante. La plupart d'entre eux sont cependant compliqués et manquent de souplesse.
Le script présenté ici veut éviter ces écueils en organisant le menu complètement avec HTML, et en ne réalisant en JavaScript que le nécessaire traitement d'événement.
Ainsi le menu peut-il être adapté presqu'à volonté et reste utilisable même quand JavaScript est désactivé.

vers le hautvers le bas 

Exemple avec explications

Popup-Seite Exemple d'affichage: aperçu

<html>
<head>
<title>Exemple</title>
<script type="text/javascript">
  /*
   * Ajoute les gestionnaires d'événement et classes CSS
   aux éléments de liste, pour fermer les points du menu au départ.
   *
   * menu: référence à la liste
   * data: chaîne qui contient les numéros des points déroulés du menu, .
   */
  function treeMenu_init(menu, data) {
    var array = new Array(0);
    if(data != null && data != "") {
      array = data.match(/\d+/g);
    }
    var items = menu.getElementsByTagName("li");
    for(var i = 0; i < items.length; i++) {
      items[i].onclick = treeMenu_handleClick;
      if(!treeMenu_contains(treeMenu_getClasses(items[i]), "treeMenu_opened")
          && items[i].getElementsByTagName("ul").length
            + items[i].getElementsByTagName("ol").length > 0) {
        var classes = treeMenu_getClasses(items[i]);
        if(array.length > 0 && array[0] == i) {
          classes.push("treeMenu_opened")
        }
        else {
          classes.push("treeMenu_closed")
        }
        items[i].className = classes.join(" ");
        if(array.length > 0 && array[0] == i) {
          array.shift();
        }
      }
    }
  }

  /*
   * Modifie la classe d'un point du menu qui a été cliqué, de sorte que les points du menu ouverts
   * puissent être fermés et que les point fermés puissent être ouverts.
   *
   * event: l'objet Event transmis par le navigateur.
   */
  function treeMenu_handleClick(event) {
    if(event == null) { //solution de rechange pour les propriétés DOM faisant défaut dans l'IE
      event = window.event;
      event.currentTarget = event.srcElement;
      while(event.currentTarget.nodeName.toLowerCase() != "li") {
        event.currentTarget = event.currentTarget.parentNode;
      }
      event.cancelBubble = true;
    }
    else {
      event.stopPropagation();
    }
    var array = treeMenu_getClasses(event.currentTarget);
    for(var i = 0; i < array.length; i++) {
      if(array[i] == "treeMenu_closed") {
        array[i] = "treeMenu_opened";
      }
      else if(array[i] == "treeMenu_opened") {
        array[i] = "treeMenu_closed"
      }
    }
    event.currentTarget.className = array.join(" ");
  }

  /*
   * Renvoie toutes les classes affectées à un élément HTML
   *
   * element: l'élément HTML
   * return: les classes affectées
   */
  function treeMenu_getClasses(element) {
    if(element.className) {
      return element.className.match(/[^ \t\n\r]+/g);
    }
    else {
      return new Array(0);
    }
  }

  /*
   * Vérifie si un tableau contient un élément déterminé.
   *
   * array: le tableau
   * element: l'élément
   * return: true, si le tableau contient l'élément.
   */
  function treeMenu_contains(array, element) {
    for(var i = 0; i < array.length; i++) {
      if(array[i] == element) {
        return true;
      }
    }
    return false;
  }

  /*
   * Renvoie une chaîne de caractères dans laquelle figurent tous les
   * points du menu ouverts.
   *
   * menu: référence à la liste
   * return: la chaîne de caractères
   */
  function treeMenu_store(menu) {
    var result = new Array();;
    var items = menu.getElementsByTagName("li");
    for(var i = 0; i < items.length; i++) {
      if(treeMenu_contains(treeMenu_getClasses(items[i]), "treeMenu_opened")) {
        result.push(i);
      }
    }
    return result.join(" ");
  }
</script>
<style type="text/css">
  li.treeMenu_opened ul {
    display: block;
  }
  li.treeMenu_closed ul {
    display: none;
  }
</style>
<body onload="treeMenu_init(document.getElementById('menu'), '')">
<ul id="menu">
  <li>Premièrement
    <ul>
      <li>A</li>
      <li>B</li>
    </ul>
  </li>
  <li>Deuxièmement
    <ul>
      <li>a</li>
      <li>b</li>
    </ul>
  </li>
</ul>
</body>
</html>

Explication:

Avec onload="treeMenu_init(document.getElementById('menu'), '')", la fonction d'initialisation est appelée après le chargement de la page. Ce faisant, une référence à l'élément comportant l'Id "menu" lui est transmise.
Cette fonction ajoute à chaque élément li la classe treeMenu_closed, si la classe treeMenu_opened ne lui est pas déjà affectée et qu'il ne contient pas une sous-liste.
Par ailleurs un gestionnaire d'événement onClick est ajouté à chaque élément li, de façon à appeler la fonction treeMenu_handleClick lorsqu'il est cliqué.

La fonction handleClick(event) ne fait que remplacer la classe treeMenu_closed par la classe treeMenu_opened et inversement, de sorte qu'un point du menu fermé s'ouvre lorsqu'il est cliqué et qu'un point ouvert soit refermé.

Enregistrer l'état du menu et le rétablir

La fonction treeMenu_store(menu) renvoie une chaîne de caractères qui décrit l'état actuel du menu. La chaîne de caractères contient les numéros des éléments du menu qui sont ouverts.
Avec onunload="window.name = treeMenu_store(document.getElementById('menu'))" on peut ainsi enregistrer l'état du menu lorsque l'on quitte la page.
Cette chaîne de caractères peut être transmise en deuxième paramètre à la fonction treeMenu_init(menu, data). Avec onload="treeMenu_init(document.getElementById('menu'), window.name)", il est alors possible de rétablir l'état du menu sur une autre page ou après une actualisation.

Attention:

Étant donné que le menu ne se ferme qu'au chargement de la page, il reste tout simplement ouvert lorsque JavaScript est désactivé.

L'attribut class peut contenir plusieurs classes. De ce fait des classes peuvent être affectées aux éléments li quand on utilise le script. L'attribut class n'est pas écrasé, mais les classes treeMenu_closed et treeMenu_opened sont remplacées l'une par l'autre.

Une référence à une liste énumérative ou numérotée (ol/ul) doit être transmise à la fonction treeMenu_init.

Il ne pose aucun problème de créer plusieurs menus en appelant plusieurs fois treeMenu_init(menu, data).

vers le hautvers le bas 

Liens contextuels

Les adresses qui suivent sont recommandées pour mieux comprendre les exemples ci-dessus ou pour approfondir et apprendre d'autres possiblités.

Page d'information: connexion exigée SELFHTML: Référence objet JavaScript
Page d'information: connexion exigée Articles spécialisés: Passation de valeurs JavaScript entre différents documents HTML
Page en langue anglaise W3C: DOM 2 spécifications Events: Definition de l'interface Event
Page en langue anglaise W3C: HTML 4 Spécifications: attributs de classe

vers le haut

© 2001-2005 Seite Informations