Simplicityを少し改造してみた 番外編 part15 SNSシェアボタンを無理やり改造する

Simplicityにはいくつかシェアボタンの表示方法が用意されているわけですけれども、これを独自に何とかできないものかと考えられている人は多いと思います。
カスタマイズするにしても、どのようにすれば良いのかわかりにくいとか、css設定したけどうまく適用されないとか色々あるでしょう。まぁたいていはcssで何とでもなるんですけど。

cssよりも後でjQueryは読み込まれます。つまり、jQueryはcssを書き換えるにあたって最強の環境を持っているのですが、いかんせん元がjavascriptなので、javascriptが動かないとjQueryも動かないと言うのもあり、今のご時世にjavascriptを切ってサイトを見てる人ってたくさんはいないと思うんですけれども、それでも中にはそういう人もいるのでjQuery(js)最強と言うのは言い切れない部分もあったりするのですが、それでもその機能は強力です。

そういうわけで、タイトル下にあるシェアボタンをjQueryで書き変えてみようと言う感じでやってみました。
シェアボタンの解説は以下のブログカードより。

jQuery 横並びリストのリストアイテムをアニメーション表示
例えばシェアボタン、あるいはフォローのボタンと言うのは、もちろん予めその内容を表示していても良いのですが必ずしも表示していないといけないとい...

See the Pen WordPressThemeSimplicity SNS button applied to Simplicity by Hidekichi (@Hidekichi) on CodePen.

これがそのサンプルです。
シェアボタンのアイコン部分<span class=”icon-xxxx”></span>の部分がcodepenで表示できなかったので、その部分だけfont-awesomeで書き換えています。icon-xxxxが表示できる環境があれば、このままでうまく行くのではないかなぁと思ったりしてます(試してない(笑))。

何をしてるか

今回は色々機能を盛り込みました。
単純にシェアボタンを入れるだけであれば、現状で表示しているSNSの種類とそのカウンターの数値だけ抜き出しておいて、一旦表示されているシェアボタンを削除し、そこに新たなシェアボタンを入れ込んで、SNSの種類と数値を入れればもっと簡単に短くできるはずなんですが、今回は、jQueryでできるDOMの書き変え、移動など結構色々なことをしています。

  • 既存のシェアボタンの構成を書き変えてます
  • シェアボタンがブラウザの表示領域に入ったら、シェアボタンの横にメッセージ表示
    • リストアイテムが表示されている時は非表示
    • 発火条件はロード、スクロール、リサイズ
  • メッセージは2秒間で自動で消えます
  • 簡易スキン機能(要css用意)で、色をすぐに変更することができます

機能的にはこんな感じでしょうか。スクリプトの半分ぐらいはDOMの書き変えです(笑)
多くの部分で、スクリプトにコメントを入れてあるので何をしているのかはだいたいわかるかも知れません。

いくつかDOMの書き換え以外で利用している方法を紹介してみたいと思います。

任意の条件でリストアイテムのaリンクを無効・有効化する

方法的には上記のような感じです。

$(“#sns-group-top li”).find(“a”)は、#sns-group-topつまりはタイトル下のSNSボタンの中のli、さらにその中にあるaタグと言うような意味です。.each()の部分は、そのそれぞれに対してと言う意味合いになります。
.each()の中にある、$(this)は、$(“#sns-group-top li”).find(“a”)になります。つまり、aタグのリンクそれぞれと言う感じの意味合いです。

それらをクリックした時、disable_aと言う関数が呼び出されます。disable_aはイベントのデフォルトの動作、つまりはaタグならリンクを貼ると言うような動作を無効にします。正しくは

イベントがキャンセル可能である場合、上位ノードへのイベントの 伝播 (propagation) を止めずに、そのイベントをキャンセルします。

というような意味です。本来aタグはクリックするとそのアドレスに飛びますが、それをキャンセルさせるという意味合いになります。

ここで、例えばaタグの動作をキャンセルしたは良いが、次に何かしらの条件が揃った時にまた動作させたいと言うことがあるかと思います。それらの切り替えをしているのが、.on()と.off()です。

昔からjQueryを触っている人は、ついつい、$(セレクタ).click(function(…))と書きたくなります。セレクタがクリックされた時と言うことなのでわかりやすいと言えばそうなのですが、.on()、.off()を使うともっと汎用性が上がります。特に後から追加したものへのイベントの追加と言うか、例えばajaxで書きだした要素は、本来のhtmlの中には存在せず、後からajaxの処理よってhtmlに追加されたもの、あるいは書き変えられたものになります。

$(セレクタ).ready(function(){…})は、セレクタの準備ができたらと言う意味合いです。仮に$(document).ready(function(){…})だったら、documentの準備ができた時、つまりはページの準備ができた時と言うことになり、ajaxで処理をして書きだした要素は、ページの準備ができたその時には存在しないものになるわけです。

その要素に対して、clickなどのイベントを付けたい場合は、$(セレクタ).click(function(){…})では対応できません。なので後づけできる.on()なのです。

.on()と.off()があるように、これらはスイッチのように利用できます。上記のdisable_aでいうと条件が必要になりますが、例えば

このようにあった場合、#sns-group-top liのaのリンクはまず無効になります(ifの外側で実行している処理があるため)。その中で、#sns-group-top ulが、onclickと言うクラスを持っている時は、先ほどの無効のスイッチが入っているので、それを.off()、つまり有効に切り替えます。ulが.onclickを持っている状態はリストアイテムが表示されている状態です。

流れとして、
aタグのリンクを無効にしておく。
もし、ターゲットのulがonclickを持っている場合は、リストアイテムが表示されているので、
.off()にて、無効の状態のスイッチをoffにして、有効にします。
もし、ターゲットのulがonclickを持っていない場合は、リストアイテムが閉じている状態なので、
.on()にて、有効の状態のスイッチをonにして、無効化します。

このスイッチは無効化するスイッチなので、onとoffが逆の意味合いになります。普通だと、onで有効、offで無効ですが、それが逆になるわけです。

なぜこんなことをするかと言いますと、今回施したシェアボタンは、デフォルトでリストアイテムを非表示にしています。非表示にしていますがopacityが0になっているだけで、非表示というよりは透過させてあるだけなので、そこにボタン自体はあるのです。
初期状態でul(シェアボタン)の下に隠れているので、ほとんどの場合はそのリンクをクリックすることはないと思うんですが、はみ出しているaタグのリンクの有効範囲をクリックしてしまうと、ページの遷移があるため、リストアイテムが表示されるまではリンクを無効化しておく必要があったわけです。

ブラウザの表示領域に目的の要素があるかどうかを調べる

これは、function view()の部分がしています。
必要な事として、ウィンドウの高さと、調べる要素(ターゲット)の位置(座標)が必要になります。

ある要素の座標は、$(ターゲット).offset()で求められます。offset()はdocumentの左上が0,0(top,left)になります。何かしらの親要素からの座標を求める時はposition()を使いますが、ターゲットがページのどこにあるかを調べたいわけなので、offset()を利用しています。
もしtopの座標を求めたい時は、$(ターゲット).offset().top;で値を拾うことができます。

仮に、ターゲットのx座標が10、y座標が1000の位置にあるとしましょう。
$(ターゲット).offset(); = 10,1000 = top:1000,left:10と言う値が求められます。またウィンドウの高さは、$(window).height()で求められます。

もし、ターゲットがスクロールしないと見えない位置にあると、スクロールが必要になるので、スクロールの位置も取得します。これは、$(window).scrollTop();で求められます。

ウィンドウが500pxの高さを持っているとします。すると、ターゲットの座標は1000ですから、スクロールしていない状態、0〜500px(ウィンドウの高さ)ではターゲットは見えずそこまでスクロールしないと画面内には無いという事になります。ここから、

スクロールすると、スクロールのトップを上辺として画面の高さ分ある領域が動くことになります。ターゲットの座標がこの範囲より小さくなった時に画面内に入ったとわかります。つまりは、

また、ターゲットが画面内にあると言う時は、ターゲットのY座標の位置にターゲットの高さを足した範囲の要素がスクロールトップを通り越した時に画面外に行った、つまりは、通り越すまでが画面の中にあると言えるので、

これで画面内にあるかどうかがわかります。これらを&&でどちらもtrueの時と言う条件で判断します。そうすれば、必ずターゲット要素が画面内にある時を判断できることになります。

とまぁ、こんな感じになります。

n秒間だけ要素を表示する

ここまで書いておいてアレなんですが、各関数の(target)はjQueryオブジェクトではなく単純に”.tips”などとセレクタが入ってます。もしjQueryオブジェクト($(“.tip”)等)で関数の引数にするのであれば、上記スクリプトは、target.fadeIn()…のようになりますのでご注意を。

まず、targetをfadeInさせて表示します。それに対してqueueを送り、limitミリ秒経過した後、dequeueでキューをキャンセルします。キューをキャンセルすると次の$(target).fadeOut();が実行されるという仕組みです。

まとめ

色々な手法を使って、何とか実装できるんじゃなかろうかという所までは持ってきましたが、DOMの操作だけでお腹いっぱいになってしまうぐらいに面倒臭いです。しかも、仮に仕様変更があった場合に対応するためにはスクリプトを変更していかねばならず大変なので、何とかやってはみたもののオススメはできません。

これならば、最初の方にも書きましたが、

  1. シェアボタンの位置をチェックしておく
  2. シェアボタンに記載されているSNSの種類と、そのカウントを取得しておく
  3. jQueryで元のシェアボタンと、新規のシェアボタンを入れ替え
  4. 取得しておいたデータ分だけliを作って、そこにアイコンとカウント値を入れる

この方がよっぽどスムースに対応できます。

技術参考サイト:
jQuery Snippet List
プログラムメモ | jQuery
jquery.inview | GitHub

スポンサーリンク

シェアする

フォローする