ユーザーが戻るボタンを使用してページに到達したかどうかをどのように検出しますか?


90

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

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

問題は、次の場合です。

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

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

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

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


これはあなたが引用した質問とどう違うのですか?
2009年

質問は似ていますが、私は環境を考えているため、答えは異なります。私は間違っている可能性があります。他の解決策で解決される問題の可能性についての私の解釈は、ユーザーがajaxによってロードされたページのタブをクリックしてから、別のタブをクリックするというものです。戻るボタンをクリックすると、前のタブではなく、別のページに戻ります。彼らは、「ページ履歴」内の「ajax履歴」を循環したいと考えています。少なくとも、これはYahoo Browser History Managerが何をすべきかについての私の印象です。私はもう少し基本的なものを求めていました。
トム、

受け入れられた答えはあなたのiframeトリックを特徴とします。
2009年

回答:


79

非表示のフォームを使用します。フォームデータは、ブラウザーに再読み込みするか、戻るボタンを押してページに戻るときに(通常)保持されます。次のコードがページに表示されます(おそらく下部にあります)。

<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秒)にインラインで配置できます。


5
「フォームデータは(通常)ブラウザーで保持されます」-それを拡張できますか?一部のブラウザでは保持されませんか?またはいくつかの状況で?
トム

4
実際、これがうまくいかないと私が考えることができるすべての方法をリストアップしましょう。(1)Operaはページの完全な状態を保持し、jsを再実行しません。(2)キャッシュ設定を微調整して、ページからサーバーに戻るボタンを強制的にロードすると、フォームデータが失われる可能性があります。これは、この質問には適しています。(3)電話のブラウザーのキャッシュははるかに小さく、ブラウザーは既にキャッシュからページをドロップしている可能性があります(これらの目的には問題ありません)。
Nick White

10
一部のブラウザでは、非表示のタグが保持されません。したがって、非表示の入力タグを使用する代わりに、非表示のテキストタグを使用できます。<input type = "text" value = "0" id = 'txt' name = 'txt' style = "display:none" />
sajith

2
これは私にとってはうまくいきました。それが故障する状況があると私は確信していますが、すべての解決策がこの問題を解決します。
Joren

Safariブラウザを搭載したiPhoneでは動作しません。試してください。戻るボタンをクリックすると、jsが再度呼び出されません。
woheras

52

ここに、この古い問題に対する非常に簡単な最新の解決策があります。

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は現在、すべての主要なブラウザーでサポートされています。


私はこれについて聞いていませんでした。私はこのドキュメント(developer.mozilla.org/en-US/docs/Web/API/Performance/navigation)を見つけたので、詳しく説明してほしいと思います(たとえば、なぜ必要なwindow.performance && window.performance.navigation.typeだけではなくwindow.performance.navigation.TYPE_BACK_FORWARD?)。
ライアン

5
window.performance.navigation.TYPE_BACK_FORWARDは常に2に等しい定数です。したがって、比較のためにのみ使用されます。
Bassem 2017年

Performance.navigationはandorid&オペラミニ以外のすべてのデバイスでサポートされていますが、全く問題ありませんその非常に素晴らしい(developer.mozilla.org/en-US/docs/Web/API/Performance/navigation
Elbaz

1
performance.navigationは非推奨のようです。代わりにdeveloper.mozilla.org/en-US/docs/Web/API/…
RubberDuckRabbit

1
Firefox v70は2、戻るボタンヒットのPerformance.navigation = をサポートします。v70までは、誤って返されていました1
アンディマーサー

13

この記事ではそれについて説明します。以下のコードを参照してください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>

1
これは良い答えです。最新のChrome 40 / Firefox 35で動作します。ただし、IE11はこれらのイベントをサポートしていません。
Slava Abakumov、2015

caniuse.com/#feat=page-transition-eventsによると、ページ遷移イベントは実際にIE11 +でサポートされています。私たちが話すように、機能の88%がグローバルにカバーされています
Cristian

ちなみに、Chromeは[戻る]ボタンからクリックしてもevent.persisted=を返しfalseます。window.performance.navigationまたはChromeにはPerformanceNavigationTimingを使用する必要があります。
アンディマーサー

4

最近のブラウザでは、これは今では正しい方法のようです:

const perfEntries = performance.getEntriesByType('navigation');
if (perfEntries.length && perfEntries[0].type === 'back_forward') {
  console.log('User got here from Back or Forward button.');
}

これは2020年1月の時点ではまだ「実験的」ですが、十分にサポートされているようです。

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming


1
==の代わりに===を使用することを
お勧めします

2

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

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

<!-- 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>

この段階での私の(最小限の)テストから、これは期待どおりに機能するようです。見落としましたか?


私が知っていることではありませんが、完全にはテストしていません。getElementByIdは一部の古いブラウザではサポートされていませんが、必要に応じてjqueryなどに簡単に交換できます。
トム、

2

あなたは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


Safariでの作業
Jakob

2

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


その素晴らしい回避策ですが、彼が毎回これを検出したい場合はどうすればよいですか。サイトを開いて閉じたときに、開いたときと検出して閉じる前に戻る必要がある
Elbaz

1

このページの使用、特に@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

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

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

私の知る限り、Chromeでは動作しないようです。console.logは、ページへのアクセス方法に関係なく、elseステートメント(テスト用に追加)でのみトリガーされます。
ルーク、

0

私は今日同様の問題に遭遇し、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を使用しなくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.