2015-10-21 123 views
0

我有一个导航系统,涉及到一个下拉菜单,允许用户到达第二和第三级别的推出。悬停时,父菜单保持活动状态,并且箭头方向发生变化。jQuery下拉鼠标延迟

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

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

我已经在这个社区搜索过,发现jQuery dropdown menu with setTimeout does not work这确实有助于写我拥有的东西。如有任何问题,欢迎提出宝贵意见!干杯。

对于我的意思的视觉表示,我创建了一个jsfiddle:https://jsfiddle.net/hoffismo/4b9jL7t4/5/

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); 
     } 
    }); 
}); 

回答

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); 
     } 
    }); 
    });