0

I have a nav that has subnavs. When the user hovers over the li's in the nav I show the subnav for the respective li. I'm running into an issue where moving the mouse from the nav to subnav fires the mouseout. I was thinking I would need to implement a timeout but unsure where to start and can't get it working. See the below js fiddle...

http://jsfiddle.net/Nhvc6/

bflemi3
  • 6,698
  • 20
  • 88
  • 155

3 Answers3

1

Two things, first of all you should use mouseenter/mouseleave (available thanks to jQuery) instead of mouseover/mouseout. These won't fire when moving to child elements. See this and this.

Second of all, you can either implement a timer, or use the wonderful jQuery hoverIntent plug-in.

Community
  • 1
  • 1
jmlnik
  • 2,867
  • 2
  • 17
  • 20
  • i'm using `hover()` not the individual jquery functions – bflemi3 Apr 01 '12 at 17:43
  • Well, either you'll have to use hoverIntent(), check out the kink in the answer, or use these methods. This is the way to do it properly. – jmlnik Apr 02 '12 at 00:12
1

Try replacing:

timeoutHandle = setTimeout(navMouseOut($subnav), 300);

With this:

timeoutHandle = setTimeout(navMouseOut, 300, $subnav); //Works for all but IE!!

This passes a reference to the function navMouseOut. The navMouseOut parameter $subnav is also passed as a third parameter to setTimeout. Note the third parameter of setTimeout will be ignored by IE. Works in all modern browsers though.

If you require cross-browser comparability, you should pass an anonymous function to setTimeout in order to invoke navMouseOut

timeoutHandle = setTimeout(function() {
    navMouseOut($subnav);
}, 300);

Updated Fiddle

More info

shaunsantacruz
  • 8,903
  • 3
  • 19
  • 19
0

Skip the timer entirely in this case, if you don't mind your subnav's behavior depending on proper css positioning. Here is an idea of what you could do (vastly simplified from what you had in your jFiddle)

HTML:

<ul id="nav">
<li>Howdy
    <ul class="subnav">
        <li>Howdy</li>
        <li>Howdy</li>
        <li>Howdy</li>
    </ul>
</li>
<li>Howdy
    <ul class="subnav">
        <li>Howdy</li>
        <li>Howdy</li>
        <li>Howdy</li>
    </ul>
</li>

​ CSS:

#nav {
margin-top: 0 !important;
width: 200px;
}

#nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

#nav li {
    position: relative;
    display: block;
    margin: 0 0 3px 0;
    border:thin solid black;
}

.subnav {
    position: absolute;
    margin: none;
    left:198px;
    top:-1px;
    width: 200px;
    display: none;
}

​ Javascript:

$('#nav li').mouseenter(function(event) {
    $(this).children().show();
});

$('#nav li').mouseleave(function(event) {
    $(this).children().hide();
});

​ The important thing here: as long as the nav list item and its subnav list are touching, the 'mouseleave' or 'mouseout' event won't fire on the 'li', as the subnav is part of the 'li'. When you leave either the subnav or its parent 'li', the 'mouseleave' event fires. Worked well for me in jFiddle.

I'd also personally use a 'ul' for your subnav, as I did above. Semantically, makes more sense to me.

jCyCle
  • 466
  • 4
  • 7