3

内のコンテンツを表示するナビゲーション ページを作成していますiframe。要件は、現在読み込まれているページに対応するナビゲーション リンクが強調表示されていることです。フレームの内容は私の手に負えません。ユーザーがブラウザで戻る/進むボタンを使用すると、問題が発生します。

アイデアは、history.replaceStateナビゲーション リンクに関する情報をページに関連付け、popstateイベント時にナビゲーション パネルの状態を復元するために使用することでした。コンテンツがAJAX経由でアプリケーションにロードされた場合、それは完全に機能しました。

iframeナビゲーションの場合history、トップウィンドウのオブジェクトは変更されないので、 で作業するcontentWindow必要があり、同じドメインのページのみをサポートするように制限します。

問題は、イベントにサブスクライブできなかったことです。次のコードは機能しません。

$(window).on('popstate', function () { handleHistory('popstate@window'); });
$('#frame').on('popstate', function () { handleHistory('popstate@iframe'); });
$($('#frame')[0].contentWindow).on('popstate', function () { handleHistory('popstate@iframe.window'); });
$('#frame')[0].contentWindow.onpopstate = function () { handleHistory('popstate@iframe.window'); };

後者の場合は後履歴ナビcontentWindow.onpopstateですnull

最後に、loadイベントを使用しようとしましたが、機能しましたが、すべてのページ リソースが読み込まれるまで待機するため、起動するまでにかなりの遅延があります。

$('#menu a').click(function() {
    // ...
    $('#frame').one('load', function() {
        frameWindow.history.replaceState({ linkId: link.id },frameWindow.document.title, frameWindow.location.href);
    });
    // ...
});
$('#frame').load(function () { handleHistory('load@iframe'); });

私が試した別のアプローチcontentWindow.location.hrefは、タイマーをポーリングして、より早く反応することでした。一見するとうまくいきましたが、その後、履歴レコードがブラウザーから消えることがあることに気付きました (少なくとも Firefox では)。

var isLoading = false;
$('#menu a').click(function() {
    // ...
    isLoading = true;
    $('#frame').one('load', function() { isLoading = false; });
    (function poll () {
        var frameWindow = getFrameWindow();
        if (getFrameWindow().location.href == link.href) {
            frameWindow.history.replaceState({ linkId: link.id },frameWindow.document.title, frameWindow.location.href);
        } else {
            setTimeout(poll, 100);
        }
    })();
    // ...
});
setInterval(function () {
    if (!isLoading) {
        handleHistory('timer');
    }
}, 100);

内部の履歴を追跡する他の良い方法はありますiframeか? おそらく私はいくつかの間違いを犯しましたか?おそらく、コンテンツのドメインに関係なくこれを行う方法さえありますか?


ソース コードとデモ ページは次のとおりです (スクリプトの動作をわかりやすくするために遅延が追加されています)。
onload アプローチ: src デモ
タイマー アプローチ: src デモ

4

1 に答える 1

0

これは実際には満足のいく解決策ではありませんが、フレームの on load イベントで履歴スタックのサイズを調べることができます。

<html>
<body>

<iframe src="http://w3c.org" class="xssFrame"></iframe>
<p class="output"></p>

<script>
var size = window.history.length;
var tempSize = null
//document.querySelector(".xssFrame").unload = function(){} //might need to set this handler to force load event on back click
document.querySelector(".xssFrame").onload = function () {
    var delta = size - window.history.length;
    document.querySelector(".output").innerHTML = "parent history: " + size + " combined history: " + window.history.length + " go " + (delta-1).toString()
    if(tempSize ===  window.history.length) {
      document.querySelector(".output").innerHTML = "go now" + (delta).toString()
      window.history.go(delta)
    } else {
      tempSize = window.history.length
    }


}
</script>
</body>
</html>
于 2015-02-20T06:13:30.353 に答える