jQuery dropdown mouseout延迟

时间:2015-10-21 02:34:47

标签: jquery drop-down-menu

我的导航系统包含一个下拉菜单,允许用户进入第二级和第三级推出。在悬停时,父菜单保持活动状态,并且箭头方向发生变化。

我遇到的麻烦是允许用户运行下拉菜单并且它会停留大约1秒钟,但是如果用户返回到父级我希望下拉列表消失(以避免重影)。

虽然我似乎有jQuery工作,但我想知道如何清理它特别是悬停功能,因为我有很多重复的代码。或者有更简单的方法来实现这一目标吗?

我搜索了这个社区,发现jQuery dropdown menu with setTimeout does not work确实有助于我写下我的内容。有任何问题请询问,对此的任何帮助都将受到大力赞赏!欢呼声。

为了直观地表达我的意思,我在https://jsfiddle.net/hoffismo/4b9jL7t4/5/创建了一个jsfiddle。

以下HTML代码:

<nav role="navigation">
    <ul class="menu">
        <li class="first expanded"><a href="#">Lorem Ipsum</a>

            <ul class="menu">
                <li class="first leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="last leaf"><a href="#">Lorem Ipsum</a>

                </li>
            </ul>
        </li>
        <li class="expanded"><a href="#">Lorem Ipsum</a>

            <ul class="menu">
                <li class="first leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="last expanded"><a href="#">Lorem Ipsum</a>

                    <ul class="menu">
                        <li class="first leaf"><a href="#">Lorem Ipsum</a>

                        </li>
                        <li class="leaf"><a href="#">Lorem Ipsum</a>

                        </li>
                        <li class="leaf"><a href="#">Lorem Ipsum</a>

                        </li>
                        <li class="leaf"><a href="#">Lorem Ipsum</a>

                        </li>
                        <li class="leaf"><a href="#">Lorem Ipsum</a>

                        </li>
                        <li class="leaf"><a href="#">Lorem Ipsum</a>

                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <li class="expanded"><a href="#">Lorem Ipsum</a>

            <ul class="menu">
                <li class="first leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="last leaf"><a href="#">Lorem Ipsum</a>

                </li>
            </ul>
        </li>
        <li class="expanded"><a href="#">Lorem Ipsum</a>

            <ul class="menu">
                <li class="first leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="last leaf"><a href="#">Lorem Ipsum</a>

                </li>
            </ul>
        </li>
        <li class="expanded"><a href="#">Lorem Ipsum</a>

            <ul class="menu">
                <li class="first leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="leaf"><a href="#">Lorem Ipsum</a>

                </li>
                <li class="last leaf"><a href="#">Lorem Ipsum</a>

                </li>
            </ul>
        </li>
        <li class="last leaf"><a href="#">Lorem Ipsum</a>

        </li>
    </ul>
</nav>

下面的jQuery代码:

// Add arrows for the navigation.
$('nav ul > li').each(function () {
    var _this = $(this);

    // Set timer for fade out.
    var timer = null;

    // Arrows stored as data ready to be fetched.
    $('a').data('arrows', {
        up: ' <i>&#65514;</i>',
        right: ' <i>&#65515;</i>',
        down: ' <i>&#65516;</i>',
        left: ' <i>&#65513;</i>'
    });

    // Initially add the down and right arrows.
    if (_this.not('li ul li').find('ul').length > 0) {
        _this.children('a').append($('a').data('arrows').down);
    } else if (_this.find('ul').length > 0) {
        _this.children('a').append($('a').data('arrows').right);
    }

    // Hover events for both mouseover and mouseout.
    _this.hover(function () {
        // Reset the timer if user hovers back over.
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }
        // Second level mouseover.
        if (!_this.children('a').hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
            $('li ul > li').mouseover(function (e) {
                // Reset the timer if user hovers back over.
                if (timer) {
                    clearTimeout(timer);
                    timer = null;
                }
                e.stopPropagation();
                if (_this.children('a').hasClass('active')) {
                    _this.children('a').addClass('active');
                    _this.children('ul').addClass('fadeout');
                }
            });
            _this.has('ul').children('a').addClass('active');
            _this.children('a').find('i').replaceWith($('a').data('arrows').up);
        }
        // Third level mouseover.
        else if (!_this.children('a').hasClass('active') && _this.find('ul').length > 0) {
            $('li ul li ul > li').mouseover(function (e) {
                // Reset the timer if user hovers back over.
                if (timer) {
                    clearTimeout(timer);
                    timer = null;
                }
                e.stopPropagation();
                if (_this.children('a').hasClass('active')) {
                    _this.children('a').addClass('active');
                    _this.children('ul').addClass('fadeout');
                }
            });
            _this.has('ul').children('a').addClass('active');
            _this.children('a').find('i').replaceWith($('a').data('arrows').left);
        }
    },

    function () {
        // Second level mouseout.
        if (_this.children('a').hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
            $('li ul > li').mouseout(function (e) {
                // Reset the timer if user hovers back over.
                if (timer) {
                    clearTimeout(timer);
                    timer = null;
                }
                e.stopPropagation();
                if (_this.children('ul').hasClass('fadeout')) {
                    _this.children('a').addClass('active');
                    timer = setTimeout(function () {
                        _this.children('a').removeClass('active');
                        _this.children('ul').removeClass('fadeout');
                        _this.children('a').find('i').replaceWith($('a').data('arrows').down);
                    }, 1000);
                }
            });
            _this.children('a').removeClass('active');
            _this.children('ul').removeClass('fadeout');
            _this.children('a').find('i').replaceWith($('a').data('arrows').down);
        }
        // Third level mouseout.
        else if (_this.children('a').hasClass('active') && _this.find('ul').length > 0) {
            $('li ul li ul > li').mouseout(function (e) {
                // Reset the timer if user hovers back over.
                if (timer) {
                    clearTimeout(timer);
                    timer = null;
                }
                e.stopPropagation();
                if (_this.children('ul').hasClass('fadeout')) {
                    _this.children('a').addClass('active');
                    timer = setTimeout(function () {
                        _this.children('a').removeClass('active');
                        _this.children('ul').removeClass('fadeout');
                        _this.children('a').find('i').replaceWith($('a').data('arrows').right);
                    }, 1000);
                }
            });
            _this.children('a').removeClass('active');
            _this.children('ul').removeClass('fadeout');
            _this.children('a').find('i').replaceWith($('a').data('arrows').right);
        }
    });
});

1 个答案:

答案 0 :(得分:0)

我在https://css-tricks.com/dropdown-menus-with-more-forgiving-mouse-movement-paths/找到关于CSS技巧的非常有用的帖子后,我现在解决了这个问题。

在查看了文章中链接的以下CodePen后,我使用了“扩展CSS边界”方法。这包括添加另一个div并扩展子菜单外部的区域,这有效地保持了下拉菜单的活动。一切都有CSS的力量!

我还将整个悬停功能修剪回到下面:

  // Add arrows for desktop version of the navigation.
  $('nav ul > li').each(function() {
    // Defining variables.
    var _this = $(this);
    var listitems = _this.children('a');

    // Arrows stored as data ready to be fetched.
    $('a').data('arrows', {
      up: '<i class="fa fa-chevron-up"></i>',
      right: '<i class="fa fa-chevron-right"></i>',
      down: '<i class="fa fa-chevron-down"></i>',
      left: '<i class="fa fa-chevron-left"></i>'
    });

    // Initially add the down and right arrows.
    if (_this.not('li ul li').find('ul').length > 0) {
      listitems.prepend($('a').data('arrows').down);
    }
    else if (_this.find('ul').length > 0) {
      listitems.prepend($('a').data('arrows').right);
    }

    // Hover events for both mouseover and mouseout.
    _this.hover(function() {
      // Second level mouseover.
      if (!listitems.hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
        listitems.addClass('active');
        listitems.find('i').replaceWith($('a').data('arrows').up);
      }
      // Third level mouseover.
      else if (!listitems.hasClass('active') && _this.find('ul').length > 0) {
        listitems.addClass('active');
        listitems.find('i').replaceWith($('a').data('arrows').left);
      }
    },
    function() {
      // Second level mouseout.
      if (listitems.hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
        listitems.removeClass('active');
        listitems.find('i').replaceWith($('a').data('arrows').down);
      }
      // Third level mouseout.
      else if (listitems.hasClass('active') && _this.find('ul').length > 0) {
        listitems.removeClass('active');
        listitems.find('i').replaceWith($('a').data('arrows').right);
      }
    });
  });