2010-02-23 3 views
3

HTML:простого JQuery выпадающего - clearTimeout, SetTimeout вопросы

<ul class="topnav"> 
    <li><a href="#"><span>One</span></a></li> 
    <li><a href="#"><span>Two</span></a></li> 
    <li> 
     <li><a href="#"><span>Three</span></a></li> 
     <ul class="subnav"> 
      <li><a href="#">A</a></li> 
      <li><a href="#">B</a></li> 
      <li><a href="#">C</a></li> 
     </ul> 
    </li> 
</ul> 

Jquery:

var timeout = null; 

$(document).ready(function() { 

    $("ul.topnav li").mouseover(function() { 

     if (timeout) clearTimeout(timeout); 

     $(this).find("ul.subnav").slideDown('fast').show(); 

    }).mouseout(function() { 
     timeout = setTimeout(closemenu, 500); 
    }); 

    // sub menu mouseovers keep dropdown open 
    $("ul.subnav li").mouseover(function() { 
     if (timeout) clearTimeout(timeout); 
    } 
    ).mouseout(function() { 
     timeout = setTimeout(closemenu, 500); 
     // alert(timeout); 

    }); 

    // any click closes 
    $(document).click(closemenu); 
}); 

// Closes all open menus 
function closemenu() { 
    $('ul.subnav:visible').hide(); 
    if (timeout) clearTimeout(timeout); 
} 

У меня возникли проблемы с тайм-аутом. При использовании, если i mouseover «Three», выпадающее меню остается навсегда. если i mouseover «A», выпадающее меню останется навсегда, но если я навешиваю «B» или что-нибудь ниже, меню закроется на мне. если вы раскомментируете «// alert (timeout)»; он попадает туда для B, (и A), но время ожидания будет иметь значение. почему это? Я думал, что clearTimeout будет игнорировать переменную тайм-аута?

ответ

0

Вы пытаетесь создать выпадающее меню? почему бы не использовать существующие jQuery-плагины для этого или еще лучше, css-only выпадающее меню вроде http://purecssmenu.com/?

+0

Я пытаюсь работать в существующем меню веб-сайта, поэтому я пытался проложить самый простой маршрут – user210757

5

Вы можете упростить код в целом с помощью .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(); 
    }); 
});​ 

You can see a working demo here

Вместо обмена глобальной timeout переменной, это устанавливает тайм-аут на верхнего уровня <li>, каждый у одного есть независимый таймер, и когда вы наводите назад на этот элемент, только его таймер очищается. Также .hover() использует mouseenter и mouseleave, а не mouseover и mouseout, разница в том, когда вы идете в ребенка или между детьми, mouseenter не срабатывает снова, и mouseleave не срабатывает на материнской <li> мы заботимся о.

Вы можете проверить это с помощью демонстрационной ссылки выше, я добавил подпункты в первое меню, чтобы продемонстрировать, что они независимы. Если у вас возник вопрос о $.proxy, он просто делает this внутри этой анонимной функции времени, ссылаясь на то, что я хочу (текущий this) ... элемент, который необходимо закрыть после таймаута.

Смежные вопросы