HTML:
You can simplify your code overall by using .hover() and .data() like this:
$(function() {
$("ul.topnav li").hover(function() {
var timeout = $(this).data("timeout");
if(timeout) clearTimeout(timeout);
$(this).find("ul.subnav").slideDown('fast');
}, function() {
$(this).data("timeout", setTimeout($.proxy(function() {
$(this).find("ul.subnav").slideUp();
}, this), 500));
});
$(document).click(function() {
$('ul.subnav:visible').hide();
});
});
You can see a working demo here
Instead of sharing a global timeout
variable, this sets a timeout per top level <li>
, each one has an independent timer, and when you hover back over that element, only its timer is cleared. Also .hover() uses mouseenter and mouseleave, rather than mouseover and mouseout, the difference is when you go into a child or between children, mouseenter
doesn't fire again, and mouseleave
doesn't fire on the parent <li>
we care about.
You can test this with the demo link above, I added sub-items to the first menu as well, to demonstrate they're independent. If you happen to have question about the $.proxy in there, it's just making this
inside that timeout anonymous function refer to what I want it to (the current this
)...the element that needs closing after the timeout.
youre trying to build a drop down menu? why not use existing jquery plugins for that or better yet, css-only drop down menu like http://purecssmenu.com/?