Reputation: 111
I'm making a menu in jquery. You can see it at http://mywash.dk/testtest/index.html
The submenu that is shown from the start (below 'Hvordan') is the active menu so it should always be shown (unless you hover on another menu-item in which case another submenu should show.
It's working okay but has 1 annoying bug. When you hover from 'Hvad' to 'Hvem' it quickly display and hides the active menu before showing the menu it is supposed to.
Any idea why this is the case?
Thanks so much for your help!
Jquery:
$(document).ready(function() {
$('#menu > ul > li:not(.inpath) ul').hide();
$('#menu .inpath ul').show();
$('#menu > ul > li:not(.inpath)').hover(
function() {
$('ul', this).show("slide", { direction: "left" }, 400);
if($('#menu li.inpath ul').is(':visible') && $(this).not('#menu ul li')){
$('#menu li.inpath ul').hide("slide", { direction: "left" }, 400);
}
}, function() {
$('ul', this).hide("slide", { direction: "left" }, 400);
if($('#menu li.inpath ul').is(':hidden') && $(this).not('#menu ul li')){
$('#menu li.inpath ul').show("slide", { direction: "left" }, 400);
}
});
});
Html:
<div id="menu">
<ul>
<li class="test"><a href="">Hvem</a>
<ul>
<li class="first-item"><a href="index.html">Submenu</a></li>
</ul>
</li>
<li class="test"><a href="">Hvad</a>
<ul>
<li class="first-item"><a href="index.html">Produkter</a></li>
<li class="activeitem"><a href="cases.html" >Leveringer</a></li>
</ul>
</li>
<li class="inpath test"><a href="">Hvordan</a>
<ul>
<li class="first-item"><a href="">Reklame</a></li>
<li><a href="">PR</a></li>
<li><a href="">Websites</a></li>
<li><a href="">Illustrationer</a></li>
</ul>
</li>
<li class="last-item test"><a href="">Sådan!</a></li>
</ul>
<div class="clear"><!--clearfix--></div>
</div>
Upvotes: 1
Views: 908
Reputation: 82814
Well, it does, what you tell it. Break it down:
The main nav is visible, child navs are hidden
Mouse enters a child: Scroll away main, scroll in child
Mouse leaves child again: Scroll away child, scroll in main
Mouse enters another child: Scroll in child, scroll away main. But at the time of this event, the animation of 3. hasn't finished yet. So, the new animations just stack on top of the currently queued.
How to fix?
You need to cancel the current animations on the main nav. Let your hover-in function look like this:
function() {
$('ul', this).show("slide", { direction: "left" }, 400);
if($('#menu li.inpath ul').is(':visible') && $(this).not('#menu ul li')){
$('#menu li.inpath ul').stop(true, true).hide("slide", { direction: "left" }, 400);
// ----------------------------^ stop all current animations and clear the queue
}
}
or you query the length of the main queue on entering:
$('#menu li.inpath ul').queue().length > 0
// -> then stop
The basic idea is laid out in the jQuery docs and explained in this SO answer, too. Basically, every time you put an animation on a jQuery object, the animation is queued and executed after all currently running animations.
So if the mouse enters a navigation point, you have to check, if the main navigation is in motion right now by looking at its queue length. If there are animations piled up, you can call .stop(true, true)
to empty the queue and set the element in a state as if all the animations would have finished (the double-true
). Then you can hide it, and no animation will come in your way.
If it is not in motion, i.e., if it has an empty queue, and if it is visible, (and only in this case,) you have to slide it out of view.
Upvotes: 1