4

I have created a collapsible menu with stucture like:

  • Parent
  • Parent 2
  • Parent 3
    • Sub category

I have the following javascript

    var config = {
        over: function() { $(this).children('ul').slideDown('slow'); },
        timeout: 5,
        out: function() { }
    }

    $("ul.root-tags li").hoverIntent(config);

    $('ul.root-tags').mouseout(function() {
        $(this).children('li ul').each(function () {
            $(this).slideUp('slow');
        });
    });

Basically I want to open sub categories on hover of the parent item but only collapse opened subcategories on mouseout of the entire list, not just the parent item. My current code does not do this. What changes do I need to make?

jsfiddle is here http://jsfiddle.net/zkhVC/4/

Matthew Hui
  • 3,321
  • 2
  • 27
  • 38

3 Answers3

3

This should address what you are asking for:

$('#head').mouseleave(function() {

    $(this).find('li ul').each(function () {
        $(this).stop().slideUp('slow');
    });

});

$("ul li").mouseenter(function() {
    $(this).children('ul').stop().slideDown('slow');
});​

Fiddle

Here

Explanation

  • Do not use hover event, because it will get fired over and over again you are over the element. You want to use mouseenter instead.
  • Use mouseleave instead of mouseout:

The mouseleaveevent differs from mouseoutin the way it handles event bubbling. If mouseout were used in this example, then when the mouse pointer moved out of the Inner element, the handler would be triggered. This is usually undesirable behavior. The mouseleaveevent, on the other hand, only triggers its handler when the mouse leaves the element it is bound to, not a descendant. So in this example, the handler is triggered when the mouse leaves the Outer element, but not the Inner element.

  • Take a deeper look at how selectors works: you do not need of the children function here.
  • You want to use the stop function before calling an animation to prevent animations buffering.
Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57
1

It looks a little strange, but maybe we could explain it like this :

It seems that mouseout () event is send to children of ul.root-tags. So you should try the event.stopPropagation() method avoid bubbling down.

$('ul.root-tags').mouseout(function(e) {
    e.stopPropagation();
    $(this).children('li ul').each(function () {
        $(this).slideUp('slow');
    });
});

If it doesn't work right now, using e.target, you may find exactly who calls who.

Community
  • 1
  • 1
Nicolas Zozol
  • 6,910
  • 3
  • 50
  • 74
  • Modified the jsfiddle with the solution of Nicolas Zozol works: http://jsfiddle.net/zkhVC/5/ – BastiS Oct 21 '12 at 09:32
1

Use jQuery's mouseleave instead of mouseout:

$('ul.root-tags').mouseleave(function() {
    $(this).find('ul').slideUp('slow');
});

$("ul.root-tags li").hover(function() {
    $(this).find('ul').slideDown('slow');
})​

See this FIDDLE.

Michal Klouda
  • 14,263
  • 7
  • 53
  • 77
  • Form mkyong : both mouseout() and mouseleave() events are fire when the mouse leaves the matched element. The only different is in the way of the “event bubbling” http://www.mkyong.com/jquery/different-between-mouseout-and-mouseleave-in-jquery/ – Nicolas Zozol Oct 21 '12 at 09:40