2015-10-21 109 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); 
     } 
    }); 
    });