0

我一直在尝试将 JQuery 中的一些动画事件与我试图同时或以特定顺序发生的许多其他过程进行排序时遇到了一些困难。这基本上是我想要完成的事情:

  1. 用户单击一个按钮,这会导致自定义 div 弹出框出现在屏幕上。
  2. 弹出框与其背景一起动画。
  3. 弹出框显示一条加载消息,同时它还向服务器发送(延迟 1.5 秒后)一个 Ajax 请求,以下拉指定的内容,然后将这些内容加载到弹出框中。
  4. 然后,加载文本的弹出框应该被通过侧向检索的内容替换。
  5. 当用户阅读消息时,他/她可以点击弹出框的关闭图标或点击退出键来关闭弹出框。
  6. 弹出窗口通过淡出动画关闭。

使用我当前的代码(下面的 JSFiddle 链接),这似乎可以正常工作,并且弹出动画和排序将正确显示,前提是用户在单击按钮再次显示之前先关闭弹出窗口。但是(这是我的问题)...如果弹出窗口保持打开状态并且用户再次单击该按钮,则动画的顺序会变得混乱...似乎事件链分崩离析-过程显示弹出窗口不会首先等待弹出窗口关闭,并且您会得到可怕的效果。

关于如何解决这个问题的任何想法?

理想情况下,正如代码中的逻辑所暗示的,我们希望等待弹出窗口的关闭动画完全完成,然后再开始弹出窗口的显示动画。说到JQuery,我还是有点菜鸟,请见谅。我试图做一些研究,并相信解决方案可能在于以某种巧妙的方式使用 Deferreds。然而,我认为你们可能会提供一个伟大的、有效的、最新的解决方案,并防止我把我所有的头发都拔掉。=)

这是我的代码(在某些地方有所简化,但仍然很好地模仿了问题):

http://jsfiddle.net/Nickel3ack/kdcwT/21/

4

1 回答 1

0

我设法解决了我的问题并让我的所有事件都正确排序。在我掌握我实际在做的事情之前,我巧妙地使用了 Deferreds 并进行了大量的试验和错误。无论如何,如果有人需要这个解决方案来解决他们正在做的任何事情......

问题:
我希望在我的页面上弹出一个消息框,以从本质上替换浏览器的警报窗口以达到我的目的。我想链接一些淡入淡出和滑动动画来显示消息框,然后显示它的内容。我还希望加载图像在第一次出现时出现在消息框中,同时向服务器发送异步请求。消息框将显示响应。反正我是这样设置的...

在我的 html 正文中,我包含了消息框容器:

<div id="msg-box">
<div id="msg-box-container">
    <div id="msg-box-headbar">
        <div id="msg-box-title"></div>
        <div id="msg-box-clButton"></div>
    </div>
    <div id="msg-box-content"></div>
    <div id="msg-box-footbar"></div>
</div>
</div>
<div id="msg-box-backdrop"></div>

如您所见,我的消息框还有一个背景(我将其设置为位于消息框容器之外的半透明 div)。背景将同时显示和动画,但独立于消息框本身。这是另一个复杂因素,因为事件的顺序和时间必须正确执行,否则我们会得到奇怪的效果……比如背景在做一件事,而消息框在做另一件事。

脚本:
为了使我的代码更简洁,在我的第一次尝试中,我为消息框创建了一个对象字面量,其中包含一组用于操作消息框的函数。这需要大量研究,但最终的解决方案是使用链式和延迟的组合。最后,我的代码如下所示:

    var msgBox = {
    status: 0,
    self: $('#msg-box'),
    title: $('#msg-box-title'),
    cl_button: $('#msg-box-clButton'),
    content: $('#msg-box-content'),
    backdrop: $('#msg-box-backdrop'),

    hideBox: function() {
        var b = this;
        if (b.status == 1) {
            var dfd = $.Deferred();
            b.self.fadeOut(500);
            b.backdrop.fadeOut(500, dfd.resolve);
            b.status = 0;
            return dfd.promise();
        }
    },

    showBox: function(ttl, msg) {
        var b = this;
        if (b.status == 1) {
            $.when(b.hideBox()).then(function() {
                b.doShow();
                b.loadCont(ttl, msg);
            });
        }
        else {
            if(b.backdrop.queue().length > 0) {
                $.when(b.backdrop.queue()).done( function() {
                    b.doShow();
                    b.loadCont(ttl, msg);
                });
            }
            else {
                b.doShow();
                b.loadCont(ttl, msg);
            }
        }
    },

    doShow: function() {
        var b = this;
        b.title.text('Loading...');
        b.content.html('<div id="msg-box-loader"><img id="loading-img" src="/graphics/loader-16.gif" /></div>');
        b.backdrop.height(b.self.height());
        b.self.centerBox($(window).width());
        b.backdrop.centerBox($(window).width());
        b.self.fadeIn('fast');
        b.backdrop.corner('round 6px').fadeTo('fast', 0.6);
    },

    loadCont: function(ttl, msg) {
        var b = this;
        b.content.delay(1500).queue(function(next) {
            b.title.text(ttl);
            b.content.text(msg).slideDown('fast');
            b.backdrop.height(b.self.height()).slideDown('fast');
            b.status = 1;
            next();
        });
    }
};

如您所见,在隐藏/显示序列中的几个点,我使用 Deferreds 来允许某些事件在启动新事件之前完成。作为参考,这些是我的绑定:

    // events related to message box
$(document).keydown( function(e) {
    if (e.keyCode == 27) {
        e.preventDefault();
        if(msgBox.status == 1)
            msgBox.hideBox();
    }
});
msgBox.cl_button.hover( function() { $(this).toggleClass('no-hover').toggleClass('hover'); });
msgBox.self.on('click', msgBox.cl_button.selector, function() { msgBox.hideBox();  });
$(window).resize(function() {
    if (msgBox.status == 1) {
        msgBox.self.centerBox($(window).width());
        msgBox.backdrop.centerBox($(window).width());
    }
});

// login form submitted
$('#login-form').submit( function(e) { 
    e.preventDefault();
    var postData = 'async=login&user='+$('#login-user').val()+'&pass='+hex_md5($('#login-pass').val());
    $.ajax({ type: 'POST', url: "index.php", data: postData, 
        success: function(response) { 
            if(response==0) msgBox.showBox('Login Failed', 'Invalid Credentials'); 
            else if(response==1) msgBox.showBox('Success', response); 
            else msgBox.showBox('Internal Error', 'There was an internal error. Please contact the administrator.<br><br>'+response); 
        },
        error: function() { 
            msgBox.showBox('Internal Error', 'There was an internal error. Please contact the administrator.'); 
        } 
    });
});
于 2012-03-05T19:37:39.887 回答