私は自分の問題を解決し、すべてのイベントを適切にシーケンスすることができました。実際に何をしているのかを理解するまでには、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.');
}
});
});