わんどの写真部! ~ 商用フリー・クレジット表記不要の高解像度写真素材サイト』なるサイトを運営しておりまして、先ごろよりpushState&popStateと、Facebookの「いいね!」、Google+1ボタンに対応させる小改造を行ってました。

Ajaxで写真を動的に遷移するのですが、写真ごとにいいね!と+1が欲しいので、遷移したタイミングでボタンを手動でリセットする必要がある、さあ、どうしよう、というのが今回のお題です。

Facebookのほうは、こちらの記事にあったんですが、Googleのを日本語で解説してるサイトは見つからず。仕方ないので、素直に英語の公式ドキュメントあたってみました。

plusone.jsを読み込む

+1 ボタンを動的に表示させる方法はいくつかあるようですが、諸々勘案したところ、今回の条件にマッチするのは、Explicit renderというヤツのようで、その紹介です。まず、基本スクリプトを読み込みます。

		<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
	   		{'lang': 'ja', 'parsetags': 'explicit'}
		</script>

とりあえず<head>タグ内に配置しておけば安全でしょう。

ボタンに表示される言語(lang)と、ボタンを「明示的に(explicit)レンダリングする」=「動的に生成する」かどうか(parsetags)を、オプションで設定してます。

どうでもいいんですが、VBやってた人は、ここで反応してしまいますね。→Option Explicit

ボタンのコンテナを作成

+1ボタンを表示させたい場所に、コンテナとなるブロックレベル要素を記述します。

		<div id="plusone-div"></div>

などと、一応id属性を付けといてください。

ボタンの実体をレンダリングする

いよいよ+1ボタンを生成するコードを記述します。

今回の場合だと、最初の写真ページが表示された段階で一度ボタンを生成しますので、windowのloadイベントかなんかに記述します。↑SyntaxHighliterの仕様で、コーテーションが変なヤツになってます。コピペの際は、通常のものに修正してください。

最初の引数でコンテナを指定します。idで指定するならその文字列を書けばいいのですが、ドキュメントにSpecify either the ID of the container (string) or the DOM element itself.とありますから、DOMオブジェクトそのものをここにいれてもいいようです。jQueryなら$(‘hoge’)[0]とかですか。

二つ目の引数は各種のパラメーターです。ドキュメントの「+1 tag attributes」の項を参考にします。せっかくなんで、主な項目だけ日本語で抜き出してみます。正確性は保証できませんが…。

属性の名前 デフォルト値 詳細
href (+1させたいページのURL) (現在のページのURL) 私には英語がむずかしくてよくわかりませんが、他のページへの+1ボタンを設置するなら、gapi.plus.renderを使え、その際は、この属性を必ず指定せよ、ということのようです。↓下で解説します。
size small
medium
standard
tall
standard +1ボタンのサイズ。詳しくは、ここを参照。
annotation none
bubble
inline
bubble アノテーション(+1の数や、簡単なインフォメーションなどの表示)をどうするか。

none
アノテーションを表示しない
bubble
吹き出しの中に+1の数を表示(例:gp1-1
inline
Google+上でユーザーとつながっている人で、そのページを+1している人のサムネイルが表示される。また、+1の数も表示(例:gp1-2

これだけあれば十分でしょう(汗)。ほかにも、width、align、expandToなどの配置系や、コールバック、吹き出しのホバーイベントなどのハンドラもあるようです。

ここで、どうしてExplicit render、つまりgapi.plus.renderを呼び出す方法を選択したのかが分かります。pushStateとは、「別のページのコンテンツを、現在のページに動的に読み込ませる」ことにほかならないわけですから、ボタンには別のページのURLを設定する、という体になる、というわけです。

ボタンのURLを変更する

で、今回の本題なのですが、これがいたってシンプル。要は、ボタンをレンダリングしなおす、つまり、もう一度gapi.plusone.renderを発火させるだけです。もちろんパラメーターのhrefは、変更先のURLにセット、そのほかのパラメータも、再度記述します。

まとめ

以上をふまえて、HTMLのアウトラインの例を示します。本来は、これにpopState処理なども追加する必要がありますが、割愛します。

		<!DOCTYPE html>
		<html lang="ja">
		<head>
			<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
			<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
				{'lang': 'ja', 'parsetags': 'explicit'}
			</script>
			<script>
				function update(index, is_first_time){
					$('#image-container').empty().append(
						$('<img />').attr('src', 'images/' + index + '.jpg')
					);
					if(!is_first_time) window.history.pushState(null, null, index + '.html');
					gapi.plusone.render('plusone-div', {
						'href': window.location.href,
						'size': 'tall',
						'annotation': 'inline'
					});
				};
				$(window).load(function(){
					$('#links a').click(function(){
						update($(this).text(), false);
						return false;
					});
					var current = window.location.pathname;
					current = current.substring(current.lastIndexOf('/') + 1,current.length);
					current = current.substring(0, current.indexOf('.'));
					update(current, true);
				});
			</script>
		</head>
		<body>
			<div id="image-container">
			</div>
			<div id="links" style="font-size: 150%; margin: 1em 0">
				<a href="1.html">1</a>
				<a href="2.html">2</a>
				<a href="3.html">3</a>
			</div>
			<div id="plusone-div"></div>
		</body>
		</html>

これを「1.html」として設置したとすると、同じディレクトリに、以下のような.htaccessを置き、

		<IfModule mod_rewrite.c>
		RewriteEngine On
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteCond %{REQUEST_FILENAME} !-d
		RewriteRule ^(.*) 1.html [L]
		</IfModule>

さらに同ディレクトリに「images」ディレクトリを設置して、中に「1.jpg」「2.jpg」「3.jpg」を置き、最初の「1.html」、または、「2.html」「3.html」にアクセスすると動作します。

サンプルをこちらに置いておきますので、実際に+1して確かめてみてください、…っていう新手のステマじゃありません。念のため。