1. Page d'accueil
  2. Tutoriels JavaScript

Créer un menu "accordéon" avec jQuery

Le 07-11-2007 par Collectif Alsacreations dans Tutoriels JavaScript.

Le but de ce tutoriel est de transformer le menu HTML du chapitre suivant en un menu "accordéon". Un menu "accordéon" est un menu déroulant un peu particulier, dont les sous-menus s'ouvrent au clic de souris (ou au focus).
Pour cela, on va bien sûr utiliser JavaScript, mais en se basant sur la bibliothèque jQuery. J'ai utilisé la version 1.2.1 de jQuery, la plus récente au moment d'écrire ces lignes.

Améliorer l'ergonomie

Sommaire

  1. Introduction
  2. La base HTML
  3. Le code JavaScript
  4. Les styles CSS
  5. Améliorer l'ergonomie
  6. Conclusion

Marquer les "éléments déclencheurs"

Pour améliorer l'ergonomie du menu, on va faire en sorte de distinguer les liens qui déclenchent le déroulement d'un sous-menu des autres. Et dans la foulée, on va aussi distinguer ceux qui permettent de cacher un sous-menu.

Pour cela, il nous suffit d'ajouter une classe aux éléments de liste dans lesquels il y a un sous-menu ouvert. On pourra en effet modifier l'apparence de cet élément à l'aide des styles. Les autres éléments contenant un sous-menu sont déjà connus, ils portent tous la classe toggleSubMenu !

Donc, en résumé, lorsqu'on ouvre le sous-menu, il faut ajouter une classe (par exemple "open"), et lorsqu'on le referme, il faut la supprimer. Il faudra aussi supprimer cette classe si elle existe pour un autre sous-menu.

jQuery possède deux méthodes, addClass() et removeClass(), qui vont faire la majorité du travail à notre place :

<script type="text/javascript" src="jquery-1.2.1.js"></script>    


<script type="text/javascript">
<!--
$(document).ready( function () {
    // On cache les sous-menus :
    $(".navigation ul.subMenu").hide();
    // On sélectionne tous les items de liste portant la classe "toggleSubMenu"
    // et on remplace l'élément span qu'ils contiennent par un lien :
    $(".navigation li.toggleSubMenu span").each( function () {
        // On stocke le contenu du span :
        var TexteSpan = $(this).text();
        $(this).replaceWith('<a href="" title="Afficher le sous-menu">' + TexteSpan + '<\/a>') ;
    } ) ;

    // On modifie l'évènement "click" sur les liens dans les items de liste
    // qui portent la classe "toggleSubMenu" :
    $(".navigation li.toggleSubMenu > a").click( function () {
        // Si le sous-menu était déjà ouvert, on le referme :
        if ($(this).next("ul.subMenu:visible").length != 0) {
            $(this).next("ul.subMenu").slideUp("normal", function () { $(this).parent().removeClass("open") });
        }
        // Si le sous-menu est caché, on ferme les autres et on l'affiche :
        else {
            $(".navigation ul.subMenu").slideUp("normal", function () { $(this).parent().removeClass("open") });
            $(this).next("ul.subMenu").slideDown("normal", function () { $(this).parent().addClass("open") });
        }
        // On empêche le navigateur de suivre le lien :
        return false;
    });
} ) ;
// -->

</script>

Il suffit maintenant de styler li.open et li.toggleSubMenu différemment grâce aux CSS.

Garder un sous-menu ouvert

Lorsque le visiteur clique sur un des "vrais" liens du menu, il est normalement envoyé sur une autre page. Résultat, la page est rechargée, et le sous-menu dans lequel l'utilisateur naviguait n'apparait plus, il a été fermé.

Il est possible de le garder ouvert après un changement de page, mais on va avoir besoin d'intervenir directement sur le code HTML.

Si votre site est statique, il suffit d'ajouter à la main une classe (par exemple "open_at_load") sur le sous-menu que vous voulez garder ouvert (en fonction de la page). Pour les sites dynamiques, il est aussi possible de générer cette classe, en fonction d'une variable $_GET['page'] ou autre.

Dès lors, il suffit de dire au script de fermer tous les sous-menus au chargement, sauf celui qui porte la classe "open_at_load" :

<script type="text/javascript" src="jquery-1.2.1.js"></script>    
<script type="text/javascript">
<!--
$(document).ready( function () {
    // On cache les sous-menus
    // sauf celui qui porte la classe "open_at_load" :
    $(".navigation ul.subMenu:not('.open_at_load')").hide();
    // On sélectionne tous les items de liste portant la classe "toggleSubMenu"

    // et on remplace l'élément span qu'ils contiennent par un lien :
    $(".navigation li.toggleSubMenu span").each( function () {
        // On stocke le contenu du span :
        var TexteSpan = $(this).text();
        $(this).replaceWith('<a href="" title="Afficher le sous-menu">' + TexteSpan + '<\/a>') ;
    } ) ;

    // On modifie l'évènement "click" sur les liens dans les items de liste
    // qui portent la classe "toggleSubMenu" :
    $(".navigation li.toggleSubMenu > a").click( function () {
        // Si le sous-menu était déjà ouvert, on le referme :
        if ($(this).next("ul.subMenu:visible").length != 0) {
            $(this).next("ul.subMenu").slideUp("normal", function () { $(this).parent().removeClass("open") } );
        }
        // Si le sous-menu est caché, on ferme les autres et on l'affiche :
        else {
            $(".navigation ul.subMenu").slideUp("normal", function () { $(this).parent().removeClass("open") });
            $(this).next("ul.subMenu").slideDown("normal", function () { $(this).parent().addClass("open") } );
        }
        // On empêche le navigateur de suivre le lien :
        return false;
    });

} ) ;
// -->

</script>

Passer au chapitre suivant : Conclusion

  • Réussir son site web avec XHTML et CSS
  • CSS : Le guide complet
  • Memento CSS
  • Memento XHTML