印刷用表示へ切り替え 通常表示へ切り替え 更新履歴を表示 更新履歴を隠す
misc XHTML にソーシャルボタンを Valid に設置する

ソーシャルボタンを XHTML の環境に Valid な状態で設置する。ちょっとインチキだが,XHTML に対応していないソーシャルボタンに対しては,パーセントエンコードして Valid にした後,デコードしてボタンを表示させることにする。どの記事でも同じコードで済むように書くことにする。

■ ■ ■

導入環境と結果

重い腰を上げ,ようやくブログにソーシャルボタンを設置することにした。このブログの現在のマークアップ環境は「-//W3C//DTD XHTML+RDFa 1.1//EN」である (nlog(n): OGP 対応と XHTML+RDFa 1.1 への移行)。このブログは Movable Type を使って構築されているが,今回のソーシャルボタンの設置法は,Movable Type である必要はない。

ソーシャルボタン

今回導入するボタン (画像です。クリックできません)。

導入の条件

ソーシャルボタンを導入する際の条件を次のように決めておく。

W3C で Valid であるというお墨付きをもらうことが必須である。HTML-lint の満点は諦めることにする。実際,HTML-lint は,現時点 (htmllint.cgi 1.28 / htmllint.pm 3.58) では XHTML + RDFa 1.0 までしか対応していないため, XHTML + RDFa 1.1 である時点でどうやっても満点は取れないのである。ただし, XHTML + RDFa 1.1 以外の問題がまったくない状態にはしておきたい。

期待される効果

ソーシャルボタンを設置することで期待される効果は次のようなものである。

  • このブログの不人気っぷりが白日の下にさらされる (泣)
  • ブログ記事のリンクを簡単にソーシャルサービスに投稿できる
  • このブログを見る人同士が何をチェックしているのかが分かる

実際は,ソーシャルボタンをつけることで,リンクやツイートの数が表示されるだけである。だが,その数に「0」が並ぶことは想像に難くないのであって,それを見ることで精神の崩壊が起こる可能性もあるわけである。「やってらんねー」とか言ってアルコール摂取量が増えたとしたら,それはすべてソーシャルボタンのせいなのである。今まで目を背けていたことが,常に見えてしまうという事態が発生するからである。

ソーシャルボタンをつけると,そのボタンを押せば,リンクをソーシャルサービスに投稿するアクションが起こるようになる。もしボタンがついていなければ,利用者はソーシャルサービスにサインインしてからブログを見に来なければならない。しかし,ボタンがついていることで,投稿のアクションを起こした後でサインインすればいいという逆の流れが可能になるのである。このような,流れを逆転することで便利になるという仕組みは,Movable Type に出合った頃にも出合って驚いたことがある。Movable Type 用のブックマークレットがそうだった (nlog(n): ブックマークレットとは?)。

ソーシャルボタンには,「ソーシャル」というだけあって,他人とのつながりも期待できる。例えば,誰がツイートしたのか,誰がはてなブックマークをつけたのかが分かる。そうすれば,このブログを通じて知らない人たちが知り合うというきっかけにもなる。そうやって知り合うことは万が一にもないだろうが,可能性としてはゼロではない。Facebook の場合は誰が「いいね」しているのか分からない。ソーシャルに対する考え方が違うためである。

導入方法

ソーシャルボタンは,各ソーシャルサービスが公式の導入方法を公開している (ソーシャルボタンの設置方法まとめ - NAVER まとめ)。ソーシャルサービスが提供する方法の他に,それらをまとめて設置するための jQuery プラグインを導入する方法もある (Pinterest/Google+1/Twitter/facebookいいね/facebook Share/mixiチェック/mixiイイネ/GREEいいね/Evernote/はてブのボタンを超カンタンに作れる jQuery.socialbutton プラグインを作ったよ | アイトランス株式会社)。

ソーシャルボタンは,各個別記事に設置し,まとめて複数の記事が表示されるアーカイブには設置しないことにする。ソーシャルボタンを呼び出す際に,URL やタイトルが必要な場合があるが,それらは JavaScript の document.URL や document.title で与えてやることにする。そうすれば,どの記事に対しても同一のソースで書くことができ,しかも Movable Type 以外にも適用することができる (人気ソーシャルボタン(facebookいいね・tweetボタン・はてぶ・googleプラス)を1ソースで設置する : code14)。

そして,最も重要なことは,最初の条件にあげたように The W3C Markup Validation Service に合格することである。実は,今まで導入をためらってきたのは,ソーシャルボタンを導入することで XHTML として正しくなくなってしまうからだったのである。しかし,無理矢理にでも XHTML Valid にする方法があることが分かった。ソーシャルボタン導入のための背中を押してくれたのは 減点されないソーシャルブックマークボタン | ナメサメカリンチョ の記事である。

(グーグル プラスワン) ボタン表示用のコードは HTML 5 の文法のコードとそうでないコードがあります。そうでない方がデフォルトです。HTML 5 ではない方のコードでボタンを設置すると Another HTML-lint gateway で減点されることはありませんが、W3C の XHTML 認定 には合格しません。HTML 5 の文法のコードだと減点される上に合格しません。これは根本的な問題なので twitter ボタンのように改変することもできません。こうなったらゴリ押しです。

減点されないソーシャルブックマークボタン | ナメサメカリンチョ

仕組みとしては次のようになる。

  1. ボタン表示用のタグをエンコードすることで (パーセントエンコーディング - Wikipedia),XHTML として正しいものにする
  2. エンコードしたタグを JavaScript でデコードしてソーシャルボタンを表示させる

エンコードには Unescape Encoder/Decoder を使う。デコードもできるので,とても便利。

スクリプト内は CDATA で囲むという提案があるが (Google Plus One Button Won’t Validate Strict XHTML « Too Much White Space),HTML コメントの方がまだましらしいし (XHTML文書におけるJavaScriptの使用上の注意点),コメントにしたとしても HTML-lint の評価が思わしくないので,何もしないことにした。

その他,細かいことではあるが,ボタン表示用のタグには明示的に何のボタンであるかを入れていくことにする。例えば,グーグルプラスワンボタンであれば,公式のコードは

<div class="g-plusone"></div>

だが,

<div class="g-plusone">Google +1</div>

のように書くことにする。理由の一つとしては,タグの間が空だと HTML-lint に指摘されるからである。どうせボタンによって上書きされるので,何が書いてあっても構わないのである。また,もしソーシャルサーバがダウンしているときにでも,それが何のボタンであるかが分かるという利点もある。タグの間に幅ゼロの文字を入れたい場合は「&zwnj;」と書けば HTML-lint には問題を指摘されない。

導入するボタンは上にバルーンで数が表示されるボックス型で統一することにする。

ソーシャルボタン設置コード

Tweet ボタン

公式サイトにアクセスし (Twitter / Twitterボタン),コードを取得する。ボックス型にするには,さっとマニュアルに目を通すと「data-count="vertical" を追加する」とあるが,XHTML の「a」タグには「data-count」属性は存在しないのでまずい。そこで,マニュアルをもっとよく読むと,https://twitter.com/share のクエリ文字列として「count=vertical」を指定すればよいと書いてあるのでそうする (Tweet Button | Twitter Developers)。

ボタンを表示したい部分には次の HTML コードを書く。

<a href="https://twitter.com/share?count=vertical&amp;lang=en" class="twitter-share-button twitter-count-vertical">Tweet</a>

body 閉じタグの前に次の JavaScript コードを書く。公式サイトからコピペするだけで OK だが,script タグには type="text/javascript" を追加しておくことを忘れずに。

<script type="text/javascript">!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>

はてなブックマークボタン

はてなブックマークボタンは,2011年の公開当初は,利用者の行動情報を取得する版が使われていたが,問題があったために行動情報を取得しないものに差し替えられた (はてなブックマークボタンから収集した行動情報の第三者提供をやめます - はてなの日記 - 機能変更、お知らせなど)。ソーシャルボタン用のコードは はてなブックマークボタンの作成・設置について - はてなブックマーク から取得できる。例えば次のようなものである。

<a href="http://b.hatena.ne.jp/entry/アドレス" class="hatena-bookmark-button" data-hatena-bookmark-title="タイトル" data-hatena-bookmark-layout="vertical-balloon" data-hatena-bookmark-lang="en" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a>

「アドレス」には URL を,「タイトル」には記事のタイトルを入れる。これには JavaScript の機能を使って document.URL, document.title を document.write することにする。しかし,script タグの中には a タグや img タグを入れることができない。しかも,a タグには data-hatena-bookmark-title 属性や data-hatena-bookmark-layout 属性はない。そこで,HTML のコード部分をパーセントエンコードして,document.write する際に unescape するというワザを使う。コードの可読性は極端に悪くなり,「あんた何いってんの」状態になるが,Valid 獲得を捨てるわけにはいかない。訳が分からなくて変態的なコードになっても Valid を通すというのが男である。

Unescape Encoder/Decoder を使って,アドレスとタイトル以外を細切れにしてエンコードし,それをつなぎ合わせる。最終的にボタン表示したい部分には次のように書くことになる。

<script type="text/javascript">
  document.write( unescape('%3C%61%20%68%72%65%66%3D%22%68%74%74%70%3A%2F%2F%62%2E%68%61%74%65%6E%61%2E%6E%65%2E%6A%70%2F%65%6E%74%72%79%2F') + encodeURIComponent(document.URL) + unescape('%22%20%63%6C%61%73%73%3D%22%68%61%74%65%6E%61%2D%62%6F%6F%6B%6D%61%72%6B%2D%62%75%74%74%6F%6E%22%20%64%61%74%61%2D%68%61%74%65%6E%61%2D%62%6F%6F%6B%6D%61%72%6B%2D%74%69%74%6C%65%3D%22') + encodeURIComponent(document.title) + unescape('%22%20%64%61%74%61%2D%68%61%74%65%6E%61%2D%62%6F%6F%6B%6D%61%72%6B%2D%6C%61%79%6F%75%74%3D%22%76%65%72%74%69%63%61%6C%2D%62%61%6C%6C%6F%6F%6E%22%20%64%61%74%61%2D%68%61%74%65%6E%61%2D%62%6F%6F%6B%6D%61%72%6B%2D%6C%61%6E%67%3D%22%65%6E%22%20%74%69%74%6C%65%3D%22このエントリーをはてなブックマークに追加%22%3E%3C%69%6D%67%20%73%72%63%3D%22%68%74%74%70%3A%2F%2F%62%2E%73%74%2D%68%61%74%65%6E%61%2E%63%6F%6D%2F%69%6D%61%67%65%73%2F%65%6E%74%72%79%2D%62%75%74%74%6F%6E%2F%62%75%74%74%6F%6E%2D%6F%6E%6C%79%40%32%78%2E%70%6E%67%22%20%61%6C%74%3D%22このエントリーをはてなブックマークに追加%22%20%77%69%64%74%68%3D%22%32%30%22%20%68%65%69%67%68%74%3D%22%32%30%22%20%73%74%79%6C%65%3D%22%62%6F%72%64%65%72%3A%20%6E%6F%6E%65%3B%22%20%2F%3E%3C%2F%61%3E') );
</script>

心なしか吐き気をもよおすコードが出来上がったが,以上である。body 閉じタグの前には次のコードを置く。

<script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8"></script>

XHTML では,はてなブックマークの非同期オプションである async 属性は許されないので削除する。このブログの文字コードは EUC-JP であるが,スクリプトの文字コード指定は charset="utf-8" となっている。これはスクリプトのソースがあるサーバの文字コードである。

Google +1 ボタン

Google プラスワンボタンも公式サイトからコードを入手する (+1 ボタン - Google+ Platform ― Google Developers)。ボタン表示をしたい部分に設置したいのは次のコードであるが,

<div class="g-plusone" data-size="tall">Google +1</div>

data-size 属性は許されないので,次のようにする。はてなブックマークができてしまえば,こんなのは何ともない。

<script type="text/javascript">
  document.write(unescape('%3C%64%69%76%20%63%6C%61%73%73%3D%22%67%2D%70%6C%75%73%6F%6E%65%22%20%64%61%74%61%2D%73%69%7A%65%3D%22%74%61%6C%6C%22%3E%47%6F%6F%67%6C%65%20%2B%31%3C%2F%64%69%76%3E'));
</script>

body 閉じタグの前に置くコードは公式サイトのコピペで OK。

<script type="text/javascript">
  window.___gcfg = {lang: 'ja'};
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script>

Pocket ボタン

Pocket はクラウドブックマークのサービスで,マークをつけておいて「あとで読む」が簡単にできるというもの。Pocket ボタンも同様に,ボタンを表示させたい部分のコードを取得する (Pocket for Publishers: Pocket Button)。
<a data-pocket-label="pocket" data-pocket-count="vertical" class="pocket-btn" data-lang="en">Pocket</a>

これも XHTML としてはダメなので,代わりに次のように書く。

<script type="text/javascript">
  document.write(unescape('%3C%61%20%64%61%74%61%2D%70%6F%63%6B%65%74%2D%6C%61%62%65%6C%3D%22%70%6F%63%6B%65%74%22%20%64%61%74%61%2D%70%6F%63%6B%65%74%2D%63%6F%75%6E%74%3D%22%76%65%72%74%69%63%61%6C%22%20%63%6C%61%73%73%3D%22%70%6F%63%6B%65%74%2D%62%74%6E%22%20%64%61%74%61%2D%6C%61%6E%67%3D%22%65%6E%22%3E%50%6F%63%6B%65%74%3C%2F%61%3E'));
</script>

body 閉じタグの前は次を。

<script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script>

Facebook Like ボタン

Facebook も公式サイトからコードを取得する (Like Button - Facebook Developers)。提供されるコードには HTML 5, XFBML, IFRAME の3種類がある。XFBML は独自すぎるし,IFRAME は XHTML では使えない。そこで,HTML 5 用のコードを使う。

<div class="fb-like" data-width="55" data-height="65" data-colorscheme="light" data-layout="box_count" data-action="like" data-show-faces="true" data-send="false">Facebook Like</div>

HTML 5 のコードはそのまま XHTML では使えないので,これも同様にパック詰め。

<script type="text/javascript">
  document.write(unescape('%3C%64%69%76%20%63%6C%61%73%73%3D%22%66%62%2D%6C%69%6B%65%22%20%64%61%74%61%2D%77%69%64%74%68%3D%22%35%35%22%20%64%61%74%61%2D%68%65%69%67%68%74%3D%22%36%35%22%20%64%61%74%61%2D%63%6F%6C%6F%72%73%63%68%65%6D%65%3D%22%6C%69%67%68%74%22%20%64%61%74%61%2D%6C%61%79%6F%75%74%3D%22%62%6F%78%5F%63%6F%75%6E%74%22%20%64%61%74%61%2D%61%63%74%69%6F%6E%3D%22%6C%69%6B%65%22%20%64%61%74%61%2D%73%68%6F%77%2D%66%61%63%65%73%3D%22%74%72%75%65%22%20%64%61%74%61%2D%73%65%6E%64%3D%22%66%61%6C%73%65%22%3E%46%61%63%65%62%6F%6F%6B%20%4C%69%6B%65%3C%2F%64%69%76%3E'));
</script>

Facebook の場合,appID を取得して,自分の Facebook ページと関連付けると Facebook のニュースフィードに表示されたり,Facebook インサイトが使えるよいうになるなどいいことがあるらしいが (FacebookのOGPに fb:admins と fb:app_id の設定は必要?htmlタグのxmlnsは? | Cappee Design),私は Facebook ページとブログは切り離しておきたいので,appID の記述はしていない。appID がなくても Debugger - Facebook Developers で警告表示されない。

body 閉じタグの前には次を。

<div id="fb-root">&zwnj;</div>
<script type="text/javascript">
(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>

Facebook は <div id="fb-root"></div> が謎。幅ゼロの文字 &zwnj; を入れて HTML-lint の警告をパスする。

スタイルシート

並べ方,すなわち見た目も重要である。このブログでは,以上のボタン表示コードを,

<ul class="social_buttons">
  <li>Twitter ボタンの表示コード</li>
  <li>はてなブックマークボタンの表示コード</li>
  <li>Google +1 ボタンの表示コード</li>
  <li>Pocket ボタンの表示コード</li>
  <li>Facebook いいねボタンの表示コード</li>
</ul>

の形式で XHTML ソース内には書いておき,CSS では次のように指定している。

.social_buttons {
        list-style-type: none;
        clear: both;
        }
.social_buttons li {
        float: right;
        margin-left: 10px;
        }
.social_buttons:after {
        content: "";
        display: block;
        height: 0;
        clear: both;
        }
.twitter-share-button { width: 60px !important; }

できあがり

できあがりはこの記事の冒頭の通りである。そして,すべてのブログ記事に適用したところ,北風が心を吹き抜けた。あまりにもゼロが並んでいるのは印象が悪過ぎである。客の入っていない店が入りづらいのと同じだ。「信用できないから誰も来ていない」みたいな。

「すべては現状を受け入れることから始まる」

って言われてもねぇ (泣)

2013年11月28日追記:
Delicious ブックマークボタンを追加しました (nlog(n): Delicious の縦型ソーシャルボタンを自力で作る)。

Posted by n at 2013-10-10 00:33 | Edit | Comments (0) | Trackback(0)
Trackbacks

  • 「手違いで複数トラックバックを送ってしまった!」という場合でも気にしないでください (重複分はこちらで勝手に削除させていただきます)
  • タイムアウトエラーは,こちらのサーバの処理能力不足が原因です (詳細は トラックバック送信時のエラー をご覧ください)
  • トラックバックする記事には,この記事へのリンクを含めてください(詳細は 迷惑トラックバック対策 をご覧ください)
Comments
Post a comment
  • 電子メールアドレスは必須ですが,表示されません (気になる場合は「メールアドレスのような」文字列でもOKです)
  • URL を入力した場合はリンクが張られます
  • コメント欄内ではタグは使えません
  • コメント欄内に URL を記入した場合は自動的にリンクに変換されます
  • コメント欄内の改行はそのまま改行となります
  • 「Confirmation Code」に表示されている数字を入力してください (迷惑コメント対策です)


(必須, 表示されます)


(必須, 表示されません)


(任意, リンクされます)


Confirmation Code (必須)


Remember info (R)?