2
votes

I am trying to develop my own accordion/sliding menu. (as a side question, any good ones that can be easily customized/skinned?)

I found that seem to trigger when I am sliding down an "inner" menu. Since it's "inner", my mouse definitely has not left #mainnav.

My test page here

Without that annoying test alert here

$("#mainnav").mouseleave(function() {
    alert("mouseleave #mainnav");
});

more complete source:

$(function() {
    $("#mainnav > li > a").hover(mouseOver);
    $("#mainnav").mouseleave(function() {
        alert("mouseleave #mainnav");
    });
});
function mouseOver() {
    $(this).next("ul").slideDown("fast", function() {
        $("li:has(ul) > a", this).hover(mouseOver);
    });
}
#mainnav, #mainnav ul {
    list-style: none;
    padding: 0;
    margin: 0;
    background: #bbb;
}
#mainnav ul {
    display: none;
    margin: 5px 10px;
}
#mainnav a {
    display: block;
    padding: 5px 10px;
    margin: 2px 0;
    background: yellow;
}
<ul id="mainnav">
    <li><a href="#">Test</a></li>
    <li><a href="#">Test</a></li>
    <li><a href="#">Test</a></li>
    <li> 
        <a href="#">Test</a>
        <ul>
            <li><a href="#">Test</a></li>
            <li> 
                <a href="#">Test 1</a>
                <ul>
                    <li><a href="#">Test</a></li>
                    <li><a href="#">Test</a></li>
                    <li><a href="#">Test</a></li>
                </ul>
            </li>
            <li><a href="#">Test</a></li>
        </ul>
    </li>
    <li><a href="#">Test</a></li>
    <li><a href="#">Test</a></li>
</ul>
5
Maybe it has to do with event propagation? Maybe you need to stopPropagation? - meder omuraliev
i am thinking something is weird with the selector, which seems correct tho, maybe because of margins cause this... stopPropagation where/when? why do u say its because of propagation tho? - iceangel89
@iceangel89 Link provided in your question is not working, can you create a JSFiddle or share any link to your site? - Aditya Singh

5 Answers

0
votes

There isn't a single JQuery accordion/sliding menu/anything that isn't easily skinned and customized. They all use CSS.

0
votes

You seem to have found a reliable way to crash Google Chrome with that script. Weird.

Maybe you need to also select all child elements.

$("#mainnav, #mainnav > *").mouseleave(function() {
    alert("mouseleave #mainnav");
});
0
votes

The jQuery UI accordion uses CSS generated by ThemeRoller. You can even further customize the CSS produced by ThemeRoller.

As to your problem, I suspect it's an issue with jQuery simulating the event (it's Microsoft proprietary). The example on the jQuery site uses DIVs and paragraphs and it seems to work as advertised. You might want to try stopping the propagation of the "hover" event to see if that prevents the mouseout on the child from triggering mouseleave on the parent.

EDIT: I just noticed that your hover method only has one callback. I believe it takes two, and you need to stop propagation in both. The following seems to do the trick but to make it work (since leaving the anchor on either end has the event block) I had to wrap the whole thing in a DIV with padding 5 and attach the mouseleave event to it.

$(function() {
    $("#mainnav > li > a").hover(
         mouseOver,
         mouseOut
    );
    $("#navContainer").mouseleave(function() {
        alert("mouseleave #mainnav");
    });
});

function mouseOver(e) {
    $(this).next("ul").slideDown("fast", function() {
        $("li:has(ul) > a", this).hover(mouseOver, mouseOut);
    });
    e.stopPropagation();
}
function mouseOut(e) {
    e.stopPropagation();
}

<div id="navContainer" style="padding: 5;">
   ... your list ...
</div>
0
votes

Old post, I know, but for future visitors: The test page was no loger live :( but I think this happens because the element listening for the mouseleave is moving below the pointer since the mouseenter, leaving itself from you.

If that's the case, measuring the distance of the pointer to the mouseenter-ed element when entering and leaving events fire (but before the animations/effects occur) you can tell whether the mouse is "approaching" or "leaving" the element. That way, you can "wait" one second before triggering the "mouseleave" effects/actions/functions.

-2
votes

Use a Web Inspector. Safari has one, Firefox has firebug. Grab one of them, you'll notice that it happens whenever you're entering one of the list items. You ARE leaving mainnav. I don't think you understand the way Box Model and the JQuery events system works. Here's a good resource on Box Model (follow the link he mentions and read all of that too, it is necessary to understand this before you will be able to understand your problem). Here is the events/mouseleave page in JQuery's documentation. If you would have read this a long time ago, you would not be here asking this very question. They even put it in bold for you. Their documentation is excellent.

Mouseout fires when the pointer moves into or out from child element, while mouseleave doesn't.

I'm not going to write your code for you, you need to learn these things on your own. This is a crucial part of JQuery/CSS that cannot be skipped over if you intend to write your own scripts.