Home A propos du site [Joomla] Menu Accordéon avec jQuery

Menu principal

Informatique

Mathématiques

[Joomla] Menu Accordéon avec jQuery
Site - Site
Écrit par Arnaud Kientz   

accordeon

 

Il existe plusieurs bibliothèques JavaScript si l'on désire créer quelques effets visuels rapidement sur un site. La première avec laquelle j'ai travaillé est Scriptaculous, basée sur Prototype, Joomla travaille quant à lui avec Mootools, et j'ai récemment découvert jQuery qui me parait plus puissant, plus maléable et moins lourd que scriptaculous.

 

Avec autant de scripts, les pages de ce site ce sont trouvées chargées, beaucoup trop chargées, et il a fallu faire un choix, quitte à travailler un peu.

Mon choix s'est porté sur JQuery. Si la modification des effets visuels créés avec Scriptaculous était simple, c'était une autre paire de manches avec l'intégration pour Joomla et l'excellent plugin fboxbot.

 

 

Je vais décrire ici comment créer un menu accordéon avec une petite fonction JavaScript. Il suffit de cliquer sur le menu de gauche pour voir le résultat de ce script, avec évidemment mes propres adaptations CSS. Premier réflexe, avant de vouloir réinventer la roue, une petite recherche m'indique qu'il existe déjà pour cela le module SBD Accordeon, mais je ne l'ai trouvé ni pratique, ni à mon goût.

 

Me voilà donc en train d'apprendre jQuery pour réaliser mon petit script de menu accordéon.

Premièrement, ce script fonctionne pour un menu créé avec Joomla, avec des éléments de sous-menus. Les liens "parents" n'auront comme seule tâche d'activer le sous-menu associé, et les autres liens fonctionnent tout à fait normalement.

Il est important que l'intégralité du menu soit chargé pour chaque page, et donc dans les options du module associé aux menus, il faut cocher "Oui" pour "Toujours afficher les sous-menus" :

 

module_menu

 

Ensuite, il faut télécharger jQuery à cette adresse ( en version 1.4.2 au moment où j'écris ces lignes ), le mettre dans le dossier de votre template Joomla, et dans le fichier index.php du template, insérer le lien vers ce script :

 

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

 

N'hésitez pas à utiliser les versions minifiées de jQuery, afin de réduire la taille de vos pages ( hé oui, tout le monde n'a pas l'ADSL ), et pour la bonne santé de votre bande passante, surtout si vous avez beaucoup de trafic.

 

Le script ci-dessous est un script adaté de l'excellent tutoriel Menus Accordéons du site Alsacréations.

Ceci étant, voici le code à insérer dans le fichier index.php du template, ou via un script JavaScript externe ( attention tout de même car il comporte deux petites erreurs, voir la fin de l'article ) :

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$(document).ready( function () {
 
// Cacher les sous-menus : ce sont des blocs enfants des classes "parent" de Joomla
$(".parent ul").hide();
 
// Si vous voulez que le sous-menu reste ouvert, suite à un clic sur un lien de ce sous-menu,
// il faut ajouter la ligne suivante :
$(".active ul").show();
 
// On associe une nouvelle action au clic sur un lien "parent"
$("ul.menu li.parent > a").click( function () {
 
// Si le sous-menu n'est pas visible, c'est-à-dire si il ne possède pas la classe "open",
// on referme tous les autres sous-menus, et on l'ouvre en slide.
// Les menus fermés perdent leur classe "open", et le menu ouvert l'obtient.
if (!$(this).parent().hasClass("open")) {
$("ul.menu li ul").slideUp("normal", function () { $(this).parent().removeClass("open") });
$(this).next("ul").slideDown("normal", function () { $(this).parent().addClass("open") } );}
 
// Sinon, c'est que le sous-menu est déjà ouvert, et dans ce cas on le referme en slide
// en supprimant sa classe "open".
else {$(this).next("ul").slideUp("normal", function () { $(this).removeClass("open") });}
 
 
// On empêche de suivre les liens créant les sous-menus
return false;
});
 
} ) ;

 


 

 

Petites variations pour la gestion des événements ou des effets :

  • On voit à la ligne 11 que l'action est lancée par un "clic". En remplaçant "click" par "mouseover", le menu se déroule par un survol de souris. Il y a encore d'autres événements possibles, mais pour cela je vous laisse lire un peu la documentation de jQuery.
  • L'effet visuel utilisé ici est le "slide". On peut également utiliser l'effet "fade" ( apparition par opacité, mais c'est moins joli dans ce cas que le slide ) en remplaçant slideUp et slideDown respectivement par fadeOut et fadeIn. Encore mieux : on peut définir sa propre animation grâce à animate ( enfin mieux, ça dépend de ce que chacun peut inventer... ).

 

 

Et si il y a plusieurs niveaux ?


Par défaut, ce script fonctionne pour des menus ne comprenant qu'un seul niveau de sous-menus, puisqu'étant initialement prévu simplement pour mon site. Une demande a été formulée pour qu'il soit également valable dans le cas d'une hiérarchie multiple. Dans ce cas, il faut modifier la ligne :

 

 

$(".active ul").show();

 

 

qui s'occupe d'afficher la liste "ul" en cours, par :

 

 

$("#current").parents("ul").show(); 

 

 

"#current" désigne dans la classe CSS de Joomla le lien vers la page que vous avez devant vos yeux.

Si votre menu comporte plusieurs niveaux de sous-menus, il va falloir montrer ( show() ) la liste "ul" parent de niveau le plus haut, et accessoirement montrer tous les niveaux "ul" supérieurs. La méthode "parents("ul") désigne rapidement tous ces parents de la forme "ul".

En conclusion, cette ligne devrait permettre d'afficher tous les parents de la forme "ul" du lien courant.

Je reste au conditionnel, car cela fonctionne avec le code de test que j'avais. Merci de me faire parvenir vos retours si cela ne devait pas fonctionner chez vous.

 

Voici le code complet de la variante "multi-niveaux" :

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$(document).ready( function () {

$(".parent ul").hide();
$("#current").parents("ul").show();

$("ul.menu li.parent > a").click( function () {

if ($(this).next("ul:visible").length != 0) {
$(this).next("ul").slideUp("normal", function () { $(this).parent().removeClass("open") } );
}

else {
$("ul.menu ul").slideUp("normal", function () { $(this).parent().removeClass("open") });
$(this).next("ul").slideDown("normal", function () { $(this).parent().addClass("open") } );
}

return false;
});

} ) ;

 

 

A propos des conflits avec d'autres librairies ( notamment mootools... ) :

 

Haaaaaa, ce serait bien si tout en informatique pouvait directement fonctionner sans effort. Sauf que c'est rarement le cas.

Joomla utilise la librairie javascript mootools, et il se peut qu'il y ait des conflits, tout simplement parque les deux librairies utilisent les mêmes "raccourcis". Le résultat est simple : le menu ne marche pas.

Pour un script aussi simple que le menu accordéon, il suffit simplement de remplacer chaque dollar ( l'origine du malentendu entre les deux librairies ) par le terme jQuery, ce qui donne :

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
jQuery(document).ready( function () {
 
jQuery(".parent ul").hide();
 
jQuery(".active ul").show();
 
jQuery("ul.menu li.parent > a").click( function () {
 
 
if (!jQuery(this).parent().hasClass("open")) {
jQuery("ul.menu li ul").slideUp("normal", function () { jQuery(this).parent().removeClass("open") });
jQuery(this).next("ul").slideDown("normal", function () { jQuery(this).parent().addClass("open") } );}
 
else {jQuery(this).next("ul").slideUp("normal", function () { jQuery(this).removeClass("open") });}
 
return false;
});
 
} ) ;

 

 

Problèmes et erreurs :

 

Brice Boucart s'est intéressé d'une manière plus appronfondie à ce code et a décelé deux problèmes, je le cite :

 

  • "Le premier problème que j'ai repéré survient lorsque l'on clique sur un élément parent que l'on a déjà déplié et replié : en effet, au troisième clic (le premier pour déplier le menu, le second pour le replier), rien ne se passe alors que le menu devrait se déplier à nouveau. Il s'avère en fait que la classe open que le script attribue au menu déplié n'est pas retirée lorsque l'on clique sur le même menu pour le replier (pas de problème lorsque l'on clique sur un autre menu parent)."
  • "Le second problème survient lorsque l'on rafraîchit la page ou que l'on clique sur un des éléments du menu ouvert et donc que l'on charge une nouvelle page ; en effet, dans ces cas-là, le menu contenant l'élément correspondant à la page que l'on affiche est bien déplié (grâce à la cinquième ligne du script initial) mais l'élément parent ne présente plus la classe open, ce qui est problématique si l'on souhaite replier ce menu ou lorsque l'on désire « marquer » le menu déplié en utilisant des propriétés CSS appliquées à l'élément possédant la classe open."
Il donne également les solutions à ces problèmes sur la page où il décrit l'implémentation de ce code dans son joomla. Je le remercie vivement de m'avoir contacté pour me tenir informé de ces problèmes.

Pour les paresseux comme moi, je vous livre la version finale corrigée :

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$(document).ready( function () {
    $(".parent ul").hide();
    $(".active ul").show();
    $(".active").addClass("open");
 
    $("ul.menu li.parent > a").click( function () {
 
        if (!$(this).parent().hasClass("open")) {
            $("ul.menu li ul").slideUp("normal", function () { $(this).parent().removeClass("open") });
            $(this).next("ul").slideDown("normal", function () { $(this).parent().addClass("open") } );}
 
        else {$(this).next("ul").slideUp("normal", function () { $(this).parent().removeClass("open") });}
        return false;
    });
} ) ;

 


 

Enfin un avis perso : le site officiel de jQuery dont je donne le lien plus haut est très complet, et propose bon nombre de plugins intéressants, mais pour les bases, j'ai préféré lire la documentation la page de developpeur-web2, que je trouve plus lisible.

Au cas où certains d'entre vous aimeraient s'y mettre....Complice

Mise à jour le Mercredi, 11 Août 2010 21:40