Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Меню аккордеон на задержке при событии hover | jQuery (https://javascript.ru/forum/jquery/48598-menyu-akkordeon-na-zaderzhke-pri-sobytii-hover-%7C-jquery.html)

Александр О. 09.07.2014 19:13

Меню аккордеон на задержке при событии hover | jQuery
 
Доброго всем дня!

У меня проблема. Некорректно работает скрипт для меню-аккордеона.

Я составил довольно обычный jquery-скрипт для того, чтобы в меню-аккордеон при наведении мышки
на пункты разделов меню после небольшого таймаута в 0.5 секунды плавно раскрывались соответствующие вложенные пункты и подразделы.

Вот этот скрипт:

<script type="text/javascript">
$(document).ready(function(){
    
    $("#menu1 a.ssylka_razd").hover(function(){
 
        $(this).addClass('waiting');
        setTimeout(function(){
            p = $('#menu1 .waiting').parent().next().children('ul');
            p.slideDown(500).removeClass('waiting');
        },800);
 
    }, function(){
        $('#menu1 .waiting').removeClass('waiting');
    });
});
</script>


Вот оптимизированный (сокращенный) HTML-код, который обслуживает скрипт:

<ul id='menu1'>
      <li class='current1'>
          <a href='#' class='ssylka'>МАНГАЛЫ</a>
      </li>
      <li>
          <a href='#' class='ssylka_razd'>КОПТИЛЬНИ</a>
      </li>
      <li>
            <ul> 
                 <li> 
                       <a href='#' class='ssylka'>Коптильни с гидрозатвором на подставке</a> 
                 </li> 
                 <li> 
                       <a href='#' class='ssylka'>Коптильни малые</a>
                 </li>
             </ul>
      </li>
      <li>
          <a href='#' class='ssylka_razd'>МЕБЕЛЬ ДЛЯ ДАЧИ Camping World</a>
      </li>
      <li>
            <ul> 
                  <li>
                        <a href='#' class='ssylka'>Складные стулья</a>
                  </li>
                  <li> 
                         <a href='#' class='ssylka'>Складные кресла</a> 
                  </li>
            </ul>
  </ul>


Скрипт, вроде бы, правильный. Он должен игнорировать быстрые перемещения мышки (кратковременные задержки мышки над пунктами разделов). И только лишь, когда мышка останавливается над пунктом раздела (class='ssylka_razd') более, чем на 0.8 секунды, срабатывает скрипт, чтобы плавно выкатить вложенные пункты и подразделы.

Однако, когда я, тестируя скрипт, быстро перемещаю мышку верх-вниз-верх-вниз по меню-аккордеону, некоторые пункты-разделы начинают раскрываться. Хотя, этого не должно происходить, потому что при быстрых осциляциях мышки, он не задерживается над пунктами разделов более 0.1-0.3 секунды.
______________________________

Подскажите, пожалуйста, как исправить мой скрипт, и в чем моя ошибка.
Чтобы увидеть воочию этот эффект, можете проверить меню-аккордеон на этой тестовой странице:

Если можно, дайте совет, без исправления html-кода моего примера.

рони 09.07.2014 19:31

Александр О., в строке 3 обьявите переменную для таймера
в строку 13 добавьте обнуление таймера

Александр О. 09.07.2014 20:01

to рони:

Прошу прощения, не соображу никак.
Если я объявлю переменную таймера в третьей строке, вроде:
var timer = setTimeout( скрипт, 800);
то я, тем самым, запускаю в этом месте скрипт timer ...

Или вы имеете ввиду иное объявление таймера?

Если Вас не затруднит, настучите, пожалуйста, здесь эти строчки.
Я не дока в вопросах javascript.

рони 09.07.2014 20:11

Цитата:

Сообщение от Александр О.
var timer = setTimeout( скрипт, 800);

это строка 7 только пожалуйста без var --- var timer; это в 3 --- и window.clearTimeout(timer); в 13

неужели вы сами непонимаите логику -- таймер сработал а он у вас завязан на класс -- он сразу и сработает если курсор над любой ссылкой в этот момент -- ещё ждать он не будет

рони 09.07.2014 20:16

Александр О.,
$(function () {
    var timer;
    $("#menu1 ul").hide();
    $(".current1").parents("ul").css("display", "block");
    $(".ssylka_razd").parent(".current1").next().children("ul").css("display", "block");
    $("#menu1 a.ssylka_razd").hover(function () {
        $(this).addClass("waiting");
        timer = setTimeout(function () {
            p = $("#menu1 .waiting").parent().next().children("ul");
            p.slideDown(500).removeClass("waiting")
        }, 800)
    }, function () {
        window.clearTimeout(timer);
        $("#menu1 .waiting").removeClass("waiting")
    })
});

рони 09.07.2014 20:21

Цитата:

Сообщение от Александр О.
быстро перемещаю мышку верх-вниз-верх-вниз по меню-аккордеону

и запустили с 10 таймеров в вашем случае -- а с clearTimeout -- всего один

Александр О. 09.07.2014 20:44

to рони:

Логику понимает тот, кто хорошо разбирается в базовом материале.
Верно, как и следующее:
"лишь тот красиво изложит мудрую мысль на русском языке, кто учил русский язык" :)

Я разобрался.
Правильный код:
$("#menu1 a.ssylka_razd").hover(function(){
		$(this).addClass('waiting');
		       animationTimer = setTimeout(function(){
			p = $('#menu1 .waiting').parent().next().children('ul');
			p.slideDown(500).removeClass('waiting');
		},800);
	}, function(){
		$('#menu1 .waiting').removeClass('waiting');
		clearTimeout(animationTimer);
	});

Вы мне сказали про строку 3. Я сообразил, что строка должна быть 7.
Но код у меня сразу не заработал, поскольку я написал var animationTimer = setTimeout...

Спасибо большое. Без вас бы я и дальше мучился в потугах... :)


Часовой пояс GMT +3, время: 07:48.