Niveau Niveau confirmé

Créer un menu déroulant “accordéon” avec jQuery

Tutorieljavascript

Publié par le , mis à jour le (180017 lectures)

javascript jquery

Améliorer l'ergonomie

Améliorer l'ergonomie

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="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.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="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.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>