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

私は自分の問題を解決し、すべてのイベントを適切にシーケンスすることができました。実際に何をしているのかを理解するまでには、Deferred を巧みに使用し、多くの試行錯誤を重ねる必要がありました。とにかく、誰かが取り組んでいる何かのためにこのソリューションが必要な場合に備えて...

問題:
私は自分のページにメッセージ ボックス ポップアップを表示して、ブラウザの警告ウィンドウを本質的に置き換える必要がありました。メッセージ ボックスとその内容を表示するために、いくつかのフェード アニメーションとスライド ダウン アニメーションを連鎖させたいと考えました。また、非同期リクエストがサーバーに送信されている間、メッセージ ボックスが最初に表示されたときに、読み込み中の画像がメッセージ ボックスに表示されるようにしました。メッセージ ボックスに応答が表示されます。とはいえ、こんな感じで組み立てました…

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 として設定しました)。背景は同時に表示され、アニメーション化されますが、メッセージ ボックス自体とは無関係です。イベントのシーケンスとタイミングを正しく実行する必要があるため、これはもう 1 つの複雑な問題です。そうしないと、メッセージ ボックスが別のことをしている間に背景があることを行うなど、奇妙な効果が得られます。

スクリプト:
コードを少しきれいにするために、最初の試みで、メッセージ ボックスを操作する一連の関数を使用して、メッセージ ボックスのオブジェクト リテラルを作成しました。多くの調査が必要でしたが、最終的に解決策は、チェーンと Deferred を組み合わせて使用​​することでした。最終的に、私のコードは次のようになります。

    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();
        });
    }
};

ご覧のとおり、非表示/表示シーケンスのいくつかの時点で、Deferred を使用して、新しいイベントを起動する前に特定のイベントを完了できるようにしています。参考までに、これらは私のバインディングです。

    // 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 に答える