JQUERY hover dropdown with hoverIntent

Bob picture Bob · Feb 14, 2010 · Viewed 8.1k times · Source

I am creating a dropdown that slides down when hovered over. This is some code that I had. I want to use HoverIntent to accomplish this goal.

.menu_img is the class on the image that is hovered over to start the slide down of the list

.page_nav is the class on the list that slides down when .menu_img is hovered over.

$(document).ready(function(){
  $('img.menu_img').click(function () {
   $('ul.page_nav').stop().slideDown('slow');
  });
});

HTML

<div id="helper_bar">
    <div class="page_width">
        <img src="images/page_nav.png" alt="page_nav" title="use this to navigate the page" class="menu_img" width="179" height="33" />
    </div>
</div>

<div class="page_width">
    <ul class="page_nav">
            <li><a href="#">About</a></li>
            <li><a href="#">Services Offered</a></li>
            <li><a href="#">The Team</a></li>
            <li><a href="#">The Process</a></li>
    </ul>
</div>

This is the code that I have. This works if you click on the img but if you switch .click to .hover it will hover out when you try to go to the li's. This is why I brought in hoverIntent plugin but I'm not sure how to integrate it to get the proper solution I'm trying to create.

BTW i didn't include the HTML code but its a simple image and ul li tags which I know are working fine. There is a display: none; on the ul li and I did some stuff to make it funciton properly in my layout. (i have the layout a bit different than a regular dropdown.) Either way, I'm very certain my CSS is right, I just need to figure out how to write the Jquery. Thanks!

Answer

Doug Neiner picture Doug Neiner · Feb 14, 2010

[Updated Answer]

What you want to do is going to be a bit challenging with a hover effect. Here is a possible solution, but you can't use hoverIntent with it because it needs the events to bubble, and mouseenter and mouseleave events don't bubble. However, I have incorporated a hoverIntent-like effect in this solution. First wrap both items in a single div with the id of menu:

<div id="menu">
    <div id="helper_bar"> ... </div>
    <div class="page_width"> ... </div>
</div>

And use this JS (inside a document.ready event):

var trigger = $("img.menu_img")[0], // The DOM element
    $nav    = $("ul.page_nav");     // The jQuery Wrapped DOM element
$("#menu").mouseover(function(e){
   // Keep track when the mouse is over the menu area
   if(e.target == this){
     $(this).data('over', true);
   }      

   // Only show menu if the img.menu_img was what triggered the event
   if(e.target == trigger){
     $nav.stop().slideDown('slow');
   }
}).mouseout(function(e){
   if( e.target == this ){
       var $this = $(this);
       $this.data('over', false);
       window.setTimeout(function(){
          if(!$this.data('over')) $nav.stop().slideUp('slow');
       }, 500); // Wait half a second to see if the mouse reenters the element
   }
});

Please ask if you have questions or problems with this solution.

[Original Answer]

hover will never work for what you want, since the ul list can never be a child of an img. Every time you move off the img the menu will hide. What I would recommend, is something like this (Actually, I would recommend you use image replacement instead of an image, but lets just do one thing at a time):

HTML

<ul id="nav">
  <li><img class="menu_img" alt="Home" />
      <ul class="page_nav">
         ...
      </ul>
  </li>
  ....
</ul>

JS

$("#nav > li").hoverIntent( function(){
    $('ul.page_nav', this).stop().slideDown('slow');
}, function(){
    $('ul.page_nav', this).slideUp('slow');
});

This way the mouseenter event (or a delayed version of it with hoverIntent) fires when the li is hovered, and won't fire again until the entire list is exited by the mouse. So, as long as the mouse is over the li or any of its children, the mouseout event will never fire, allowing the page_nav to do its job as a menu.