CV率アップ!ユーザーの離脱は、jQueryのアラート(ポップアップ)で防ぐ!
PCだけならbeforeunloadでできますが、iOSなどのスマホのブラウザでは、popstateやhashchangeをトリガーにして発火しないので、スマホでも動作するよう対策も。
サンプルを用意しました。
jQuery関連記事
【jQuery】pdfが存在するか、mimeタイプのバリデーションする
jQuery UIのsortableを使ってリストをドラッグで並び替える
jQueryのモーダルウィンドウを使ってフォームの確認画面を実装する
HTMLのcanvasタグとJavaScriptで円グラフの画像をつくる
bxSliderをカルーセルやコンテンツスライダーなど便利なサンプル5種
bxSliderの使い方と、オプションでのカスタマイズ方法
select・optionタグをjQueryで、プルダウンの選択値を取得、変更する
jQueryでinput[type="file"]で画像アップロード時にプレビューを表示する
jQueryでrequiredの専用エラー文と文字数制限のバリデーションをつくる
ページ移動しようとしたらアラートを出す
JavaScript
$(window).on('beforeunload', function() { return "ページを移動しようとしています。\n入力した内容が失われますがよろしいですか?"; });
beforeunload
のイベントを使って処理します。離脱しようとしたらreturn
の内容とともにalert
が出ます。
途中で改行したい場合は\n
で改行できます。
※beforeunload
不適切に使われることが多かった結果、IE/Edgeを除いて固定メッセージしか出せないようになっています。
フォームに入力したときだけ、ページ移動しようとしたらアラートを出す
JavaScript
changeFlg = false; $(window).on('beforeunload', function() { if (changeFlg) { return "ページを移動しようとしています。\n入力した内容が失われますがよろしいですか?"; } }); $("form input, form textarea, form select").change(function() { changeFlg = true; });
changeFlg
で入力の有無でフラグを立て、フラグがある時のみbeforeunload
の処理をします。
.change
でフォームの部品が変更されたらフラグを立てます。
送信ボタンは除外する
JavaScript
$(function(){ changeFlg = false; $(window).on('beforeunload', function() { if (changeFlg) { return "ページを移動しようとしています。\n入力した内容が失われますがよろしいですか?"; } }); $("form input, form textarea, form select").change(function() { changeFlg = true; }); $("input[type=submit]").click(function() { changeFlg = false; }); });
上のままだと、送信ボタンを押したときでもアラートが出てしまうので、送信ボタンを押したときはchangeFlg
を消しています。
ちなみにjQueryの本体が古いと動かない場合があるので1.9以上に上げると動くと思います。
スマホにも対応する
※2020/07追記
スマホ版が動かなかったので修正しました。
ただ、別ページへ移動・タブを閉じるでは処理されず、
戻る操作を行ったときにしか処理できません。
history.jsを準備する
Gitからhistory.jsをDLして、読み込んでください。
history.jsは古いブラウザではpushStateやpopstateが対応していないので、それらに対応するためにHistoryライブラリをオーバライドするライブラリです。
Bootstrapを準備する
BootstrapをDLして、bootstrap.min.cssとbootstrap.min.jsを読み込んでください。

popstateやhashchangeをトリガーにして動かす処理が、スマホのブラウザでは、alertやconfirmは動作しません。
面倒なのでBootstrapのmodalを使ってアラートを表示しています。
モーダルを設置する
html
<div class="modal" tabindex="-1" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> </div><!-- /.modal-header --> <div class="modal-body"> <p>入力途中ですがキャンセルしてよろしいですか?</p> </div><!-- /.modal-body --> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">いいえ</button> <button type="button" id="back" class="btn btn-primary">はい</button> </div><!-- /.modal-footer --> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal -->
「はい」ボタンにidを振ってあります。
JavaScriptを設置する
JavaScript
$(function(){ var hash = location.hash; if(hash != '#message') { // pushStateで現在のURLを履歴にスタックする history.pushState(null,null,location.href); // URLにtagを設置する location.hash = '#message'; } // URLが変更されるのを監視 $(window).on('popstate',function(event){ if(location.hash != '#message') { // モーダルを実行 $('#modal').modal('show'); } }); $('#back').click(function() { history.back(); return false; }); });
処理的には一旦ページがロードされると、URLに#messageのアンカーを付けてpushStateで履歴をスタックする。
popstateでurlが変更されたときに処理を発火させて、戻るで#messageが消えたときにモーダルが起動。
その中でページを戻るかそのページにとどまるかを選択。
戻る場合は、history.back();
で戻るようにしている。
コメント
初めまして!
現在ページ離脱防止の実装で、参考にさせていただいてます!
DEMOページを見たのですが、
スマホのsafariやchromeで見ても
ダイアログが出てこないのですが、
バージョンや仕様が変わったとか
ありますでしょうか?
この記事を作成しているときにスマホは気にしていなかったのですが、この方法ではスマホは反応しないようです。
pagehideで判別する必要があるみたいですがbeforeunloadとは挙動が違うようです。