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.
Теперь с меню стало гораздо приятнее работать. Оно немного ожидает перед тем как свернуться и не выскакивает чуть стоит провести над ним мышью. :)
