以下斜め読んだ内容

pseudo translation of useful posts, book reviews, remarks,etc. twitter: feeddict

ソーシャルプラグインのlazyload

  • 調べたり試したことのまとめ
  • とりあえずfb,twitter,g+だけ
  • コピペ用コード並べた

やりたいこと

  • 画像でみかける遅延読み込み、オンデマンドでの読み込み
    • それをlikeboxとか、tweetボタンとかでもやりたい
  • techcrunchのトップとかでやってるあれ
    • 1ページの中に100個くらいボタンある
    • $(".lazy-share-widget .platform").length //->90
    • ボタンのある所にカーソル持ってくまで、ボタンがロードされないようになってる
  • mashableのトップは全然違う
    • layzyload関係ない
    • あれはサーバ側であらかじめページにボタンを埋め込んでる
      • だからtweet数とかlike数とかの数値がかなりずれる
    • 割り切り型の手法
      • そもそもfb/tw/g+へhttpリクエスト出さない
      • CDNもつかって速さに挑戦してる
  • 「この辺までスクロールしたら表示」とか「カーソルこの辺まで来たらロード」ロードとか
    • 出来るだけhttpリクエストを減らす、というより、小出しにしたい
  • 初回ページロードだけでなく、ajaxとかpjaxにも対応

##ライブラリはあるにはあるが。。。

  • Socialite.js
    • 機能が足りない感じ
    • ボタンだけとか
    • ソーシャルプラグイン側の仕様にがっつり追従できるのか、不安
    • 実際`socialite.js`は最近開発されてない
  • プラグインのSDK
    • plusone.js<(G+)、widgets.jstwitterall.jsfacebook
    • なるべくプラグインのjsが提供してる機能だけを使って実現したい

##ライブラリ(SDK)の読み込み

  • とりあえず何度も読みに行かない
    • plusone.js、`widgets.js`、`all.js`を何度もリクエストしない
    • FBtwttrgapiオブジェクトの有無を判定すればOK
# jQuery + coffeescriptで
# twitter
if !twttr?
	jQuery.getScript "//platform.twitter.com/widgets.js"
else
	console.log "OK"

# facebook
if !FB?
	jQuery.getScript "//connect.facebook.net/ja_JP/all.js"
else
	console.log "OK"

# google+

if !gapi?
	jQuery.getScript "//connect.facebook.net/ja_JP/all.js"
else
	console.log "OK"

プラグラインの初期化

  • SDKが入ったjsを読み込んだ後の話
  • 初期化?
    • 言語とか、アプリid(facebook)とか、ウィジェットの寸法計算とか
    • 初期化自体は今回気にしてないが
  • 初期化の設定でプラグインのロード(レンダリング)だけはオフにしたい
  • facebookgoogle+はAPIがサポートしてるのでシンプルにできる
    • fb
      • xfbml:falseFB.init({..option.})のオプションに指定
    • G+
      • parsetags:"explicit"window.___gcfgプロパティにセット
  • twitterはアカン
    • widgets.js読み込みおわったらページ内の全てのソーシャルプラグインのレンダリングが始まる
    • developer toolsのnetworkタブは凄いことに
    • 引数無しのtwttr.widgets.load()が必ず走ってしまう
    • ページ全体の全てのplaceholder(=プラグイン埋め込み予定地)でプラグインのロードが始まる
  • twitterはアカンが回避方法は一応。。
    • `twttr.widgets.load()`を空振りさせる
    • `twttr.widgets.load()`実行時点で、placeholderが0になればいい
    • twiterはfbやg+のようにレンダリングをオフにできるようにしてほしい
      • sdkの機能改善はちょこちょこしてるので期待
      • twttr.widgets.load(document.querySelectorAll(".lazy-share-widget .platform")[0])
  • 初期化のタイミングは気にしとく
    • SDKを非同期読み込みするから
  • FBオブジェクトがないのにFB.init()とかやってしまわない
  • とはいえ気にしないといけないのはfacebookだけ
    • google+はwindow.___gcfgプロパティにparsetags:"explicit"sdk読み込み前にセットしておけばいい
  • facebook sdkもそんなに大変じゃない
    • window.fbAsyncInit= fucntion(){....}....FB.init(...)書く
    • こう書けば安全にFB.init()できる
# g+
window.___gcfg = 
	parsetags:"explicit" # レンダリング=手動に
	lang:"ja" # ローカライズ
#facebook
window.fbAsyncInit = ->
	FB.init(
		xfbml:false
	)

# g+の___gcfgプロパティに設定できるオプションの話
# https://developers.google.com/+/web/+1button/?hl=ja
# 
# FB.init(options)のoptions一覧はここ
# https://developers.facebook.com/docs/reference/javascript/FB.init/

twitter sdk読み込み直後の自動レンダリングを回避する

  • g+やfbのと違って一手間必要
  • twttr.widegets.load(arg)はこんな動き
    • 引数にdomノードを渡すと、渡されたdomノードだけプラグインをレンダリング
    • 当然domノードがプラグイン予定地としてちゃんとマークアップされてないとアカンが
    • 例えば、a要素としてマークアップされててclassにtwitter-share-buttonが付けられてないと、レンダリングされない
    • 引数無しだと、ページ内部のすべてのプラグインのプレースホルダーを全部チェックして、レンダリングする
    • sdk読み込み直後に走るtwttr.widegets.load()はこれをやってる
  • twttr.widgets.load()プレースホルダがなければ空振りする
  • プレースホルダーかの条件
    • a要素か、blockquote要素
    • それぞれ決まったclass名がついてる
//cssセレクタで書くとこんな感じ
"a.twitter-share-button"
"a.twitter-mention-button"
"a.twitter-hashtag-button"
"a.twitter-follow-button"
"a.twitter-timeline"
"blockquote.twitter-tweet"
/*
http://platform.twitter.com/widgets.js
の後ろのほうに書いてある
*/

引数なし、ありを比較するとこんな感じ

# プラグインをロードする箇所を明示してる場合
twttr.widgets.load document.getElementById(".share")[0]

# twttr.widgets.load()ただするだけだとこんな感じになる
selector = "a.twitter-share-button"
selector += ",a.twitter-mention-button"
selector += ",a.twitter-hashtag-button"
selector += ",a.twitter-follow-button"
selector += ",a.twitter-timeline"
selector += ",blockquote.twitter-tweet"
jQuery(selector).each ->
	twttr.widgets.load @
  • プレーホルダーとして検出されないようにするやり方1
    • スニペットをちょっとだけ直す(class名かえとく)
<!--スニペットで、twitter-tweetになってるとこを、no-twitter-tweetにしといて、.load()する直前にclass名かえとく-->

<blockquote class="no-twitter-tweet">
<p>なんでや! 家入さん無関係やろ!
RT <a href="https://twitter.com/fukuyuki">@fukuyuki</a>: 今回のロリポップの大量ハッキング騒動で最も特筆するべきことは、この騒動の中、創業者である家入さんは「ネットも電気もお金もない砂漠の真ん中で一週間生活する」というバーニングマンというイベントに参加していたことだと思う。</p>
― やまもといちろう (@kirik) 
<a href="https://twitter.com/kirik/statuses/373370555464183808">August 30, 2013</a>
</blockquote>
  • その2
    • ボタンをオンザフライで生成するメソッドを使う
    • twttr.widgets.createShareButton()とか
//.share内部にボタンが挿入される

twttr.widgets.createShareButton(
 "http://hatena.ne.jp"
 document.getElementById(".share")[0]
 ->
   console.log "buttonできた"
   return
 count:"horizontal"
 text:"Hatena"
 lang:"ja" 
)

オンデマンドでプラグインをロード

  • sdkロード、sdk初期化が終わったあとの話
  • スクロールしたタイミング
  • ajaxやら、history api経由とかコンテンツ持って来たあととか
  • ここからはfacebook,g+,twitterはだいたい同じ
  • ロード用のメソッドにプレースホルダーのdomノード渡すだけ
###
引数に渡すdomノードは
placeholderそのものじゃなくて
placeholderの親要素でok
###
jQuery(.social).each ->
	#g+
	gapi.plusone.go @
	#twitter
	twttr.widgets.load @
	#facebook
	FB.XFBML.parse @
  • あとはイベント発火のタイミングとかであれこれ指定したらいい