Search code examples
javascriptjquerymouseeventmouseovermouseout

How can I create an exception for a jquery mouseout event only if another mouseover event hasn't been triggered?


Basically my client wants hidden navigation to appear when mouseover an image. I've solved the problem of the navigation not hiding when you mouseover the navigation and then hiding when you leave the navigation. There are two problems I'm running into and I've tried a variety of different combinations that I thought would work, but of course didn't. The two problems are:

  1. When you mouseout the image without mouseover the navigation then the navigation needs to hide, as of right now it stays open until you either mouseover the image again or mouseleave the navigation.

  2. Second problem is when you mouseleave the navigation directly to mouseover the image it loops the function and hides the nav then opens the nav again, I've tried changing slideToggle to show, but that causes a whole bunch of other issues.

Right now the code is behaving as close to how I want it and could be considered acceptable, but I'd love to know how to solve the problems above. I thought about using the hoverIntent plugin to sense the mouse movements and only trigger the functions once the mouse has slowed, but couldn't get it working properly. Clearly, I am a novice when it comes to javascript and jquery so please forgive me, but I'd really appreciate any help.

Here is my code

$(document).ready(function(){

$(".nav-body").hide();

$(".nav-head").mouseover(function(){
$(this).next(".nav-body").slideToggle(600);
$(".nav-body").mouseleave(function(){
$(this).hide(700);
});
});

});

Here is my html:

<p class="nav-head"><img src="/images/face-btn.jpg" /></p> 
<div class="nav-body"> 
<ul><?php wp_list_pages('title_li=&child_of=12&depth=1'); ?></ul> 
</div>

Solution

  • Markup change

    <div class="nav-container">
        <p class="nav-head"></p>
        <div class="nav-body"></div>
    </div>
    

    Javascript

    var eventHandler;
    
    eventHandler = function(){$(".nav-head").one("mouseover",function(){
       $(this).next(".nav-body").slideToggle(600);
        $(".nav-container").one("mouseleave", function(){
            $(this).find(".nav-body").hide(700, eventHandler);
        });
    });};
    
    eventHandler();
    

    The first change is from mouseleave to mouseout. Inside the navigation, there are likely to be descendent elements that cover the actual nav-body. With mouse leave, the handler only triggers when the mouse leaves the bound element. If it goes over descend it elements, it is considered leaving. Mouseout only triggers if it is outside the bounds of the bound object.

    The second thing I did was assign a delegate to the handler binding operation so that I could use it as a callback function for hide(). This way, the event handler won't be restored to the nav-head until the hide is completely done.

    The last was to assign the mouseout handler to the containing div. This way, the so long as it leaves the nav-head (or the nav-body) since its contained, the body will hide.