2010-04-10 9 views
1

EDIT: Voir ceci dans l'action ici: http://jsbin.com/emobi/5 - et utilise mouseenter/mouseleave.Le menu de navigation de jQuery ne disparaît pas

J'ai un menu de base en utilisant des UL emboîtés, ce qui est assez standard je pense. Lorsque je survole un LI à partir du menu "root", je veux que l'UL dans ce LI s'affiche. Déplacez la souris ou à un autre LI, il montre ce sous-menu. Descendez dans le sous-menu et il reste pendant que vous passez la souris sur chaque élément. Je l'ai fait travailler avec un simple jeu jQuery.hover(), mais j'ai ensuite rencontré des problèmes. Lorsque sur une page, l'élément de menu "root" reçoit une classe de "current-page" et si cette classe existe, je veux qu'elle affiche statiquement ce sous-menu après un passage au clavier. J'espère que j'ai bien expliqué cela. J'ai juste jeté une variable dans les fonctions de survol de sorte que, au passage du curseur, il a exécuté un .show() dans le sous-menu de la page en cours. Facile. Sauf que lorsque je déplace la souris entre les LI individuels du sous-menu, il revient au sous-menu de la page en cours. J'ai donc essayé d'ajouter un élément de minuterie basé sur another question ici. Cela a empiré les choses - maintenant les sous-menus ne disparaissent pas.

Voici mon CSS, balisage, et JS ... comment diable puis-je faire fonctionner correctement?

Markup:

<div id="menu"> 
<div id="navbar"> 
    <ul id="firstmenu"> 
     <li> 
      <a href="http://localhost/site/pageone">page one</a> 
      <ul class="submenu"> 
       <li><a href="http://localhost/site/pageone/subone">subone</a></li> 
       <li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li> 
       <li><a href="http://localhost/site/pageone/subthree">subthree</a></li> 
       <li><a href="http://localhost/site/pageone/subfour">subfour</a></li> 
       <li><a href="http://localhost/site/pageone/subfive">subfive</a></li> 
      </ul> 
     </li> 

     <li> 
      <a href="http://localhost/site/pagetwo">barely there</a> 
      <ul class="submenu"> 
       <li><a href="http://localhost/site/pageone/subone">subone</a></li> 
       <li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li> 
       <li><a href="http://localhost/site/pageone/subthree">subthree</a></li> 
       <li><a href="http://localhost/site/pageone/subfour">subfour</a></li> 
       <li><a href="http://localhost/site/pageone/subfive">subfive</a></li> 
      </ul> 
     </li> 
     <li class="current-page"> 
      <a href="http://localhost/site/pagetwo">kith & kin</a> 
      <ul class="submenu"> 
       <li><a href="http://localhost/site/pageone/subone">subone</a></li> 
       <li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li> 
       <li><a href="http://localhost/site/pageone/subthree">subthree</a></li> 
       <li><a href="http://localhost/site/pageone/subfour">subfour</a></li> 
       <li><a href="http://localhost/site/pageone/subfive">subfive</a></li> 
      </ul> 

     </li> 
     <li> 
      <a href="http://localhost/site/pagethree">focal point</a> 
      <ul class="submenu"> 
       <li><a href="http://localhost/site/pageone/subone">subone</a></li> 
       <li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li> 
       <li><a href="http://localhost/site/pageone/subthree">subthree</a></li> 
       <li><a href="http://localhost/site/pageone/subfour">subfour</a></li> 
       <li><a href="http://localhost/site/pageone/subfive">subfive</a></li> 
      </ul> 
     </li> 
     <li> 
      <a href="http://localhost/site/pagefour">products</a> 
      <ul class="submenu"> 
       <li><a href="http://localhost/site/pageone/subone">subone</a></li> 
       <li><a href="http://localhost/site/pageone/subtwo">subtwo</a></li> 
       <li><a href="http://localhost/site/pageone/subthree">subthree</a></li> 
       <li><a href="http://localhost/site/pageone/subfour">subfour</a></li> 
       <li><a href="http://localhost/site/pageone/subfive">subfive</a></li> 
      </ul> 
     </li> 
     <li> 
      <a href="http://localhost/site/pagefive">clients</a> 
     </li> 

    </ul> 
</div></div> 

Et voici le CSS:

#navbar { 
    margin: 0; 
    padding: 0; 
    border: 0; 
    text-align: center; 
} 

#firstmenu { 
    margin: 6px auto 0 auto; 
    font-size: 16px; 
    list-style-type: none; 
    letter-spacing: -1px; 
} 

#firstmenu li { 
    display: inline; 
    position:relative; 
    overflow: hidden; 
    text-align: center; 
    margin-right: 10px; 
    padding: 5px 15px; 
} 

#firstmenu a { 
    text-decoration: none; 
    outline: none; 
    color: black; 
    font-weight: 700; 
    width: 75px; 
    cursor: pointer; 
} 

.current-page { 
    color: white; 
    background: url(../images/down_arrow.png) bottom center no-repeat; 

} 
.current-page a { 
    color: white; 
    border-bottom: 1px solid black; 
} 

#firstmenu .current-page a { 
    color: white; 
} 

#firstmenu li.hover { 
    color: white; 
    background: url(../images/down_arrow.png) bottom center no-repeat; 
} 
#firstmenu li.hover a { 
    color: white; 
    border-bottom: 1px solid black; 
} 

#firstmenu li ul li.hover { 
    color: white; 
    background: none; 
} 
#firstmenu li ul li.hover a { 
    color: white; 
    border-bottom: none; 
    text-decoration: underline; 
} 

#firstmenu li ul { 
    width: 900px; 
    color: white; 
    font-size: .8em; 
    margin-top: 3px; 
    padding: 5px; 
    position: absolute; 
    display: none; 
} 

#firstmenu li ul li { 
    list-style: none; 
    display: inline; 
    width: auto; 
} 

#firstmenu li ul li a { 
    color: white; 
    font-weight: normal; 
    border: none; 
} 

.sub-current-page { 
    font-weight: bold; 
    text-decoration: underline; 
} 

#firstmenu li ul li.sub-current-page a { 
    font-weight: bold; 
} 

Et enfin, ma non-à-tout-travail JS (ce qui est en $ (document) .ready() , bien sûr):

// Initialize some variables 
    var hideSubmenuTimer = null; 
    var current_page; 
$('.current-page ul:first').show(); 

    // Prep the menu 
    $('#firstmenu li').hover(function() { 
     // Clear the timeout if it exists 
     if(hideSubmenuTimer) { clearTimeout(hideSubmenuTimer); } 

     // Check if there's a current-page class set 
     if($('li.current-page').length > 0) { 
      current_page = $('li.current-page'); 
     } else { 
      current_page = false; 
     } 

     // If there's a current-page class, hide it 
     if(current_page) { current_page.children('ul:first').hide(); } 

     // Show the new submenu 
     $(this).addClass('hover').children('ul:first').show(); 

    }, function(){ 
     // Just in case 
     var self = this; 
     // Clear the timeout if it exists 
     if(hideSubmenuTimer) { clearTimeout(hideSubmenuTimer); } 

     // Check if there's a current-page class set 
     if($('li.current-page').length > 0) { 
      current_page = $('li.current-page'); 
     } else { 
      current_page = false; 
     } 

     // Set a timeout on hiding the submenu 
     hideSubmenuTimer = setTimeout(function() { 
      // Hide the old submenu 
      $(self).removeClass('hover').children('ul').hide(); 

      // If there's a current-page class, show it 
      if(current_page) { current_page.children('ul:first').show(); current_page.css('color', 'white'); } 
     }, 500); 
    }); 

Alors qu'est-ce que je fais de mal? En parallèle, j'utilise $ ('. Current-page ul: first'). Show() car si je donnais à la page .current un paramètre "display" dans le CSS, il le positionnait vraiment bizarre sur la page.

Répondre

1

La réponse est que le script a tenté d'exécuter le vol stationnaire/mouseenter/whatever fonctions sur le Li du sous-menu. En donnant à chaque racine du menu LI leur propre classe, cela fonctionne maintenant. De cette façon, il n'appelle pas les fonctions sur le sous-menu LI.Voici la fonction terminée:

$('#firstmenu .root-item').mouseenter(function() { 
    $(this).addClass('hover').children('ul:first').show(); 
    if($('.current-page').length > 0) { 
     $('.current-page').children('ul:first').hide(); 
    } 
}).mouseleave(function() { 
    $(this).removeClass('hover').children('ul').hide(); 
    if($('.current-page').length > 0) { 
     $('.current-page').children('ul:first').show(); 
    } 
}); 
0

Pourquoi est-ce que vous jouez avec les délais d'attente? Si vous juste .toggle()?

+0

.toggle() est pour un événement click; Je veux que le menu fonctionne quand la souris survole. –

+0

Oui, vous pouvez .toggle() une classe sur un élément dans le 'function() {...}' du '.hover ('. –

0

Je l'ai réécrit pour ne pas utiliser hover, mais mouseover et mouseout. Je ne sais pas si vous l'aimez, mais voici le code:

$(document).ready(function(){ 
      $(".submenu").hide(); 
      $("li").mouseover(function(){ 
      $(this).find('.submenu').show(); 
      }); 
      $("li").mouseout(function(){ 
      $(this).find('.submenu').hide(); 
      }) 
}); 

edit: je pris le temps de revoir votre code et trouvé la ligne incriminée:

#firstmenu li { 
    display: inline; 

Puisque les listes imbriquées sont à l'intérieur de le premier menu div cela s'applique à eux aussi. Une liste imbriquée inline ne peut pas être placée et n'est donc plus placée en tant qu'enfant de son dom parent dans le moteur de présentation. Le résultat est que la souris sur le sous-menu est toujours considérée comme un pointage sur son dom (à cause du bouillonnement), mais entre les éléments de la liste, vous ne passerez plus la souris sur le dom (comme dans le design original). Vous devez repenser votre conception de mise en page, parce que maintenant, il brise le moteur de mise en page.

Vous devriez probablement repenser l'utilisation des listes comme tables ...

+0

'mouseover' et' mouseout' vont tirer sur les enfants, en se cachant eux ... vous voudriez 'mouseenter' et' mouseleave' ici –

+0

En fait, quand il entre dans l'enfant il va déclencher le 'mouseover' sur l'enfant li, qui va se dérouler jusqu'à l'origine li, et il les réaffiche Bien que vous ayez raison, 'mouseenter' et' mouseleave' seraient plus propres – tzenes

+0

@tzenes - L'événement 'mouseout' de l'élément précédent se déclenche avant le' mouseover' de l'élément suivant, pensez à comment 'focus' et' blur' travail, même situation, donc l'élément enfant est caché avant que 'mouseover' ne se déclenche, mais il n'est pas visible, il est juste caché, donc il ne se déclenchera jamais –