jQuery悬停依赖于两个元素

Posted

技术标签:

【中文标题】jQuery悬停依赖于两个元素【英文标题】:jQuery hover dependent on two elements 【发布时间】:2011-09-02 04:27:18 【问题描述】:

出于设计原因,我有主导航和子导航,它们位于单独的 DIV 中。我想在主导航项悬停时显示适当的子导航,我可以这样做,但是如果用户将鼠标移到主导航项之外并进入子导航,我也想保持子导航打开-导航区域。最后一部分是我卡住的地方。

我正在考虑悬停时我需要使用 setTimeout() 和 IF 语句做一些事情,但我无法在该领域取得任何进展。这甚至是一种值得尝试的方法吗?

html

<div id="mnav">
 <ul id="buttons">
  <li class="one"><a href="#">Main 1</a></li>
  <li class="two"><a href="#">Main 2</a></li>
  <li class="three"><a href="#">Main 3</a></li>
  <li class="four nav-dark"><a href="#">Main 4</a></li>
 </ul>
</div> <!-- /mnav -->

<div id="snav">
 <ul class="snav-one">
    <li><a href="#">Sub 1.1</a></li>
    <li><a href="#">Sub 1.2</a></li>
    <li><a href="#">Sub 1.3</a></li>
    <li><a href="#">Sub 1.4</a></li>
    <li><a href="#">Sub 1.5</a></li>
    <li><a href="#">Sub 1.6</a></li>
 </ul>
 <ul class="snav-two">
    <li><a href="#">Sub 2.1</a></li>
    <li><a href="#">Sub 2.2</a></li>
 </ul>
</div> <!-- /snav -->

JS:

$(document).ready(function() 
 $("#buttons li.one, #buttons li.two").hover(function()
  var subnav = 'ul.snav-' + $(this).attr('class');

  $("#snav").slideDown('fast').addClass("open").find(subnav).show();

 , function(e)
  var subnav = 'ul.snav-' + $(this).attr('class');

  $("#snav").slideUp('fast').removeClass("open").find(subnav).hide();
 );
);

【问题讨论】:

【参考方案1】:

对于鼠标菜单人体工程学,您希望在将鼠标从主菜单移到子菜单时稍有延迟,因此子菜单在鼠标到达之前不会关闭。 (正如问题所说。)

但是,您还需要在菜单打开之前进行延迟——既避免烦人的“飞越”激活,又减少从 sub1 意外切换到 sub2的常见情况> 离开主菜单时。

所以,问题代码需要:

    hover 在子菜单 ul 元素上。 stop 在鼠标选择发生变化时停止运行动画。 一个控制打开和关闭的可复位定时器。

See the demo at jsFiddle.

把它们放在一起:

$("#buttons li.one, #buttons li.two").hover ( function ()  MenuOpenCloseErgoTimer (
        100,
        function (node) 
            var subnav = 'ul.snav-' + $(node).attr ('class');
            $("#snav ul").hide ();
            $("#snav").stop (true, true).slideDown ('fast').addClass ("open").find (subnav).show ();
        ,
        this
    ); ,
    function ()  MenuOpenCloseErgoTimer (
        200,
        function () 
            $("#snav").stop (true, true).slideUp ('fast').removeClass ("open").find ('ul').hide ();
        
    ); 
);

$("div#snav ul").hover ( function ()  MenuOpenCloseErgoTimer (
        0,
        function () 
            $("#snav").stop (true, true).slideDown ('fast').addClass ("open");
            $(this).show ();
        
    ); ,
    function ()  MenuOpenCloseErgoTimer (
        200,
        function () 
            $("#snav").stop (true, true).slideUp ('fast').removeClass ("open");
            $("#snav ul").hide ();
        
    ); 
);

function MenuOpenCloseErgoTimer (dDelay, fActionFunction, node) 
    if (typeof this.delayTimer == "number") 
        clearTimeout (this.delayTimer);
        this.delayTimer = '';
    
    if (node)
        this.delayTimer     = setTimeout (function()  fActionFunction (node); , dDelay);
    else
        this.delayTimer     = setTimeout (function()  fActionFunction (); , dDelay);

请注意#snav ul 上所需的额外操作,以便在子菜单之间的切换中断后进行清理。

【讨论】:

效果很好!非常感谢您花时间整理这些内容,您真的帮助了我并教会了我很多东西。 我不想拉伸它,但是您对重构以允许默认情况下在页面上打开子导航有任何想法吗? 这可能会变得棘手,最好打开一个新问题。说明您是否希望某些子菜单保持打开,即使用户打开一个已关闭的子菜单。基本思想是悬停功能恢复任何默认状态。最好使用 CSS 类而不是 hideshow 我已经发布了另一个问题here。您描述的逻辑似乎很简单,直到我遇到如何知道/保存菜单的初始状态的问题。【参考方案2】:

不要使用 .hover() 方法,而是尝试对 mouseenter 和 mouseleave 使用单独的事件处理程序。 mouseenter 将仅附加到 mnav 按钮,而 mouseleave 将附加到 mnav 按钮和 snav div。在您的 mouseleave 函数中,您可能需要添加一个小超时并检查它们是否从一个元素转移到另一个元素。

试试这样的:

<script>
    var timer;
    $(document).ready(function() 
        $("#mnav").mouseenter(function() 
            $("#snav").slideDown();
        );

        $("#mnav, #snav").mouseleave(function() 
            timer=setTimeout("$('#snav').slideUp();",50);
        );

        $("#mnav, #snav").mouseenter(function() 
            clearTimeout(timer);
        );
    );
</script>

【讨论】:

你能给我一个mouseleave事件处理程序的例子吗,即使它是伪代码? 我试试这个但告诉我“TypeError: $ is not a function”!!! $ 未检测到 setTimeout !!! @T Nguyen Aaaaaa,你就是那个男人。它完美地工作。谢谢,谢谢,非常感谢。【参考方案3】:

See example →

以下应该对你有用,我做了几处更改:

使用.stop() method 在进入子导航时停止动画 将幻灯片移动到子导航而不是容器,因此上述方法可以正常工作 其他一些事情

见下文:

$("#buttons li.one, #buttons li.two").hover(function() 
    var subnav = 'ul.snav-' + $(this).attr('class');

    $("#snav").find('ul').slideUp('fast');
    $("#snav").addClass("open").find(subnav).stop(true, true).slideDown('fast');
, function(e) 
    var subnav = 'ul.snav-' + $(this).attr('class');

    $("#snav").removeClass("open").find(subnav).slideUp('fast');
);

$('#snav').bind('mouseenter', function(e) 
    $(this).find('ul').stop(true, false);
).bind('mouseleave', function(e) 
    $(this).find('ul').stop(true, true).slideUp('fast');
);

See example →

【讨论】:

以上是关于jQuery悬停依赖于两个元素的主要内容,如果未能解决你的问题,请参考以下文章

两个不同元素的同步悬停

检查此元素或此元素是不是悬停在 jQuery 上

在两个表格中添加 jQuery 悬停效果

jQuery - 将鼠标悬停在元素上并将元素动画到该位置

如何使用 jquery ui 可拖动突出显示悬停时的可放置​​区域

动态jquery。如何仅将 jquery 应用于某些元素?