1

So jQuery and setTimeOut is eluding me! and I appeal to the kind nature of the Stack community for help.

I am creating a bespoke drop-down navigation and having a few issues implementing setTimeOut to the script so that the menu has time-out in its response.

I shall go into more detail regarding the time-outs.

The menu needs to have a time-out on mouseenter so the user can accidentally hover over a link and not trigger the drop-down; currently that is set to 400ms. I also want a time-out that allows the user to mouseleave the drop down and have 1000ms to hover back to the drop down before the drop down hides.

The caveat of this is that putting the time-outs in stop the drop-down from seamlessly switching between drop-downs with no flickering.

If one drop-down is visible and the user mouses to another top level link (parent, i.e. "services") the visual of the drop-down (its container) shows and only the data within the drop-down changes.

I hope this covers the requirements of the script, if not please ask me to elaborate.

JSfiddle link: http://jsfiddle.net/ATqqv/8/

And for purists or peeps who cannot visit the JSfiddle site here is my JS code.

function responsive_navigation() {
    var hover, $this;

    $target = $("header nav > ul > li");

    $target.on('mouseenter click', function (e) {
        $this = $(this);

        if(hover) {
            clearTimeout(hover); // Cancel the timeout to hide the menu
            hover = null;
        }

        hover = setTimeout(nav_show, 400);

    }).on('mouseleave', function () {
        //clearTimeout(hover);
        //hover = setTimeout(nav_hide, 1000);
        nav_hide();
    });

    // Show the menu relative to user actions
    function nav_show() {
        $this.addClass('active');
        $this.children('.dropnav').show();
    }
    // Hide the menu relative to user actions
    function nav_hide() {
        $this.children('.dropnav').hide();
        $this.removeClass('active');
    }
}

$(document).ready(function () {
    responsive_navigation();
});

Thank you in advance any and all that help and contribute to an answer.

4

2 に答える 2

1

ここで重要なのは、実行の遅延を管理することです。

イベントでは、反対の差し迫った反対のアクションをキャンセルするようにします。現在のアクションがまだ差し迫っておらず、必要な場合は、適切な ui 関数を呼び出すタイマーを開始します。

イベント以外の方法で呼び出された場合に備えて、UI 関数のすべてのタイムアウトをクリアします。これが問題にならない場合は、インスタンスを削除cancelAction()して、別のメニューが表示されているときにアクティブなメニューの非表示アクションを停止することができます。

var $parent = $("header nav > ul");

$parent.children('li').on('mouseenter click', function (e) {
    var $this = $(this);
    // cancel hiding if we left and cameback in time
    cancelAction($this, 'hover_hide_to'); 
    if (!actionImpending($this, 'hover_show_to') && !$this.hasClass('active')) {
        $this.data('hover_show_to', setTimeout(function() { nav_show($this); }, 400));
    }
}).on('mouseleave', function () {
    var $this = $(this);
    cancelAction($this, 'hover_show_to');
    if (!actionImpending($this, 'hover_hide_to') && $this.hasClass('active')) {
        $this.data('hover_hide_to', setTimeout(function() { nav_hide($this); }, 1000));
    }
});

// returnts the impending action timer id.
function actionImpending($elem, name) {
    return $elem.data(name);
}

// clear timeout for element
function cancelAction($elem, name) {
    clearTimeout($elem.data(name));
    $elem.data(name, 0);
}

function cancelAllActions($elem) {
    cancelAction($elem, 'hover_show_to');
    cancelAction($elem, 'hover_hide_to');  
}

// Show the menu, hiding the active menu.
function nav_show($elem) {
    cancelAllActions($elem);
    var $active = $parent.children(".active");
    if ($active.length > 0) {
        nav_hide($active);
    }
    $elem.addClass('active').children('.dropnav').show();
}

// Hide the menu
function nav_hide($elem, delay) {
    cancelAllActions($elem);        
    $elem.removeClass('active');
    $elem.children('.dropnav').hide();
}

jsフィドル

于 2013-08-08T22:33:44.703 に答える