将close事件附加到已附加fadeOut的div

时间:2010-08-07 20:44:56

标签: jquery events

我实现了“jquery:novice to ninja”中的“growl”弹出示例,基本上它在浏览器中显示了一个咆哮样式弹出窗口,可以通过单击其中的“关闭”链接来关闭。代码工作得很好,但我希望通过在一段时间之后使用弹出窗口fadeOut来改进它,如果用户从未点击它来关闭它(它可能会变得相当烦人,必须继续关闭它们)。原始代码如下所示:

我在我的HTML中有这个简单的div,并根据书中的示例相应地设置它

   <div id="message_box">
   </div>

这里是jquery代码(再次直接来自本书):

/**
* function that adds notices to growl like message box in bottom right corner
*/
function addNotice(notice) {
   $('<div class="notice"></div>')
      .append('<div class="skin"></div>')
      .append('<a href="#" class="close">close</a>')
      .append($('<div class="content"></div>').html($(notice)))
      .hide()
      .appendTo('#message_box')
      .fadeIn(1000)
}

/**
* event handler for closing growl like message box
*/
$('#message_box')
   .find('.close')
   .live('click', function() {
      $(this)
         .closest('.notice')
         .animate({
            border: 'none',
            height: 0,
            marginBottom: 0,
            marginTop: '-6px',
            opacity: 0,
            paddingBottom: 0,
            paddingTop: 0,
            queue: false
         }, 1000, function() {
            $(this).remove();
         });
});


/* Give it a whirl */
$(document).ready(function() {
   addNotice("<p>Welcome</p>");
});

我只是修改了这样的addNotice函数,添加了fadeOut延迟(我也试过没有延迟,同样的问题):

function addNotice(notice) {
   $('<div class="notice"></div>')
      .append('<div class="skin"></div>')
      .append('<a href="#" class="close">close</a>')
      .append($('<div class="content"></div>').html($(notice)))
      .hide()
      .appendTo('#message_box')
      .fadeIn(1000)
/* This works but seems to disable the close functionality */
      .delay(10000).fadeOut(1000, function(){$(this).remove();});
} .delay(10000).fadeOut(1000, function(){$(this).remove();});

但是当我这样做时,关闭事件不再起作用了;当您单击关闭链接时,该框未关闭。它将在指定的时间后淡出,但我希望用户可以使用这两个选项(立即关闭或只是让它褪色)。

有人可以告诉我我做错了什么吗?为什么关闭事件从未触发/捕获?

干杯, 标记

2 个答案:

答案 0 :(得分:2)

您需要在关闭操作中添加.clearQueue().stop()。动画按顺序,顺序执行,而不是并行执行。由于您将fadeIn排队,并立即排列fadeOut,因此在关闭animate()调用运行之前,这两个都会执行。 stop()将停止当前动画(延迟或淡出),clearQueue将清空动画队列,因此您接下来调用的animate将立即运行:

$('#message_box')
   .find('.close')
   .live('click', function() {
      $(this)
         .closest('.notice')
         .clearQueue()
         .stop()
         .animate({
            border: 'none',
            height: 0,
            marginBottom: 0,
            marginTop: '-6px',
            opacity: 0,
            paddingBottom: 0,
            paddingTop: 0,
            queue: false
         }, 1000, function() {
            $(this).remove();
         });
});

答案 1 :(得分:0)

来自delay()的文档:

  

设置定时器以延迟执行   队列中的后续项目

换句话说,delay()在给定的时间内停止执行任何动画(例如滑动,淡入淡出和其他动画)。在指定的持续时间过去之后,它将恢复动画。

原始案例中会发生以下情况:

  1. 您的通知显示
  2. 您点击关闭
    1. 通知动画并淡出
    2. 添加延迟代码时会发生什么:

      1. 您的通知显示。
      2. 然后在10秒钟后加上延迟。这将阻止任何动画在接下来的10秒内运行
      3. 它将fadeOut(1000, function(){$(this).remove();});添加到动画队列中(这将是延迟10秒后要运行的下一个动画)
      4. 您点击关闭。
        1. 在您之前添加的第一个fadeOut之后,结束动画在队列中排在第2位。换句话说,它没有运行,因为你仍然设置了延迟
        2. 延迟10秒
        3. 您的第一个动画fadeOut(1000, function(){$(this).remove();});正在运行 - 删除通知
        4. 运行您的第二个动画(通过点击关闭触发的动画)。由于您已经删除了上一个动画中的通知,因此无法使用
        5. <小时/> 解决方案。如果在超时延迟过去之前未单击关闭链接,请使用setTimeout设置关闭动画的超时。请参阅接受的答案。留下历史书的答案

          function addNotice(notice) {
             var notice =
             $('<div class="notice"></div>')
                .append('<div class="skin"></div>')
                .append('<a href="#" class="close">close</a>')
                .append($('<div class="content"></div>').html($(notice)))
                .hide()
                .appendTo('#message_box')
                .fadeIn(1000)
          
              /* Close the timeout after 10 seconds */
              setTimeout(function() {
                  notice.fadeOut(1000, function(){$(this).remove();});
              }, 10000);
          }
          

          编辑:在这种情况下,迈克的回答更为优雅。我真的不喜欢使用setTimeout,但如果你在通知中使用其他动画,使用延迟可能会产生一些问题。