web-dev-qa-db-ja.com

ユーザーが戻るボタンを使用してページにアクセスしたかどうかを検出するにはどうすればよいですか?

この質問は ユーザーがブラウザの戻るボタンを押したときに追跡する に似ていますが、同じではありません...解決策があり、参照とフィードバックのためにここに投稿しています。誰もがより良いオプションを持っている場合、私はすべて耳です!

状況は、「インプレース編集」、la flickrのあるページがあることです。つまり「ここをクリックして説明を追加」DIVがあります。DIVをクリックすると、[保存]ボタンと[キャンセル]ボタンのあるTEXTAREAに変わります。 [保存]をクリックすると、データがサーバーに送信されてデータベースが更新され、TEXTAREAの代わりに新しい説明がDIVに配置されます。ページが更新されると、「クリックして編集」オプションを使用して、データベースから新しい説明が表示されます。最近ではかなり標準的なWeb 2.0のもの。

問題は次の場合です。

  1. ページは説明なしでロードされます
  2. 説明はユーザーによって追加されます
  3. リンクをクリックすると、ページが移動します
  4. ユーザーが戻るボタンをクリックする

(ブラウザのキャッシュから)表示されるのは、新しい説明を含む動的に変更されたDIVのないページのバージョンです。

ユーザーは更新が失われたと仮定し、変更を確認するためにページを更新する必要があることを必ずしも理解しないため、これはかなり大きな問題です。

したがって、質問は次のとおりです。ロード後にページに変更済みのフラグを付け、ユーザーが「戻った」ときにそれを検出し、その状況で強制的に更新する方法はありますか。

86
Tom

非表示のフォームを使用します。リロードするか、戻るボタンを押してページに戻ると、フォームデータは(通常)ブラウザーに保存されます。次の内容がページに表示されます(おそらく下部近く)。

<form name="ignore_me">
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>

JavaScriptには、次のものが必要です。

var dirty_bit = document.getElementById('page_is_dirty');
if (dirty_bit.value == '1') window.location.reload();
function mark_page_dirty() {
    dirty_bit.value = '1';
}

フォームをスニッフィングするjsは、htmlが完全に解析された後に実行する必要がありますが、ユーザーの待ち時間が深刻な懸念事項である場合は、フォームとjsの両方をページの先頭(js秒)にインラインで配置できます。

77
Nick White

この古い問題に対する非常に簡単な最新のソリューションを次に示します。

if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
    alert('Got here using the browser "Back" or "Forward" button.');
}

window.performanceは現在、すべての主要なブラウザーでサポートされています。

44
Bassem

この記事ではそれについて説明します。以下のコードを参照してください: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

<html>
    <head>
        <script>

            function pageShown(evt){
                if (evt.persisted) {
                    alert("pageshow event handler called.  The page was just restored from the Page Cache (eg. From the Back button.");
                } else {
                    alert("pageshow event handler called for the initial load.  This is the same as the load event.");
                }
            }

            function pageHidden(evt){
                if (evt.persisted) {
                    alert("pagehide event handler called.  The page was suspended and placed into the Page Cache.");
                } else {
                    alert("pagehide event handler called for page destruction.  This is the same as the unload event.");
                }
            }

            window.addEventListener("pageshow", pageShown, false);
            window.addEventListener("pagehide", pageHidden, false);

        </script>
    </head>
    <body>
        <a href="http://www.webkit.org/">Click for WebKit</a>
    </body>
</html>
13
Drew Baker

onbeforeunloadイベントを使用して解決できます:

window.onbeforeunload = function () { }

onbeforeunload空のイベントマネージャー関数を使用すると、アクセスされるたびにページが再構築されます。 Javascriptが再実行され、サーバー側のスクリプトが再実行されます。ユーザーは、戻るまたは進むボタンを押すだけでページにアクセスした場合でも、ユーザーが初めてページをヒットしたかのようにページが構築されます。 。

例の完全なコードは次のとおりです。

<html>
<head>
<title>onbeforeunload.html</title>
<script>
window.onbeforeunload = function () { }

function myfun()
{
   alert("The page has been refreshed.");
}
</script>

<body onload="myfun()">

Hello World!<br>

</body>
</html>

それを試して、このページを移動してから、ブラウザの「戻る」または「進む」ボタンを使用して戻ってください。

IE、FF、Chromeで正常に動作します。

もちろん、myfun関数内で何でもできます。

詳細: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

2
Nes

LocalStorageまたはsessionStorage( http://www.w3schools.com/html/html5_webstorage.asp )を使用して、フラグを設定できます(非表示フォームを使用する代わりに)。

2
rerezz

上記のように、解決策を見つけたので、参照とフィードバックのためにここに投稿しています。

ソリューションの最初の段階は、ページに以下を追加することです。

<!-- at the top of the content page -->
<IFRAME id="page_is_fresh" src="fresh.html" style="display:none;"></IFRAME>
<SCRIPT style="text/javascript">
  function reload_stale_page() { location.reload(); }
</SCRIPT>

fresh.htmlの内容は重要ではないため、以下で十分です。

<!-- fresh.html -->
<HTML><BODY></BODY></HTML>

クライアント側のコードがページを更新するとき、次のように変更にフラグを立てる必要があります。

function trigger_reload_if_user_clicks_back_button()
{
  // "dis-arm" the reload stale page function so it doesn't fire  
  // until the page is reloaded from the browser's cache
  window.reload_stale_page = function(){};

  // change the IFRAME to point to a page that will reload the 
  // page when it loads
  document.getElementById("page_is_fresh").src = "stale.html";
}

stale.htmlはすべての作業を行います。ロードされると、必要に応じてページを更新するreload_stale_page関数を呼び出します。最初にロードされたとき(つまり、変更が行われた後、reload_stale_page関数は何もしません。)

<!-- stale.html -->
<HTML><BODY>
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT>
</BODY></HTML>

この段階での私の(最小限の)テストから、これは望みどおりに動作するようです。見落としがありますか?

2
Tom

このページを使用して、特に@Nick Whiteによる回答についての@sajithによるコメントとこのページを組み込みます。 http://www.mrc-productivity.com/techblog/?p=1235

<form name="ignore_me" style="display:none">
    <input type="text" id="reloadValue" name="reloadValue" value="" />
</form>

$(function ()
{
    var date = new Date();
    var time = date.getTime();

    if ($("#reloadValue").val().length === 0)
    {
        $("#reloadValue").val(time);
    }
    else
    {
        $("#reloadValue").val("");
        window.location.reload();
    }
});
1
nmit026

これがjQueryバージョンです。ユーザーが戻るボタンを押したときにSafariデスクトップ/モバイルがキャッシュを処理する方法のため、数回使用する必要が生じました。

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        // Loading from cache
    }
});
1
Wes

今日、同様の問題に遭遇しましたが、localStorage(ここでは少しjQueryを使用)で解決しました。

$(function() {

    if ($('#page1').length) {
        // this code must only run on page 1

        var checkSteps = function () {
            if (localStorage.getItem('steps') == 'step2') {
                // if we are here, we know that:
                // 1. the user is on page 1
                // 2. he has been on page 2
                // 3. this function is running, which means the user has submitted the form
                // 4. but steps == step2, which is impossible if the user has *just* submitted the form
                // therefore we know that he has come back, probably using the back button of his browser
                alert('oh hey, welcome back!');
            } else {
                setTimeout(checkSteps, 100);
            }
        };

        $('#form').on('submit', function (e) {
            e.preventDefault();
            localStorage.setItem('steps', 'step1'); // if "step1", then we know the user has submitted the form
            checkOrderSteps();
            // ... then do what you need to submit the form and load page 2
        });
    }

    if ($('#page2').length) {
        // this code must only run on page 2
        localStorage.setItem('steps', 'step2');
    }

});

Si基本的に:

1ページ目で、ユーザーがフォームを送信すると、localStorageに値「steps」を設定して、ユーザーが実行したステップを示します。同時に、この値が変更されたかどうかを確認するタイムアウトを使用して関数を起動します(たとえば、10回/秒)。

2ページで、上記の値をすぐに変更します。

したがって、ユーザーが戻るボタンを使用し、ブラウザーがページ1を元の状態に復元した場合、checkSteps関数は引き続き実行され、localStorageの値が変更されたことを検出できます(適切なアクションを実行できます) )。このチェックの目的が満たされると、実行を継続する必要がないため、単にsetTimeoutを使用しなくなります。

0
s427