Menu dépliant (liste, CSS et jquery)

Faire un menu dynamique en s’appuyant sur les standards en vigueur et jQuery

Un menu déroulant / dépliant exploitant jquery, css et les listes (ul, li).

But

À ceux qui me diront : « Mais pourquoi une éniéme contrib sur les menus déroulant ? », je répondrais : « Parce que ».

Plus sérieusement, il se trouve que les contrib (à mon sens) n’exploitent pas jusqu’au bout les listes, ni jquery. Jquery est maintenant intégré dans SPIP, ce qui offre pas mal de petits agréments concernant l’exploitation de javascript.

Références

Je vous invite à lire, dans un premier temps, l’ensemble des travaux listés dans rubrique 379 et Gestion des menus.

Puis pour les tenaces :
-  http://be.twixt.us/jquery/treeViewH...
-  http://jquery.bassistance.de/treeview/

Contraintes de travail

Parmi les contraintes que je me suis imposées, il y a :
-  avoir un rendu minimal acceptable sur l’ensemble des navigateurs
-  être exploitable dans le maximum de contexte (navigation, plan de site, ...)
-  n’utiliser que jquery (pas d’import de script extérieur), (code non intrusif)
-  n’utiliser que des liste (ul,li) mais pas de div ou a

Conséquence

Parmi les effets de bords désagréables, la version initiale n’est pas compatible avec Internet Explorer. Entre autre du fait que ce navigateur ne gére pas l’évènement click sur les listes.
Toutefois un petit ajout, permet de remédier à ce détail. Allez voir en bas de page.

Se faire une idée

Il parait que des images parlent mieux que des mots. Les captures d’écrans ont été réalisées sous Opéra 9.1 (window XP), les rendus sont sensiblement les mêmes sous Firefox 2.

Menu deplié (sans js)
Menu lorque javascript a été desactivé
Menu plié
Capture présentant le menu à son chargement lorsque le javascript est actif.
Menu actif
Capture présentant le menu déplié suite à un certains nombre de click

Un autre exemple, exploitant l’attribut #EXPOSE et une autre feuille de style

Version de base
Version témoin
Version triangle
Seule la feuille de style a été modifiée
Version #EXPOSE
Dans le cas d’une intégration dans un squelette article

Squelette

Le squelette reste simple et peu innovant. Il se base énormément sur les autres contributions.

Les éléments à noter sont :
-  l’identifiant #arborescence, pour éviter de casser les autres listes présentes sur votre page.
-  la classe noeud, qui indique l’existence d’éléments fils.
-  la classe feuille, qui indique un élément terminal.

Dans le cadre d’une intégration comme menu de navigation,vous trouverez :
-  #EXPOSE afin de mettre en valeur l’article/rubrique consulté(e)
-  #SET{rub,(#ENV{cacher_article}|?{6666,#ID_RUBRIQUE})} , cette affectation permet de cacher les articles de l’arborescence si une variable cacher_article=1 est transmise via INCLURE.

<ul id="arborescence">
  <BOUCLE_racine(RUBRIQUES){racine}{par titre}>
    <li class="noeud [(#EXPOSE)]">
      <a href="#URL_RUBRIQUE" [class="(#EXPOSE)"] [title="(#DESCRIPTIF|textebrut|entites_html)"]> 
        [(#TITRE|supprimer_numero)]
      </a>
       <ul [class="(#EXPOSE)"]>
        #SET{rub,(#ENV{cacher_article}|?{6666,#ID_RUBRIQUE})}
        <BOUCLE_article(ARTICLES){id_rubrique=#GET{rub}}{par num titre}>
          <li class="feuille [(#EXPOSE)]">
            <a href="#URL_ARTICLE" [class="(#EXPOSE)"] [title="(#DESCRIPTIF|textebrut|entites_html)"]> 
              [(#TITRE|supprimer_numero)]
            </a>
          </li>
        </BOUCLE_article>
        <BOUCLE_ss_rubrique(RUBRIQUES){id_parent}{par num titre}>
          <li class="noeud [(#EXPOSE)]">
            <a href="#URL_RUBRIQUE" [class="(#EXPOSE)"] [title="(#DESCRIPTIF|textebrut|entites_html)"]>
              [(#TITRE|supprimer_numero)]
            </a>
            <ul [class="(#EXPOSE)"]> 
              #SET{rub,(#ENV{cacher_article}|?{6666,#ID_RUBRIQUE})}              
              <BOUCLE_articlea(ARTICLES){id_rubrique=#GET{rub}}{par num titre}>
                  <li class="feuille [(#EXPOSE)]">
                    <a href="#URL_ARTICLE" [class="(#EXPOSE)"] [title="(#DESCRIPTIF|textebrut|entites_html)"]>
                        [(#TITRE|supprimer_numero)]
                    </a>
                  </li>
               </BOUCLE_articlea>
               <BOUCLE_n(boucle_ss_rubrique)></BOUCLE_n>
            </ul>
          </li>
        </BOUCLE_ss_rubrique>         	
      </ul>
    </li>
  </BOUCLE_racine>
</ul>

Styles CSS

Nous pouvons maintenant mettre tout ceci en page. Le code est commenté pour restituer l’utilisation des différentes mises en page. Vous constaterez la présence de la classe .plier qui correspondra à l’action plier qu’effectuera le script. Par défaut un navigateur déplie les listes, c’est pourquoi vous ne trouverez pas de classe .deplier.

	/* expose le chemin de l'article ou rubrique en cours */
	#arborescence .oui {
		color :red;
	}

	/* annule les marges pour les items et les sous items */
	#arborescence li, #arborescence li ul {
		margin: 0;
		padding : 0;		
		list-style : none;
	}
	
	/* par défaut les puces sont dans le corps des items */
	#arborescence li {
		list-style-position: inside;
		margin-left:2em;	
		vertical-align : top;		
	}
	
	#arborescence li a {
		height: 20px;				
	}
	
	/* par defaut les element noeuds (ie déplié) */
	#arborescence .noeud {
		list-style-image:url(../images/tree/minus.gif);
		background-image : url(../images/tree/line.gif);	
		background-repeat : repeat-y;	
	}

	/* lorsque le bloc fils est fermé */			
	#arborescence .plier {
		list-style-image:url(../images/tree/plus.gif);
	}

	#arborescence .plier > ul {
		display : none;
	}

	#arborescence .feuille {
		list-style-image: url(../images/tree/branch.gif);
		background-repeat : repeat-y;			
		height : 20px;		
	}

Script

Bon ce n’est pas tout ça, mais j’ai promis un menu dépliant. Dans un premier temps, il faut penser à mettre dans votre le <head> de votre squelette ceci :

#INSERT_HEAD

ou bien

<INCLURE{fond=inc-head}>

C’est ce qui permet d’accéder aux fonctions de jquery. De ce fait il faut mettre cette inclusion avant le code suivant.

Voyons voir ce que peut donner notre script proprement dit :

<script type="application/javascript">
  $(document).ready(function () {
    //parcours une fois le document à la recherche des élements noeud.
    var noeud = $(".noeud"); 
    //cache toutes les sous liste
    noeud.addClass("plier");
    //determine le comportement lors d'un click
    noeud.click(function (e) {
      //affiche ou cache la sous liste  sur click de l'élément
      $(this).toggleClass("plier");
      //interdit la propagation sur les noeuds parents
      e.stopPropagation();
    });
    //éviter un effet de bord (pliage) lors d'un click sur le lien
    $("a").click(function (e) {
      e.stopPropagation();
    });
    //éviter un effet de bord (pliage) lors d'un click sur une feuille
    $(".feuille").click(function (e) {
      e.stopPropagation();
    });


  });	
</script>

Comme vous pouvez le constater il est court et son action assez simple. Dans un premier temps, il cache l’ensemble des éléments contenu par un noeud. (à l’exception de Internet Explorer qui ne sait pas traiter .plier>li)

Ensuite, le script capture l’évènement click sur chaque noeud. Sur le noeud considéré la classe plier est ajoutée ou enlevée en fonction de sa présence. Le e.stopPropagation(); interdit la propagation de l’évènement sur les noeuds parents.

Et Internet Explorer ?

Pour les tenaces, il existe une solution qui nécessite de mettre un peu plus les mains dans le camboui.

Dans un premier temps, il nous faut détecter Internet Explorer. Les développeurs de jquery ont pensé à nous. Il existe une directive $.browser qui permet de déterminer le navigateur. Pour les curieux (uniquement :), il existe une surcharge plus évoluée (jqbrowser 2)

Pour commencer nous allons modifier la page pour Internet Explorer. Juste avant le code précédemment saisi, nous ajoutons :

  $(document).ready(function() {
    if  ($.browser.msie) {
      var noeud = $(".noeud");
      noeud.prepend("<a href=# class=noeud>&nbsp;</a>");
      noeud.children("ul").addClass("pliermsie");
    }
  });

Ce code va donc rajouter un lien nommé déplier devant chaque noeud. Et rajoute une classe pliermsie à l’élément fils qui permettra de le plier. Pour ceci rajoutons dans la CSS :

	/* personalisation de l'ancre pour ie */
	#arborescence a.noeud {
		/* ramene l'ancre au dessus de la puce */
		margin-left : -2em;
		/* formate l'anre à la taille de la puce */
		width : 20px;
		height : 20px;
		text-decoration: none ;
		background-image:url(../images/tree/invisible.gif);
	}

	/* éléments terminaux, qui ne possédent pas de sous partie */				
	#arborescence .feuille {
		list-style-image: url(../images/tree/branch.gif);
		background-repeat : repeat-y;
		height : 20px;			
	}

Et enfin nous rajoutons un bout de code pour traiter le (dé)pliage. Nous rajouterons donc ceci après les 2 blocs de code saisis jusqu’à présent.

  $(document).ready(function() {
    $(".noeud").click(function () {
      if($.browser.msie) {
        $(this).siblings("ul").toggleClass("pliermsie");
      }
    });
  });

Au final nous avons rajouté des comportements propres à Internet Explorer, sans modifier les éléments de base.

Télécharger

En attendant que contrib accepte à nouveau les documents zippés, vous pouvez charger le menu ici

Conclusion

En mettant tout ceci dans un beau squelette ça devrait le faire, non ?

Discussion

Aucune discussion

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom