history.pushStateをつかってみる。

pushState、実際にサンプルつくってみた。

http://dl.dropbox.com/u/131731/sample/pushstate/index.html

リンク遷移時にページ内で必要な部分のみ表示が代わり、かつ、
ページのtitle、ページのURLも読み込んだ内容に適応したものにかわるよう。

HTMLは事前にこんな感じになっている事想定。

HTML

//トリガーとなるaタグ、classがpjaxのものを対象としてる
//<a href="リンク先" class="pjax" title="遷移先のページのタイトル"></a>
<a href="index.html" class="pjax current" title="index">index</a></li>

<div id="main">
//この内容がページごとに置き換わる
</div>

JavaScript

jquery使うこと前提にしてる。

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {

	//init
	var _target = "#main"; //おきかえるコンテンツのID
	var _href; //同一ページのpushState二重投稿防止

	//初期ページのタイトルとHTMLを定義
	var _default = { 
		title : document.title,
		content : $(_target).html()
	};
	
	//debug
	$('nav').after($("<ol/>").addClass("debug"));

	$('a.pjax').click(function() {
		var title = $(this).attr('title'), href = $(this).attr('href');
		//console.log('location : ' + location.pathname);
		if ( _href !== href ) { //同一URLの時はpushしない(環境に応じて要調整)
			$('a.pjax').removeClass('current');
			$(this).addClass('current');
			if ( window.history.pushState ) { //pushStateが使えるブラウザなら
				window.history.pushState(title, null, href); 
					//pushState(event.state, 'title', 'url'), 先では、第1引数にタイトル渡して、第2のtitleはnullにしてるけど、
					//1には数字わたして、2には素直にページタイトルわたしたほうが、戻る/進む時の現在の位置管理ができてよさそう。
					//replaceStateは "現在のエントリを入れ替える、つまり新規のエントリは追加したくない場合に使用するAPI" だそう。
				changeContent(title,href);
				_href = href;
				
				$('.debug').append('<li>' + title + '<span>' + href + '</span></li>');
			} else { //pushState対応してないなら、普通に開く
				window.location = href;
			}
		}
		return false;
	});
	
	window.onpopstate = function(event){ //戻る/進むでイベント発動
		//console.log(event);
		$('a.pjax').removeClass('current');
		$('a[title ="' + event.state + '"]').addClass('current');
		if (event.state) {
			changeContent(event.state, location.pathname);
		} else {
			changeContent(_default.title, location.pathname);
		}
	}
	
	function changeContent(t,u) { 
		$(_target).slideUp(500,function() {
			$(_target).after('<em>loading...</em>').load(u + ' ' + _target, function() {
				$(this).slideDown(500, function() {
					document.title = t;
				}).next().remove();
			});
		});

	}
});
</script>

コメントをどうぞ

メールアドレスが公開されることはありません。 が付いている欄は必須項目です