Bonjour à tous et merci à Grafikart pour le tutoriel sur le menu accordéon qui m'a beaucoup servi.

J'ai cependant une question : comment faire pour que, quand le curseur de la souris n'est pas sur le menu, le menu déroulé se ferme automatiquement.

Car je trouve un peu gênant le fait que quand on n'est pas en train de naviguer sur le menu, une catégorie reste ouverte...

Merci encore :)

23 réponses


Donnes-nous ton code pour déjà voir quel type d'évenement tu as utilisé pour le montrer.
Après, on pourra voir comment le cacher.

Word
Auteur

Bonjour Swatto et merci d'avoir répondu.

J'ai appliqué exactement le tutoriel de Grafikart, donc mon code js est le suivant :

jQuery().ready(function(){
    $(".ascenseur").next("div").hide();
    $(".ascenseur").mouseover(function(){
        if($(this).next("div").is(":hidden")) {
            $(".ascenseur").next("div:visible").slideUp(80);
            $(this).next("div").slideDown(80);
        }
    });

});

Il faut se dire les étapes :

  • La souris passe sur le menu => on affiche la catégorie
  • La souris n'est plus sur le menu => on cache la catégorie

Cela donne donc 2 fonctions :

  • mouseover quand on passe sur l'élément
  • mouseout quand on le quitte

C'est de la logique, après il faut vraiment ne pas hésiter à aller sur la doc de jQuery (c'est en anglais mais quand on développe on a pas vraiment le choix).

Je te donne le lien sur les évènements de jQuery : ici

Word
Auteur

Oui, j'avais déjà essayé de faire quelque chose avec mouseout, par exemple ceci :

$(".ascenseur").mouseout(function(){
        if($(this).next("div").is(":visible")) {
            $(".ascenseur").next("div:visible").slideUp(80);
        }
    });

Le problème c'est que dès que je navigue sur le menu, si je ne suis pas sur une des catégories principales (par exemple si je me place sur ce qui a été déroulé), le menu se referme.
J'ai très peu de connaissances en javascript, donc j'ai encore du mal à bien saisir ce qu'il se passe.

Tu peut poster le code html ?

Word
Auteur

Oui, le voici (je l'ai un peu raccourci pour laisser juste la structure) :

<!-- Le menu : -->
<div id="menu_gauche">
   <div class="element_menu">
        <h3 class="ascenseur">XXX</h3>
        <div>
            <ul>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
            </ul>
        </div>
   </div>

   <div class="element_menu">
        <h3 class="ascenseur">XXX</h3>
        <div>
            <ul>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
            </ul>
        </div>
   </div>

   <div class="element_menu">
        <h3 class="ascenseur">XXX</h3>
        <div>
            <ul>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
            </ul>
        </div>
   </div>

</div>

Hum d'accord, au niveau de ton sélecteur, tu lui dit "quand je passe la souris sur .ascenseur, affiche le sous-menu". Le problème c'est que quand tu va sur le sous-menu, tu quitte .ascenseur, donc il cache le sous-menu.

Dans un premier temps il faudrait que tu donne une classe aux div pour pouvoir les sélectionner facilement : class="element" par exemple

J'te fait un code vite fait pour te montrer la voie.

Donc pour un code comme ceci

<div class="menu">
    <div class="element_menu">
        <h3 class="ascenseur"></h3>
        <ul class="element">
            <li><a href=""></a></li>
            <li><a href=""></a></li>
            <li><a href=""></a></li>
        </ul>
    </div>
</div>

Ça donnerai quelque chose comme ça

//Pour chaque .element_menu
$('.menu .element_menu').each(function(){

        var current = $(this);

        //On cache tous les éléments
        current.find('.element').hide();

        //Quand on clique sur .ascenseur
        current.find('.ascenseur').click(function(){

            //On affiche/cache le sous-menu
            current.find('.element').slideToggle();

        });

    });

Ce qui est important c'est le "each", comme ça chaque sous-menu est indépendant.

Word
Auteur

Hmm... Je ne suis pas sûr de tout bien comprendre.

Est-ce que c'est en plus du premier code js que j'avais passé au début, ou c'est pour le remplacer ?

Dans les deux cas, j'obtiens quelque chose d'étrange. Parfois les menus ne se déroulent pas, parfois ils sont ouverts et ne se referment pas...

C'est pour donner une idée, mon code ne fonctionne que quand on clique, dans ton cas faudrait remplacer ça

//Quand on clique sur .ascenseur
        current.find('.ascenseur').click(function(){

            //On affiche/cache le sous-menu
            current.find('.element').slideToggle();

        });

par

//Quand on passe la souris sur .ascenseur
        current.find('.ascenseur').mouseover(function(){

            //On affiche/cache le sous-menu
            current.find('.element').slideUp();

        });
        //Quand on enlève la souris de .ascenseur
        current.find('.ascenseur').mouseout(function(){

            //On affiche/cache le sous-menu
            current.find('.element').slideDown();

        });

PS : Ton code est en ligne ??

Word
Auteur

Oki pour l'adaptation, je comprends ça.

Par contre, quand je rentre sur la page, tout le menu est affiché (pas seulement les grosses catégories, même les sous-catégories), rien ne se cache.

Et non mon code n'est pas en ligne, j'essaie de construire un petit site.

En tous les cas merci pour toute l'aide que tu m'apportes !!

Hum remet tes codes (html et js) actuels, on va débugger ça :)

Word
Auteur

Merci bien ^^

Mon html :

<!-- Le menu : -->
<div id="menu_gauche">

   <div class="element_menu">
        <h3 class="ascenseur">XXX</h3>
            <ul class="element">
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
            </ul>
   </div>

   <div class="element_menu">
        <h3 class="ascenseur">XXX</h3>
            <ul class="element">
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
            </ul>
   </div>

   <div class="element_menu">
        <h3 class="ascenseur">XXX</h3>
            <ul class="element">
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
               <li><a href="...">...</a></li>
            </ul>
   </div>

</div>

Mon JS :

$('#menu_gauche .element_menu').each(function(){

            var current = $(this);

            //On cache tous les éléments
            current.find('.element').hide();

            //Quand on passe la souris sur .ascenseur
          current.find('.ascenseur').mouseover(function(){

              //On affiche/cache le sous-menu
              current.find('.element').slideUp(80);

          });

          //Quand on enlève la souris de .ascenseur
          current.find('.ascenseur').mouseout(function(){

              //On affiche/cache le sous-menu
              current.find('.element').slideDown(80);

          });

    });

Hum essaye ça

$('#menu_gauche .element_menu .element').hide();
$('#menu_gauche .element_menu').each(function(){

      var current = $(this);
      //Quand on passe la souris sur l'élément courant
      current.mouseover(function(){

          //On affiche/cache le sous-menu
          current.find('.element').slideUp(80);

      });

      //Quand on enlève la souris de l'élément courant
      current.mouseout(function(){

          //On affiche/cache le sous-menu
          current.find('.element').slideDown(80);

      });

Grosso modo je cache tous les élément aux départ, puis dans la fonction je met l'effet "hover" directement sur les ".element_menu", comme ça quand on va sur la sous-catégorie, le menu reste visible (vu qu'on se trouve toujours sur la cible).

J'espère être clair ^^"

Word
Auteur

J'ai essayé plusieurs trucs à partir de ce que tu as écrit, mais rien à faire, rien ne se cache lorsqu'on rentre sur la page...

Et oui, j'ai compris pour le mouseover !
En fait, en voyant le code, c'est vrai que ça n'avait pas l'air si compliqué, c'est juste que les sous-catégories ne se cachent pas... :s

Hum bizarre, ça devrait fonctionner, tu peut regarder si y'a des erreurs js avec un inspecteur de code ? Si y'en a une, ça bloque le reste du code.

Word
Auteur

Hmm, j'ai Firebug. Comment voir s'il y a un problème js avec ça ?

Onglet "console" et fait un F5

Word
Auteur

Oki alors j'ai corrigé, il manquait quelques ")" et "}".

Alors le script ne fonctionne pas très bien. Si l'on passe sur une catégorie, la liste se déroule puis se referme directement, de manière infinie.

Sinon, les sous-catégories sont bien cachées dès le départ.

J'suis en manque de café...
Alors essayons comme ça, tu replace tout par

$('#menu_gauche .element_menu .element').hide();
  $('#menu_gauche .element_menu').mouseover(function(){
      $(this).find('.element').slideUp(80);
  });
  $('#menu_gauche .element_menu').mouseout(function(){
      $(this).find('.element').slideDown(80);
  });

Pas évident de faire un script sans tester ^^"

Word
Auteur

Ca fait globalement la même chose que précédemment. (Par contre j'ai inversé slideUp et slideDown, sinon ça ne fait pas le bon effet)

En fait, si on laisse la souris sur .element_menu, c'est ok. Mais dès qu'on descend sur une sous-catégorie, ça se perturbe totalement...

Je vient de tester et ça a l'air de bien fonctionner avec mouseenter et mouseleave

$('#menu_gauche .element_menu .element').hide();
    $('#menu_gauche .element_menu').mouseenter(function(){
        $(this).find('.element').slideDown(80);
    });
    $('#menu_gauche .element_menu').mouseleave(function(){
        $(this).find('.element').slideUp(80);
    });
Word
Auteur

Ouah ça marche nickel ! Merci énormément !!

Je suis vraiment content ! Merci :)