|
|
|
|
Daniel Thoma:
|
|
|
|
|
|
|
| E-Mail: |
|
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!
|
|
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é.
|
|
<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>
|
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é.
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.
É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).
|
|
Les adresses qui suivent sont recommandées pour mieux comprendre les exemples ci-dessus ou pour approfondir et apprendre d'autres possiblités.
SELFHTML: Référence objet JavaScript
Articles spécialisés: Passation de valeurs JavaScript entre différents documents HTML
W3C: DOM 2 spécifications Events: Definition de l'interface Event
W3C: HTML 4 Spécifications: attributs de classe
|
|
|
|
© 2001-2005
Informations