[解決済み】未保存の変更を含むウェブページを離れる前にユーザーに警告を表示する
質問
私のアプリケーションには、フォームがあるページがいくつかあります。
誰かがナビゲートしたり、ブラウザのタブを閉じたりした場合、未保存のデータを残して本当にフォームを残してよいか確認するよう促すには、どうしたらよいでしょうか?
どのように解決するのですか?
短く、間違った答え。
によって行うことができます。
を処理します。
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>
でも、読んでみてください...
長文、正解です。
また、次のようなメッセージも表示させないようにします。
ユーザーがフォーム上で何も変更していない場合
. 一つの解決策は
beforeunload
イベントを "dirty" フラグと組み合わせて使用すると、本当に関連性のある場合のみプロンプトが表示されるようになります。
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()
は、名前がついていて無効になっていない要素にのみ作用するので、無効になっている要素や名前のついていない要素を変更しても、dirty フラグは発動しません。
そのための回避策があります
例えば、コントロールを有効にする代わりに、コントロールを読み取り専用にし、シリアライズしてから再び無効にすることができます。
だから、イベントがいいみたいです。試してみてください。 キー入力をリスニングする . このイベントには、いくつかの問題があります。
- チェックボックス、ラジオボタンなど、マウス入力で変更される要素ではトリガーされません。
- のような無関係なキー入力に対してもトリガーされます。 Ctrl キーを使用します。
- JavaScriptのコードで設定した値ではトリガーしないようにしました。
- コンテキストメニューからテキストをカットまたはペーストしてもトリガーされません。
- JavaScriptでhidden inputに値を保存するdatepickersやcheckbox/radiobutton beautifiersのような仮想入力では動作しません。
は
change
イベント
また
は、JavaScriptのコードから設定された値にはトリガーしません。
そのため、バーチャルインプットには使えません。
バインディング
input
イベントをすべての
input
の(そして
textarea
と
select
s)
をあなたのページで
は古いブラウザでは動作しません
また、上記のすべてのイベント処理ソリューションと同様に、アンドゥをサポートしていません。ユーザーがテキストボックスを変更した後にそれを取り消したり、チェックボックスをチェックしたり外したりすると、フォームはまだ汚れているとみなされます。
また、特定の要素を無視するなど、より多くの動作を実装したい場合は、さらに多くの作業が必要になります。
車輪の再発明をしないでください。
そのため、これらのソリューションや必要な回避策を実行しようと考える前に、車輪の再発明をすることになり、他の人がすでに解決している問題にぶつかる可能性があることを認識しておいてください。
もしあなたのアプリケーションがすでにjQueryを使用しているなら、自分でローリングするのではなく、テストされメンテナンスされたコードを使用し、これら全てにサードパーティライブラリを使用した方がよいでしょう。
jquery.dirty (@troseman がコメントで提案してくれた) は、フォームが変更されたかどうかを適切に検出し、プロンプトを表示中にユーザーがページから離脱するのを防ぐ機能を提供します。また、フォームをリセットしたり、現在のフォームの状態を "clean" とするなどの便利な機能も備えています。使用例です。
$("#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がロールアウトされています。 カスタムメッセージも削除される .
このサイトの他の場所にも代替案がありますが、このようなダイアログで十分わかりやすいと思います。
このサイトを離れたいですか?
変更した内容が保存されない場合があります。
去る 滞在
関連
-
[解決済み】JavaScriptのisset()に相当するもの
-
[解決済み】Google Conversionsが動作しない - スクリプトが読み込まれない
-
[解決済み】SyntaxError: ChromeのJavascriptコンソールでUnexpected Identifierが発生する。
-
[解決済み】HTMLの最初の行に予期しないトークン<がある。
-
[解決済み】未定義のプロパティ 'forEach' を読み取ることができない
-
[解決済み] jquery beforeunload ページを閉じる(離脱しない)とき?
-
[解決済み] jQueryでページを更新するにはどうすればよいですか?
-
[解決済み] 画面サイズ、現在のウェブページ、ブラウザウィンドウのサイズを取得する
-
[解決済み] ブラウザウィンドウで現在のタブを閉じるには?
-
[解決済み] chromedriverでSeleniumを使用していることをWebサイトで検出することは可能ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 Uncaught TypeError: data.push is not a function
-
[解決済み】Uncaught TypeError: nullのプロパティ'value'を読み取ることができない
-
[解決済み】Angular JS Uncaught Error。[インジェクター:モジュラー]。
-
[解決済み】SyntaxError: ChromeのJavascriptコンソールでUnexpected Identifierが発生する。
-
[解決済み】WebpackとBabelで「このファイルタイプを扱うには適切なローダーが必要な場合があります。
-
[解決済み】Javascript - ERR_CONTENT_LENGTH_MISMATCH
-
[解決済み】Syntax error: JavaScriptの不正なreturnステートメント
-
[解決済み] テキストボックスの内容が変更されたことを検出する方法
-
[解決済み】jQueryの「input」イベント
-
[解決済み] 無効化された :input 要素を $.serialize() に考慮させるにはどうしたらいいですか?