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.

Le code JavaScript

Sommaire

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

Intégrer jQuery

La première chose à faire pour pouvoir utiliser jQuery est bien évidemment d'appeller la librairie dans la page. Téléchargez jQuery sur le site officiel, et placez-le dans le répertoire (ou dans un sous-répertoire) où vous avez enregistré le fichier HTML.

Nous allons insérer l'appel au fichier jQuery dans la balise head, comme décrit dans ce point de la FAQ :

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

Dorénavant, on peut accéder aux méthodes de la bibliothèque jQuery dans tout le reste de la page.

Cacher les sous-menus

On veut que les sous-menus soient cachés au chargement de la page, lorsque le visiteur n'a encore actionné aucun élément du menu. Grâce à jQuery et ses sélecteurs utilisant la syntaxe CSS, c'est très simple :

<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();    
} ) ;
// -->
</script>    

On aurait évidemment pu cacher les sous-menus en appliquant la propriété CSS display: none, mais cette façon de faire rend le menu inutilisable pour les utilisateurs qui ne disposent pas de JavaScript ou qui l'ont désactivé.

Transformer les span en liens

Il est possible de faire réagir les éléments de liste au clic pour faire apparaître les sous-menus, comme n'importe quel élément HTML. Le problème est que les éléments de liste ne captent pas le focus lorsque l'utilisateur navigue au clavier, contrairement aux liens.

Evidemment, on pourrait utiliser directement un lien, avec un attribut href vide. Mais dans ce cas, on se retrouve avec un lien inutile si JavaScript est désactivé.

Pour obtenir un résultat aussi accessible et ergonomique que possible (pour un menu déroulant), j'ai choisi de générer des liens à l'aide de JavaScript. Ainsi, le code HTML reste propre et le menu devient utilisable au clavier.

<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>') ;
    } ) ;    

} ) ;
// -->
</script>    

Gérer l'affichage des sous-menus

Il faut maintenant que les sous-menus se déroulent lorsque l'on clique sur les liens. On va utiliser un des effets graphique fournis par jQuery, via la fonction slideToggle, qui fera apparaitre/disparaitre les sous-menus en augmentant/reduisant progressivement leur hauteur.

Il y a deux cas de figure qui peuvent se présenter lorsque l'utilisateur clique sur un lien :

  • soit le sous-menu correspondant est ouvert, et on doit simplement le replier ;
  • soit le sous-menu est fermé. Dans ce cas, il faut afficher le sous-menu correspondant et fermer les autres sous-menus.

Il n'est pas difficile de réaliser qu'en procédant de cette manière, il n'y aura jamais plus d'un seul sous-menu affiché, puisqu'à chaque fois qu'on en ouvre un, on referme les autres ! Combinée avec les effets de "slideUp" et "slideDown", cette méthode donnera l'effet "d'accordéon" recherché.

Voici le code modifié :

<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");
        }
        // Si le sous-menu est caché, on ferme les autres et on l'affiche :
        else {
            $(".navigation ul.subMenu").slideUp("normal");
            $(this).next("ul.subMenu").slideDown("normal");
        }
        // On empêche le navigateur de suivre le lien :
        return false;
    });    


} ) ;
// -->
</script>    

Plusieurs points intéressants à creuser ici, et notamment :

Et voilà, le menu est d'ores et déjà fonctionnel ! Mais il est encore largement perfectible ...

Passer au chapitre suivant : Les styles CSS

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