jQuery hover dependent on two elements

眉间皱痕 提交于 2019-11-29 10:47:55

For Mouse-menu ergonomics you want a small delay while mousing from main to sub menus, so the the sub menu does not close before the mouse gets there. (As the question says.)

But, you also need a delay before menus open -- both to avoid annoying "flyover" activation, and to reduce the common occurrence of accidentally switching from sub1 to sub2 while moving off the main menu.

So, the question code needs:

  1. hover over the sub-menu ul elements.
  2. stop to halt running animations if mouse selection changes.
  3. A resettable timer controlling both open and close.

See the demo at jsFiddle.

Putting it all together:

$("#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);
}



Note the extra operations required on #snav ul, to cleanup after interrupted swaps between sub-menus.

Instead of using the .hover() method, try using separate event handlers for mouseenter and mouseleave. The mouseenter would only be attached to the mnav buttons, while the mouseleave would be attached to both the mnav button and the snav div. On your mouseleave functions you'll probably have to add a small timeout and check to see if they went from one element to another.

Try something like this:

<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>

See example →

The following should work for you, I made several changes:

  • used the .stop() method to halt the animation on entering the subnav
  • moved the slides to the subnav ul's instead of the container so the above would work
  • some other things

See below:

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!