Вы можете упростить свой код в целом, используя .hover()
и .data()
, например:
$(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();
});
});
Рабочее демо можно посмотреть здесь
Вместо того, чтобы делить глобальную переменную timeout
, это устанавливает тайм-аут на верхний уровень <li>
, у каждого из них есть независимый таймер, и когда вы наводите указатель мыши на этот элемент, только его таймер очищен. Также .hover()
использует mouseenter
и mouseleave
, а не mouseover
и mouseout
, разница в том, когда вы входите в ребенка или между детьми, mouseenter
больше не срабатывает, а mouseleave
не срабатывает на родителя <li>
, о котором мы заботимся.
Вы можете проверить это с помощью демонстрационной ссылки выше, я также добавил подпункты в первое меню, чтобы продемонстрировать их независимость. Если у вас возник вопрос по поводу $.proxy
, это значит, что this
внутри этой анонимной функции тайм-аута ссылается на то, что я хочу (текущий this
) ... элемент который должен быть закрыт после тайм-аута.