导航下拉列表不能与timeOuts一起使用

时间:2013-08-08 11:40:53

标签: javascript jquery

所以jQuery和setTimeOut正在逃避我!我呼吁Stack社区的善意帮助。

我正在创建一个定制的下拉导航,并在脚本中执行setTimeOut时遇到一些问题,以便菜单的响应时间超时。

我将详细介绍超时。

菜单需要在mouseenter上超时,这样用户可能会意外地将鼠标悬停在链接上而不会触发下拉列表;目前设定为400毫秒。我还想要一个允许用户mouseleave下拉的超时,并在下拉隐藏之前将1000毫秒悬停回下拉列表。

需要注意的是,将停机时间设置为无法在下拉状态之间无间断切换而停止下降。

如果一个下拉列表可见并且用户将鼠标移到另一个顶级链接(父级,即“服务”),则下拉列表(其容器)的可视化显示,并且只有下拉列表中的数据发生变化。

我希望这能涵盖脚本的要求,如果没有请请详细说明。

JSfiddle链接: http://jsfiddle.net/ATqqv/8/

对于那些无法访问JSfiddle网站的纯粹主义者或窥视者来说,这是我的JS代码。

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

提前感谢您提供帮助并为答案做出贡献。

2 个答案:

答案 0 :(得分:1)

http://jsfiddle.net/DA4cv/8/

function responsive_navigation() {

var menuItems = $('header nav > ul > li');
var dropDowns = $('.dropnav');
var showTimer = null;
var hideTimer = null;

// hover over nav li
menuItems.on('mouseover click', function(){ 

    clearTimeout(showTimer);           
    clearTimeout(hideTimer);

    var mi = $(this);
    showTimer = setTimeout(function(){nav_show(mi);}, 400);
    menuItems.removeClass('active');
});

// end hover on nav li
menuItems.on('mouseleave', function(){

    clearTimeout(hideTimer);

    var mi = $(this);
    hideTimer = setTimeout(function(){nav_hide(mi);}, 1000);
});

// hover over dropdown
dropDowns.on('mouseover', function(){
    clearTimeout(hideTimer);
});

// end hover on dropdown
dropDowns.on('mouseleave', function(){
    var dd = $(this);
    hideTimer = setTimeout(function(){nav_hide(dd.parent());}, 1000);    
}); 

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

// Hide the menu relative to user actions
function nav_hide(menuItem) {
    menuItem.children('.dropnav').hide();
    menuItem.removeClass('active');
}  

}

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

答案 1 :(得分: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();
}

jsFiddle