jQuery悬停依赖于两个元素

时间:2011-05-25 23:11:28

标签: jquery jquery-hover

我有主导航和子导航,出于设计原因,它们位于不同的DIV中。我希望在主要导航项目悬停时显示相应的子导航,我可以这样做,但是如果用户将鼠标移动到主导航项目之外并进入子导航,我还希望保持子导航打开-nav区域。最后一部分是我被卡住的地方。

我正在考虑悬停我需要使用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();
 });
});

3 个答案:

答案 0 :(得分:8)

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

但是,在菜单打开之前还需要延迟 - 既可以避免恼人的“悬浮”激活,又可以减少意外从 sub1 切换到 sub2 离开主菜单时。

所以,问题代码需要:

  1. hover在子菜单ul元素上。
  2. 如果鼠标选择发生变化,
  3. stop将停止运行动画。
  4. 一个可重置的计时器,控制打开和关闭。
  5. <强> 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上所需的额外操作,以便在子菜单之间中断交换后进行清理。

答案 1 :(得分:4)

尝试使用单独的事件处理程序进行mouseenter和mouseleave,而不是使用.hover()方法。 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>

答案 2 :(得分:1)

See example →

以下内容适合您,我做了一些更改:

  • 使用.stop() method在进入子区域时暂停动画
  • 将幻灯片移动到subnav ul而不是容器,以便上面的工作
  • 其他一些事情

见下文:

$("#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 →