在slideUp()期间使用stop(true).slideDown()问题,是一个jquery错误?

时间:2013-02-20 01:30:37

标签: jquery html

我有下面粘贴的折叠菜单的代码,或者在jsfiddle上看到它。

问题是当子菜单处于向上滑动状态,并且再次单击它时,它会停止但不会向后动画(相反,子菜单会跳出但是它们的容器保持其当前高度 - 不会跳转到jQuery 2.0.0.b1)。在Firefox和Chrome中测试结果相同。

这是一个jQuery错误,还是只是我?

更新:jQuery我有filed a bug report,因为我认为这是一个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();
});

5 个答案:

答案 0 :(得分:3)

.slideDown()无效的原因是因为元素的显示设置为“阻止”,而.slideDown()通常用于在显示“无”的元素上调用。 在else if语句的ul元素中包含.hide()以获得所需的行为。

li
    .removeClass("closed inslideup")
    .addClass("inslidedown")
    .find("ul")
    .first()
    .hide()   //   <----
    .stop(true)
    .slideDown();

答案 1 :(得分:0)

这是我的版本: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方式的另一个问题是,在一瞬间出现和消失,因为你必须等到加载所有文档才能隐藏这些元素。

答案 2 :(得分:0)

基本上你应该检查<li>下的所有<ul>节点是否有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) {
    ...
}

答案 3 :(得分:0)

第一个问题是由于您使用了.stop()

根据jquery文档,

  

.stop([clearQueue] [,jumpToEnd])

     
    

clearQueue     类型:布尔值     一个布尔值,指示是否也删除排队的动画。默认为false。

         
      

jumpToEnd       类型:布尔值       一个布尔值,指示是否立即完成当前动画。默认为false。

    
  

通常,您希望在处理动画时使用.stop(false,true)。

至于你的第二个问题,原因是由于以下jquery / css。

  

li.removeClass(“关闭inslideup”)

     
    

li.closed&gt; ul {display:none; }

  

当您删除“已关闭”类时,ul元素的显示将被设置回默认的“块”,因此它会立即显示。滑动动画不会发生,因为元素已经显示(尽管回调仍在执行)。

答案 4 :(得分:0)

目前我正在使用一种解决方法,在滑动动画进行过程中忽略了click事件。 刚从第23行的li.inslideup a, li.inslidedown a选择器过滤参数中删除了.on()选择器(如果jQuery得到修复,其他代码保持不变,但可以简化)。

解决方法位于jsfiddle