コンテンツのajaxロードでHTML5履歴APIを試しています。
相対リンクで接続されたテストページがたくさんあります。私はこれらのリンクのクリックを処理するこのJSを持っています。リンクがクリックされると、ハンドラーはそのhref属性を取得し、それをajaxLoadPage()に渡します。この属性は、要求されたページから現在のページのコンテンツ領域にコンテンツをロードします。(私のPHPページは、通常どおりリクエストすると完全なHTMLページを返すように設定されていますが、リクエストのURLに?fragment = trueが追加されている場合は、コンテンツのチャンクのみが返されます。)
次に、クリックハンドラーがhistory.pushState()を呼び出して、アドレスバーにURLを表示し、ブラウザーの履歴に追加します。
$(document).ready(function(){
var content = $('#content');
var ajaxLoadPage = function (url) {
console.log('Loading ' + url + ' fragment');
content.load(url + '?fragment=true');
}
// Handle click event of all links with href not starting with http, https or #
$('a').not('[href^=http], [href^=https], [href^=#]').on('click', function(e){
e.preventDefault();
var href = $(this).attr('href');
ajaxLoadPage(href);
history.pushState({page:href}, null, href);
});
// This mostly works - only problem is when popstate happens and state is null
// e.g. when we try to go back to the initial page we loaded normally
$(window).bind('popstate', function(event){
console.log('Popstate');
var state = event.originalEvent.state;
console.log(state);
if (state !== null) {
if (state.page !== undefined) {
ajaxLoadPage(state.page);
}
}
});
});
pushStateを使用して履歴にURLを追加する場合は、戻るボタンまたは進むボタンのクリックを処理するために、popstateイベントのイベントハンドラーも含める必要があります。(これを行わない場合、戻るをクリックすると、アドレスバーに履歴にプッシュしたURLが表示されますが、ページは更新されません。)したがって、私のpopstateハンドラーは、作成した各エントリのstateプロパティに保存されたURLを取得します。そしてそれをajaxLoadPageに渡して、適切なコンテンツをロードします。
これは、クリックハンドラーが履歴に追加されたページで問題なく機能します。しかし、「通常」にリクエストしたときにブラウザが履歴に追加したページはどうなりますか?通常どおり最初のページにアクセスし、ajaxの読み込みを行うクリックでサイト内を移動するとします。その後、履歴を最初のページに戻そうとすると、最後のクリックで最初のページのURLが表示されますが、表示されません。ブラウザにページをロードしません。何故ですか?
これは、最後のpopstateイベントのstateプロパティと関係があることがわかります。値を与えることができるのはpushState()またはreplaceState()によって履歴に追加されたエントリのみであるため、そのイベントの状態プロパティはnullです。しかし、ページの最初の読み込みは「通常の」リクエストでした。ブラウザが元のURLに戻って通常どおりに読み込まないのはなぜですか?