インターセプトページ終了イベント


117

システム内のページを編集するときに、ユーザーが別のWebサイトに移動することを決定した場合、保存していないすべての編集内容が失われる可能性があります。

現在の作業が失われる可能性があるため、別のページに移動しようとする試みを阻止して、これを実行することをユーザーに確認したいと考えています。

Gmailはこれを非常によく似た方法で行います。たとえば、新しいメールを作成し、メッセージ本文に入力を開始して、アドレスバーに新しい場所を入力します(たとえば、twitter.comなど)。「よろしいですか?」

これを複製する方法は?IE8をターゲットにしていますが、FFおよびChromeにも対応したいと考えています。


回答:


154

Ghommeyの回答に似ていますが、これはIEとFirefoxの古いバージョンもサポートしています。

window.onbeforeunload = function (e) {
  var message = "Your confirmation message goes here.",
  e = e || window.event;
  // For IE and Firefox
  if (e) {
    e.returnValue = message;
  }

  // For Safari
  return message;
};

1
最初の行を説明してください(var message = ...)?そのカンマと2番目の式が何をしているのかわかりません。
mtmurdock 2012

7
@mtmurdockこれは、複数の変数を宣言するJavascript構文です。 var foo, bar;と同じですvar foo; var bar;
T Nguyen

4
@ mtmurdock、2番目のステートメント " var e = e || window.event;" これは、eをパラメーターe(真である場合)に、またはwindow.eventが真でない場合に等しく設定することを意味します。パラメータeがnullの場合は真実ではありません。
T Nguyen

3
@Blieque addEventListenerはIE8ではサポートされていません。質問を読まなくても、人々の回答を編集しないでください。
イーライグレイ

2
Chromeでこれ以上は動作しません(非推奨):developers.google.com/web/updates/2016/04/...
ミカ・シュワブ

25

この記事を参照してください。あなたが探している機能はonbeforeunloadです

サンプルコード:

  <script language="JavaScript">
  window.onbeforeunload = confirmExit;
  function confirmExit()
  {
    return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
  }
</script>

2
ユーザーが「このページにとどまる」ではなく「このページを離れる」オプションを選択したことを確認する方法はありますか?
Shilpa Soni

@ShilpaSoniあなたはすぐに後続のアンロードイベント、developer.mozilla.org / en-US / docs / Web / API / Window / unload_eventを取得しますが、同期的な方法はないと思います。
scipilot

6

迷惑な確認ポップアップの代わりに、サーバーに未保存のデータを正常にポストするために少し(ミリ秒単位)離れるの遅らせて、次のようにダミーテキストをコンソールに書き込むことでサイト用に管理しました。

window.onbeforeunload=function(e){
  // only take action (iterate) if my SCHEDULED_REQUEST object contains data        
  for (var key in SCHEDULED_REQUEST){   
    postRequest(SCHEDULED_REQUEST); // post and empty SCHEDULED_REQUEST object
    for (var i=0;i<1000;i++){
      // do something unnoticable but time consuming like writing a lot to console
      console.log('buying some time to finish saving data'); 
    };
    break;
  };
}; // no return string --> user will leave as normal but data is send to server

編集:Synchronous_AJAXjqueryでそれを行う方法 も参照してください


ポップアップのこの代替案が好きです。提案をありがとう、レミ。
Chris Ballance、2012年

2
それはまったく意味がありません-1。javascriptがスレッド化されていないため、postRequestを実行し、誰も何もしないようにせずにサイトの計算を一時停止しています(postRequestを含み、その間、計算は一時停止する前に送信されていました)。
fmsf 2012

そして、それが機能する理由です。実際、post-requestは計算が一時停止する前に送信されましたが、実際に残される前にこの小さなページのブロックにより、ブラウザークライアント(javascriptではない)がこの要求を正しく送信するのに十分な時間が保証されます。 。(ブロックせずに)リクエストのみを送信し、直後にページを離れると、リクエストが常に送信されるわけではないことに気付きました。
レミ

6
本番環境では使用しません。console.logはクロスブラウザではありません。各postRequestは前のpostRequestの遅延の影響を受けます(これは、ループ*スケジュールされたリクエストの期間中、ページがそこでハングすることも意味します)。リクエストは並行して開始されません。実際にリクエストを送信することは保証されていません。この問題に直面することを余儀なくされた場合、リクエストが1つしかない場合は、同期ajaxリクエストを使用します。複数のリクエストでは、非同期ajaxリクエストと、リクエストのコールバックからの結果(成功またはエラー)をチェックするループを使用します。
2012

console.logがクロスブラウザではなく、同期Ajaxリクエストが実際に推奨されるソリューションであることを知りませんでした(単一のリクエストの場合)。言及されているのSCHEDULED_REQUESTは、データのバッファーのようにサーバーに送信する必要がある緊急ではない情報を蓄積し、複数の要求を1つの要求に効果的に結合するオブジェクトです(もちろん、これらの要求のURLは同じです)。アンロードする前に同期Ajax要求を使用すると、問題のあるブラウザー間で問題が解決するはずです。貴重なコメントありがとうございます!
Remi

0

必要なデータをすべて入力していないユーザーがいます。

<cfset unloadCheck=0>//a ColdFusion precheck in my page generation to see if unload check is needed
var erMsg="";
$(document).ready(function(){
<cfif q.myData eq "">
    <cfset unloadCheck=1>
    $("#myInput").change(function(){
        verify(); //function elsewhere that checks all fields and populates erMsg with error messages for any fail(s)
        if(erMsg=="") window.onbeforeunload = null; //all OK so let them pass
        else window.onbeforeunload = confirmExit(); //borrowed from Jantimon above;
    });
});
<cfif unloadCheck><!--- if any are outstanding, set the error message and the unload alert --->
    verify();
    window.onbeforeunload = confirmExit;
    function confirmExit() {return "Data is incomplete for this Case:"+erMsg;}
</cfif>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.