我的导航系统包含一个下拉菜单,允许用户进入第二级和第三级推出。在悬停时,父菜单保持活动状态,并且箭头方向发生变化。
我遇到的麻烦是允许用户运行下拉菜单并且它会停留大约1秒钟,但是如果用户返回到父级我希望下拉列表消失(以避免重影)。
虽然我似乎有jQuery工作,但我想知道如何清理它特别是悬停功能,因为我有很多重复的代码。或者有更简单的方法来实现这一目标吗?
我搜索了这个社区,发现jQuery dropdown menu with setTimeout does not work确实有助于我写下我的内容。有任何问题请询问,对此的任何帮助都将受到大力赞赏!欢呼声。
为了直观地表达我的意思,我在https://jsfiddle.net/hoffismo/4b9jL7t4/5/创建了一个jsfiddle。
以下HTML代码:
<nav role="navigation">
<ul class="menu">
<li class="first expanded"><a href="#">Lorem Ipsum</a>
<ul class="menu">
<li class="first leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="last leaf"><a href="#">Lorem Ipsum</a>
</li>
</ul>
</li>
<li class="expanded"><a href="#">Lorem Ipsum</a>
<ul class="menu">
<li class="first leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="last expanded"><a href="#">Lorem Ipsum</a>
<ul class="menu">
<li class="first leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="expanded"><a href="#">Lorem Ipsum</a>
<ul class="menu">
<li class="first leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="last leaf"><a href="#">Lorem Ipsum</a>
</li>
</ul>
</li>
<li class="expanded"><a href="#">Lorem Ipsum</a>
<ul class="menu">
<li class="first leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="last leaf"><a href="#">Lorem Ipsum</a>
</li>
</ul>
</li>
<li class="expanded"><a href="#">Lorem Ipsum</a>
<ul class="menu">
<li class="first leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="leaf"><a href="#">Lorem Ipsum</a>
</li>
<li class="last leaf"><a href="#">Lorem Ipsum</a>
</li>
</ul>
</li>
<li class="last leaf"><a href="#">Lorem Ipsum</a>
</li>
</ul>
</nav>
下面的jQuery代码:
// Add arrows for the navigation.
$('nav ul > li').each(function () {
var _this = $(this);
// Set timer for fade out.
var timer = null;
// Arrows stored as data ready to be fetched.
$('a').data('arrows', {
up: ' <i>↑</i>',
right: ' <i>→</i>',
down: ' <i>↓</i>',
left: ' <i>←</i>'
});
// Initially add the down and right arrows.
if (_this.not('li ul li').find('ul').length > 0) {
_this.children('a').append($('a').data('arrows').down);
} else if (_this.find('ul').length > 0) {
_this.children('a').append($('a').data('arrows').right);
}
// Hover events for both mouseover and mouseout.
_this.hover(function () {
// Reset the timer if user hovers back over.
if (timer) {
clearTimeout(timer);
timer = null;
}
// Second level mouseover.
if (!_this.children('a').hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
$('li ul > li').mouseover(function (e) {
// Reset the timer if user hovers back over.
if (timer) {
clearTimeout(timer);
timer = null;
}
e.stopPropagation();
if (_this.children('a').hasClass('active')) {
_this.children('a').addClass('active');
_this.children('ul').addClass('fadeout');
}
});
_this.has('ul').children('a').addClass('active');
_this.children('a').find('i').replaceWith($('a').data('arrows').up);
}
// Third level mouseover.
else if (!_this.children('a').hasClass('active') && _this.find('ul').length > 0) {
$('li ul li ul > li').mouseover(function (e) {
// Reset the timer if user hovers back over.
if (timer) {
clearTimeout(timer);
timer = null;
}
e.stopPropagation();
if (_this.children('a').hasClass('active')) {
_this.children('a').addClass('active');
_this.children('ul').addClass('fadeout');
}
});
_this.has('ul').children('a').addClass('active');
_this.children('a').find('i').replaceWith($('a').data('arrows').left);
}
},
function () {
// Second level mouseout.
if (_this.children('a').hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
$('li ul > li').mouseout(function (e) {
// Reset the timer if user hovers back over.
if (timer) {
clearTimeout(timer);
timer = null;
}
e.stopPropagation();
if (_this.children('ul').hasClass('fadeout')) {
_this.children('a').addClass('active');
timer = setTimeout(function () {
_this.children('a').removeClass('active');
_this.children('ul').removeClass('fadeout');
_this.children('a').find('i').replaceWith($('a').data('arrows').down);
}, 1000);
}
});
_this.children('a').removeClass('active');
_this.children('ul').removeClass('fadeout');
_this.children('a').find('i').replaceWith($('a').data('arrows').down);
}
// Third level mouseout.
else if (_this.children('a').hasClass('active') && _this.find('ul').length > 0) {
$('li ul li ul > li').mouseout(function (e) {
// Reset the timer if user hovers back over.
if (timer) {
clearTimeout(timer);
timer = null;
}
e.stopPropagation();
if (_this.children('ul').hasClass('fadeout')) {
_this.children('a').addClass('active');
timer = setTimeout(function () {
_this.children('a').removeClass('active');
_this.children('ul').removeClass('fadeout');
_this.children('a').find('i').replaceWith($('a').data('arrows').right);
}, 1000);
}
});
_this.children('a').removeClass('active');
_this.children('ul').removeClass('fadeout');
_this.children('a').find('i').replaceWith($('a').data('arrows').right);
}
});
});
答案 0 :(得分:0)
我在https://css-tricks.com/dropdown-menus-with-more-forgiving-mouse-movement-paths/找到关于CSS技巧的非常有用的帖子后,我现在解决了这个问题。
在查看了文章中链接的以下CodePen后,我使用了“扩展CSS边界”方法。这包括添加另一个div并扩展子菜单外部的区域,这有效地保持了下拉菜单的活动。一切都有CSS的力量!
我还将整个悬停功能修剪回到下面:
// Add arrows for desktop version of the navigation.
$('nav ul > li').each(function() {
// Defining variables.
var _this = $(this);
var listitems = _this.children('a');
// Arrows stored as data ready to be fetched.
$('a').data('arrows', {
up: '<i class="fa fa-chevron-up"></i>',
right: '<i class="fa fa-chevron-right"></i>',
down: '<i class="fa fa-chevron-down"></i>',
left: '<i class="fa fa-chevron-left"></i>'
});
// Initially add the down and right arrows.
if (_this.not('li ul li').find('ul').length > 0) {
listitems.prepend($('a').data('arrows').down);
}
else if (_this.find('ul').length > 0) {
listitems.prepend($('a').data('arrows').right);
}
// Hover events for both mouseover and mouseout.
_this.hover(function() {
// Second level mouseover.
if (!listitems.hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
listitems.addClass('active');
listitems.find('i').replaceWith($('a').data('arrows').up);
}
// Third level mouseover.
else if (!listitems.hasClass('active') && _this.find('ul').length > 0) {
listitems.addClass('active');
listitems.find('i').replaceWith($('a').data('arrows').left);
}
},
function() {
// Second level mouseout.
if (listitems.hasClass('active') && _this.not('li ul li').find('ul').length > 0) {
listitems.removeClass('active');
listitems.find('i').replaceWith($('a').data('arrows').down);
}
// Third level mouseout.
else if (listitems.hasClass('active') && _this.find('ul').length > 0) {
listitems.removeClass('active');
listitems.find('i').replaceWith($('a').data('arrows').right);
}
});
});