私のアプリケーションにはフォームのあるページがいくつかあります。
ユーザーが別の場所に移動したり、ブラウザ タブを閉じたりした場合に、未保存のデータを残したままフォームを離れてもよいかどうかを確認するメッセージが表示されるように、フォームを保護するにはどうすればよいですか?
ベストアンサー1
短い、間違った答え:
これをするにはイベントを処理しbeforeunload
、null以外の文字列を返す:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
このアプローチの問題は、フォームを送信すると unload イベントも発生することです。これは、フォームを送信していることを示すフラグを追加することで簡単に修正できます。
var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting) {
return undefined;
}
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
次に、送信時にセッターを呼び出します。
<form method="post" onsubmit="setFormSubmitting()">
<input type="submit" />
</form>
しかし、読み続けてください...
長い、正しい答え:
また、ユーザーがフォーム上で何も変更していない場合にも、このメッセージは表示したくないでしょう。 1 つの解決策は、イベントを「ダーティ」フラグと組み合わせて使用することですbeforeunload
。これにより、本当に関連がある場合にのみプロンプトがトリガーされます。
var isDirty = function() { return false; }
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting || !isDirty()) {
return undefined;
}
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
この方法を実装するにはisDirty
、さまざまなアプローチがあります。
使用できますjQuery とフォームのシリアル化ただし、このアプローチにはいくつか欠点があります。まず、任意のフォームで動作するようにコードを変更する必要があります (これで$("form").each()
十分です)。しかし、最大の問題は、jQuery はserialize()
名前付きの無効でない要素でのみ動作するため、無効または名前のない要素を変更しても、ダーティ フラグがトリガーされないことです。それには回避策があるコントロールを有効にしてシリアル化し、再度無効にするのではなく、コントロールを読み取り専用にするなどです。
だからイベントは良い方法のようです。キー入力を聴くこのイベントにはいくつかの問題があります:
- チェックボックス、ラジオ ボタン、またはマウス入力によって変更されるその他の要素ではトリガーされません。
- キーのような無関係なキー押下に対してトリガーされますCtrl。
- JavaScript コードを通じて設定された値ではトリガーされません。
- コンテキスト メニューからテキストを切り取ったり貼り付けたりしてもトリガーされません。
- JavaScript を通じて非表示の入力に値を保存する日付ピッカーやチェックボックス/ラジオボタンの美化機能などの仮想入力では機能しません。
のchange
イベントまたJavaScript コードから設定された値ではトリガーされません、仮想入力にも機能しません。
すべての(およびと)input
にイベントをバインドするinput
textarea
select
あなたのページに古いブラウザでは動作しませんまた、上記のすべてのイベント処理ソリューションと同様に、元に戻す機能はサポートされていません。ユーザーがテキスト ボックスを変更して元に戻したり、チェック ボックスをオンにしたりオフにしたりすると、フォームは依然としてダーティと見なされます。
さらに、特定の要素を無視するなど、さらに多くの動作を実装したい場合は、さらに多くの作業が必要になります。
車輪の再発明はしないでください。
したがって、これらのソリューションと必要なすべての回避策の実装を検討する前に、車輪の再発明をしており、他の人がすでに解決した問題に遭遇する傾向があることを認識してください。
アプリケーションで既に jQuery を使用している場合は、独自のコードを作成するのではなく、テスト済みでメンテナンスされたコードを使用し、これらすべてにサードパーティのライブラリを使用することもできます。
jquery.dirty(コメントで @troseman が提案) は、フォームが変更されたかどうかを適切に検出し、プロンプトを表示している間にユーザーがページを離れないようにする機能を提供します。また、フォームをリセットしたり、フォームの現在の状態を「クリーン」な状態に設定するなどの便利な機能もあります。使用例:
$("#myForm").dirty({preventLeaving: true});
現在は放棄されている古いプロジェクトはjQuery の Are You Sure? プラグイン、これもうまく機能します。デモページ使用例:
<script src="jquery.are-you-sure.js"></script>
<script>
$(function() {
$('#myForm').areYouSure(
{
message: 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.'
}
);
});
</script>
カスタムメッセージはすべての場所でサポートされているわけではありません
ご注意ください2011年からFirefox 4このダイアログではカスタムメッセージはサポートされていません。2016年4月現在、Chrome 51が展開されています。カスタムメッセージも削除されている。
このサイトの他の場所にもいくつか代替手段がありますが、次のようなダイアログで十分明確だと思います。
このサイトを離れますか?
変更内容は保存されない可能性があります。
Leave Stay