カテゴリー:
JavaScript
タグ:
 ajax twitter facebook mixi

このエントリーをはてなブックマークに追加
更新日時:
2013年10月24日(木)
作成日時:
2013年03月03日(日)

前の記事 / 次の記事

ツイッターの「ツイート」ボタン、facebookの「いいね!」ボタン、googleの「+1」ボタン
mixiの「イイネ!」ボタン、はてなの「はてなブックマーク」ボタンをajaxで差し替える、
正常に表示されない

たぶん他の各ソーシャルサイトのボタンも全部そう。

ちょっと調べてみると、ajaxで要素を差し替えた場合は、

  • scriptタグに記述されたスクリプトは実行されない。
  • document.onload() イベントが発生しない(jQueryの $(document).ready() イベントも発生しない)

っていうところに原因がありそう。

Ajax/Ajaxで取ってきたHTMLコンテンツ内の<script>タグを実行させたい

それを回避するためにボタンの呼び出しスクリプトを
document.onload() や $(document).ready() 以外のところに書いてみたり、
スクリプトをhtmlファイルに直書きにしてテキストとしてevalしてみたりしたんだけど、
自分で書いたスクリプトは期待通りに動いたけど、ツイートボタン以外は動かなかった。

おそらくscriptタグで呼び出した先のスクリプトで
document.onload() の処理があってそこが動いてないんだろうなと。

で、結論としては仕様が公開されてるんだからちゃんと仕様を読めよって話で、
mixi以外のボタンは公式に再レンダリングするためのapiが提供されていて、
それを一行書けば解決だった。

mixiは公式には公開されてないっぽくてぐぐって出て来たページにあったコードを
使ってみたけどそのページも書いてあるようにブラウザのボタンで戻ったり進んだりすると
「イイネ!」ボタンが増殖する。特に解決する気はないのでこれ以上は調べない。

はてなも、mixiみたいな感じで戻る、進むボタンを使うとバグる(falseという文字列になる)。
はてなは色々試してみたけど解決法がよく分からず、結局戻る、進むボタンが使用された時に、
改めてJavaScriptで要素を再作成するようにしたらうまくいった。
(mixiもこの方法でなんとかなるかも知れない。やってないから不明。)

それぞれのボタンで参考にしたページ。

twitter
Cannot update tweet button with AJax
ajax ツイッター tweetボタン 表示されない
ツイートボタンのツイート内容を動的に変える

facebook
FB.XFBML.parse
Ajax+pushStateでページ遷移したときにFacebookプラグインを更新する方法

google
Google+ Platform
Update FB:Like URL Dynamically using JavaScript
Google +1(プラスワン)ボタンを設置

mixi
[js] 動的に設置したソーシャルボタンの初期化

はてな
Ajax(pjax)遷移時におけるSNSボタン再構築

次の各処理をページ遷移した時にキックすればajaxで遷移させてもボタンが更新されるはず。
はてなは別の処理をしてるので後述。

※Facebookは仕様変更が入った?みたいでこのやり方でうまくいかないかも?
Facebookについては旧情報ということで・・・、今どうすればいいかは調べてません。
2014/08/04

/* 
 * [ツイートボタン]
 * tweet-button は任意のid
 * ボタンに紐付けるURLを事前に書き換える必要がある
 */
document.getElementById('tweet-button').setAttribute('data-url', document.location.href);
twttr.widgets.load();

/*
 * [facebook いいね!]
 */
FB.XFBML.parse();

/*
 * [Google+1]
 * gplusone は任意のid
 * ボタンとして使う要素を明示的に渡す必要がある
 * ボタンをデフォルト以外の形状で使うには改めてパラメーターを渡す必要がある
 */
gapi.plusone.render(document.getElementById('gplusone'), {size: "tall", width: "120px", annotation: "block"});

/*
 * [mixi イイネ!]
 * 但しブラウザのボタンで戻ったり進んだりするとバグる
 */
__MIXI_PLUGINS__._init();

turbolinksなら"page:load", pjaxなら"pjax:complete"辺りでキックするのがいいのかな。

// いずれもイベントの検知はjQuery
// turbolinks
$(document).on("page:load", function(){
  document.getElementById('tweet-button').setAttribute('data-url', document.location.href);
  twttr.widgets.load();
  FB.XFBML.parse();
  gapi.plusone.render(document.getElementById('gplusone'));
  __MIXI_PLUGINS__._init();
});

// pjax
$(document).on("pjax:complete", function(){
  document.getElementById('tweet-button').setAttribute('data-url', document.location.href);
  twttr.widgets.load();
  FB.XFBML.parse();
  gapi.plusone.render(document.getElementById('gplusone'));
  __MIXI_PLUGINS__._init();
});

他のソーシャルサイトのボタンも同じような関数が用意されている気がするので、
他のボタン類もその関数があれば同じ方法で対応出来るんじゃないかと。

はてなについて

ぐぐると色んなページに他のボタンと同じようにページ遷移時にバグる場合は
次の処理

Hatena.Bookmark.BookmarkButton.setup();

をキックせよと書いてあるんだけど、自分の環境ではうまくいかなかった。
(ボタンは出てくるけど件数が出て来ない。)

自分の環境というのはRails3上でTurbolinksでページ遷移をさせているのだけど、
pjaxで頑張ってる場合はうまくいくのかも知れない。

色々考えるのが面倒くさくなったので、とりあえずはてなボタンだけは
JavaScriptで要素を丸ごと再作成するようにした。

今まで生のJavaScriptだったのにいきなりCoffeeScriptになって申し訳ないけど・・・。

# CoffeeScript
#
# Turbolinksで戻る、進むボタンを使った時は "page:restore" イベントが発生する。
# それ以外の時は正常に動作するので考慮しなくていい。
$(document).on "page:restore", ->
  # 何でもいい、はてなブックマークボタンを内包する任意のid
  $hatena_box = $("#hatena-bookmark-box")
  $a =
    $("<a>", {
      "href":                        "http://b.hatena.ne.jp/entry/" + encodeURI(location.href)
      "ata-hatena-bookmark-title":   document.title
      "class":                       "hatena-bookmark-button"
      "data-hatena-bookmark-layout": "vertical-balloon"
      "data-hatena-bookmark-lang":   "ja"
      "title":                       "このエントリーをはてなブックマークに追加"
    })
  $img =
    $("<img>", {
      "src":    "http://b.st-hatena.com/images/entry-button/button-only@2x.png"
      "alt":    "このエントリーをはてなブックマークに追加"
      "width":  "20"
      "height": "20"
      "style":  "border: none;"
    })
  $script =
    $("<script>", {
      "type":    "text/javascript"
      "src":     "http://b.st-hatena.com/js/bookmark_button.js"
      "charset": "utf-8"
      "async":   "async"
    })
  $hatena_box.html("").append($a.append($img)).append($script)