Pull-down — выпадающим меню, работающим на javascript, никого не удивить. Мне не нравится, что оно закрывается мгновенно, как курсор мыши выходит за край выпавшей секции. Немного промахнешься (особенно это часто случается с последними пунктами), и меню нужно открывать вновь.
В простых реализациях использутеся событие hover, в котором задаются две функции:
1 2 3 4 5 6 7 8 9 |
$('.navbar .dropdown').hover(function() { //разворачиваем меню вниз $(this).find('.dropdown-menu').first() .stop(true, true).slideDown(250); }, function() { //сворачиваем его вверх $(this).find('.dropdown-menu').first() .stop(true, true).slideUp(250); }); |
Когда курсор наводится на родительский пункт — меню разворачивается, когда фокус у контейнера теряется — меню сворачивается.
Мы сделаем так, чтобы между получением фокуса и разворачиваением меню, а также потерей фокуса, и соответственно, сворачиваем меню, можно было вставить задержку.
В приведенном примере используется bootstrap css, и вы, возможно, узнали данный API по именам классов. Но предлагаемый метод можно будет использовать и в других иерархических меню.
Идея в том, чтобы создавать для каждого контейнера меню пару уникальных объектов timeout. Один из них будет задавать задержку перед открытием меню, а второй — перед закрытием.
Для понимания, с чем мы работаем, я приведу пример HTML кода меню:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<div id="navbarCollapse" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="dropdown" id="m1"> <a href="/url00">Головной пункт меню 1</a> <ul class="dropdown-menu"> <li><a href="/url1">Ссылка меню 1</a></li> <li><a href="/url2">Ссылка меню 2</a></li> </ul> </li> <li class="dropdown" id="m2"> <a href="/url01">Головной пункт меню 2</a> <ul class="dropdown-menu"> <li><a href="/url3">Ссылка меню 3</a></li> <li><a href="/url4">Ссылка меню 4</a></li> </ul> </li> </ul> </div> |
Корневые пункты меню мы отметили идентификаторами m1, m2 … Их мы будем использовать для создания уникальных переменных таймеров — tmIn{mN} и tmOut{mN}.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$('.dropdown').hover( function(){ var uid = $(this).attr('id'); eval('tmIn'+uid +' = setTimeout(function(){ $("#"+uid+" > ul").slideDown(250); }, 100);'); eval('if (typeof tmOut'+uid+' !== "undefined") clearTimeout(tmOut'+uid+');'); }, function(){ var uid = $(this).attr('id'); eval('clearTimeout(tmIn'+uid+');'); eval('tmOut'+uid +' = setTimeout(function(){ $("#"+uid+" > ul").slideUp(250); }, 500);'); } ); |
Я модифицировал hover, добавив в него генерацию таймеров. Если таймер не успел сработать, то он удаляется. В примере время разворачивания и свертывания меню одинаковое — 250 мс, время ожидания перед развертыванием меню — 100 мс, а время, после которого меню сворачивается при потере фокуса, — 500 мс.
Для создания динамических переменных таймеров, пришлось прибегнуть к функции eval.
Теперь с меню стало гораздо приятнее работать. Оно немного ожидает перед тем как свернуться и не выскакивает чуть стоит провести над ним мышью. :)