我有一个折叠菜单的代码粘贴在下面,或者在jsfiddle上看到它。
问题是,当子菜单处于向上滑动状态,再次单击时,它会停止,但不会向后设置动画(相反,子菜单会跳出,但其容器保持当前高度-jQuery 2.0.0.b1没有跳过)。在Firefox和Chrome中进行了测试,结果相同。
这是一个jQuery错误,还是只有我?
更新:我已经为jQuery提交了一份错误报告,因为我认为这是一个jQuery错误。
更新2:请参阅Brad M对该行为的解释(但我仍然认为这是jQuery的一个问题,需要在内部解决)。
HTML
<ul>
<li><a href="#">Menu1</a></li>
<li class="opened"><a href="#">Submenus 1</a>
<ul class="submenu">
<li><a href="#">submenu1-1</a></li>
<li><a href="#">submenu1-2</a></li>
</ul></li>
<li class="closed"><a href="#">Submenus 2</a>
<ul class="submenu">
<li><a href="#">submenu2-1</a></li>
<li><a href="#">submenu2-2</a></li>
</ul></li>
<li><a href="#">Menu4</a>
</li>
</ul>
Javascript
var initMenu = function() {
$("li.closed > ul.submenu").css("display", "none");
var toggleMenu = function(li) {
if (li.hasClass("opened") || li.hasClass("inslidedown")) {
li.removeClass("opened inslidedown").addClass("inslideup").find("ul").first().stop(true).slideUp({
duration: 1000,
complete: function() {
li.addClass("closed").removeClass("inslideup");
}
});
}
else if (li.hasClass("closed") || li.hasClass("inslideup")) {
li.removeClass("closed inslideup").addClass("inslidedown").find("ul").first().stop(true).slideDown({
duration: 1000,
complete: function() {
li.addClass("opened").removeClass("inslidedown");
}
});
}
};
$("ul").on("click", "li.opened a, li.closed a, li.inslideup a, li.inslidedown a", function(e) {
e.preventDefault();
toggleMenu($(this).closest("li"));
});
};
$(document).ready(function() {
initMenu();
});
.slideDown()
不工作的原因是元素的显示设置为"block",而.slideDown()
通常用于在显示为"none"的元素上调用。在else-if语句中的ul元素上包含.hide()
,以获得您想要的行为。
li
.removeClass("closed inslideup")
.addClass("inslidedown")
.find("ul")
.first()
.hide() // <----
.stop(true)
.slideDown();
这是我的版本:http://jsfiddle.net/RF3xK/4/
Javascript:
$(document).ready(function() {
rotator($('#quotes .textItem:first'));
function rotator(elem) {
elem.slideDown(800, function(){
var me = $(this),
next = me.next(),
prev = me.prev();
if (!next.length) {
next = $('.textItem').first();
next.insertAfter(me);
}
rotator(next);
}).delay(800).slideUp(800);
}
});
CSS:
#quotes { background: #eee;}
#quotes .textItem { display: none; }
请注意,我将.hide()替换为document.ready事件上的那些元素,这是不必要的javascript,你可以像我一样用css来做,js方法的另一个问题是,在很短的一段时间内,它会出现和消失,因为你必须等到所有文档加载后才能隐藏这些元素。
基本上,你应该检查<ul>
下的所有<li>
节点是否都有css类,比如关闭或打开,你可以使用jQuery选择器来实现这一点。
这里有一个快速而肮脏的解决方法,你绝对可以将其重新考虑到更好的逻辑中。
if ($('li[class~="opened"]').length > 0 || $('li[class~="inslidedown"]').length > 0) {
...
}
else if ($('li[class~="closed"]').length > 0 || $('li[class~="inslideup"]').length > 0) {
...
}
第一个问题是由于您使用了.stop()
根据jquery文档,
.stop([clearQueue][,jumpToEnd])
clearQueue类型:布尔一个布尔值,指示是否也删除排队的动画。默认为false。
跳转到结束类型:布尔指示是否立即完成当前动画的布尔值。默认为false。
通常,在处理动画时,您希望使用.stop(false,true)。
至于您的第二个问题,原因是以下jquery/css。
li.removeClass("closed-inslidup")
li.closed>ul{display:none;}
当您移除"closed"类时,ul元素的显示会被设置回默认的"block",因此它会立即显示。向下滑动的动画不会出现,因为元素已经显示(但回调仍在执行)。
目前,我使用的解决方法只是在滑动动画进行时忽略单击事件。刚刚在第23行从.on()
的选择器筛选参数中删除了li.inslideup a, li.inslidedown a
选择器(在jQuery被修复的情况下,保留其他代码不变,但它可以被简化)。
解决方法在jsfiddle上。