Lightbox互換なImage Lightboxの作り方

このサイトの目的

Javascriptライブラリ”Image Lightbox”と古い”Lightbox”に互換性を持たせます。

いわゆるLightbox

Lightbox“はブログの画像表示に使われる定番のJavaScriptです。
古くは”Prototype Js“などで実装されていましたが、最近は”jQuery“版の方が人気があるようです。
ライセンスがCreative Commonsであるため、カスタマイズしたバージョンが山のように見つかります。
僕が愛用していたのは”jQuery lightbox plugin”というものですが、これはiPhone普及以前に書かれたコードであるため、モバイル機器の小さな画面ではレイアウトが乱れるという問題があったのでした。

Section001_002.jpg
画面が広い場合のLightbox。画像全体が表示されている。
Section001_001.jpg
画面が狭い場合のLightbox。画像の端が途切れている。


そこでImage Lightbox

Section002_001.jpgレイアウトが乱れないLightboxを探したところ、”Image Lightbox”が良さそうでした。
コードが非常に小さくてシンプルなのでカスタマイズも簡単そう。
本家ページのデモを動かしてみるとモバイルでも奇麗に表示されています。
本稿ではこのサンプルコードをベースに、 旧LightboxImageLigtboxの互換性を検討します。

互換性の問題

ウェブサイトのLightboxをImage Lightboxに置き換える作業を開始すると、色々と困った事に気づきます。
両者は殆ど同じ機能を持っているのですが、呼び出し側の記述が少し異なっているのです。

/*旧Lightboxの記述法*/
<a href=”image001.jpg” rel=”lightbox[group-a]” alt=”タイトル1”><img src=”image001.jpg” alt=”image001″></a>

/*Image Lightboxの記述法*/
<a href=”image001.jpg” data-imagelightbox=”a”><img src=”image001.jpg” alt=”タイトル1”></a>

両者は「このタグはLightboxですよ」という宣言が異なっています。また、画像拡大時に表示されるタイトルも、A要素に持たせるかIMGに持たせるかという違いがありました。
Image Lightboxを導入しようとしたら、今までに書いた旧Lightbox用のタグを全て書き換えなければいけません。
これは困った・・・

グループ化の難しさ

更にコードをよく見ると、グループ化の方法も異なっています。
1ページ中に複数の画像グループがある場合、旧LightboxではHTMLを書く時にrel=”lightbox[group-a]“のように[]内に適当な文字列を入れておけば、勝手にグループ化してくれました。
しかしImage Lightboxは予め data-imagelightbox=”a”などとして、”a”の部分はJavascriptで定義しておく必要があるみたいです。
つまり、予め設定した有限個のグループしか持つことができず。同じページ内で識別子がバッティングしないように、ユーザー側が慎重にグループ名を選ぶ必要がでてきます。
これは取り回しが悪そう・・・

画像グループ1。この3枚だけがループ表示される。
画像グループ2。この3枚だけがループ表示される。


Image Lightboxを読んでみる

過去のHTMLを書き換えるのは現実的ではないので、Image Lightboxのコードを触ることになります。
どんな高度な内容かと恐る恐るコードの中身を見ると・・実にシンプルで分かり易い。
これなら何とかなりそうです。

呼び出し方式の違い 

先ずは、呼び出し方式の違いを何とかします。
Image Lightboxのコードは次の通り。
要するにjQueryのセレクタで、”data-imagelightbox”タグを持つA要素を探し出し、メソッドのimageLightbox()を呼び出しているんですね。

/*Image Lightbox修正前:*/
$( ‘a[data-imagelightbox=”a”]’ ).imageLightbox();

したがって、Lightboxのトリガーを “data-imagelightbox”でなく、rel=”lightbox”に変えてやればOK。

/*Image Lightbox修正後:*/
$(‘a[rel=”lightbox”]).imageLightbox();

タイトル取得方法の違い

続けてタイトルの読み出し方の違い。
Image Lightboxでタイトルを読み出しているのは次のコードになります。記述法はヤヤコシイですが、要するに「”A”要素の直下にある”IMG”要素の”ALT”タグをタイトルとする」という意味ですね。

/*Image Lightbox修正前:*/
var description = $( ‘a[href=”‘ + $( ‘#imagelightbox’ ).attr( ‘src’ ) + ‘”] img’ ).attr( ‘alt’ );

旧Lightboxに合わせるため、”A”要素の”TITLE”要素を読み出すようにします。

/*Image Lightbox修正後:*/
var description = $( ‘a[href=”‘ + $( ‘#imagelightbox’ ).attr( ‘src’ ) + ‘”]’ ).attr( ‘title’ );

Image Lightboxを書き換える

更にグループ化にも対応させます。

問題を整理すると、同じページに多数のLightbox画像があり、それぞれ以下のように適当な(Javascript側からすると未知の)グループ名が振られているとします。
このとき、Javascript側は、「グループfooは画像が3枚」「グループbarは画像が2枚」「グループquxは画像が4枚」。などと解釈して、グループ事にimageLightbox()メソッドを呼び出してやる必要があります。

rel=”lightbox[foo]”
rel=”lightbox[foo]”
rel=”lightbox[foo]”

rel=”lightbox[bar]”
rel=”lightbox[bar]”

rel=”lightbox[qux]”
rel=”lightbox[qux]”
rel=”lightbox[qux]”
rel=”lightbox[qux]”

文章にするとヤヤコシイですが、jQueryはこの辺りが実に簡単。

1:var lbarr=[];
2:$(“a[rel^=’lightbox’]”).each(function(){
3:  lbarr.push( $(this).attr(“rel”) );
4:});
5:var tmparr = $.unique(lbarr);
6:for(var i=0;i<tmparr.length;i++)
7:{
8:  var reltxt = ‘a[rel=”‘+tmparr[i]+'”]’;
9:  $(reltxt).imageLightbox();
10:}

2行目のjQueryセレクタで、rel=”lightbox[group_name]”を含んだA要素から、relの中身を文字列として取得します。
5行目のunique関数で、relの配列(lbarr)から、ユニークな文字列だけを取り出します。
上の例だと、tmparrの中身は”lightbox[foo]”,”lightbox[bar]”,”lightbox[qux]”の3要素になります。
これでグループ化は完了。
8行目はグループ名に基づいてjQueryのセレクタ文字列を作っています。
9行目でセレクタを使い、relの中身が同じA要素を一つのグループとしてLightboxを起動しています。

補足

今回はLightboxグループ化の記述として”lightbox[groupname]”を例に挙げました。しかしこの”[]”という記述はXHTMLでは文法エラー扱いになってしまいます。(実行はできますが)

奨励される書き方は rel=”lightbox-groupname”やrel=”lightbox.groupname”とのこと。
上記のコードはこの表記にも対応してしますので、お好きな文法で書いて下さい。

このコードはrel=””の引用府の中の文字列を比較して、同じ文字列なら同じグループという判定をしているのです。
従って、rel=”lightbox[A]”とrel=”lightbox-B”という風に表記が混在していても動作します。
ただし、”lightbox[A]”と”lightbox-A”は別のグループ扱いですが。

結論

背景色などを微調整した改造版コードの動作デモです。
改造前後のコードは下記からダウンロードできます

この改造版コードだと、Image Lightboxのコアファイル(“imagelightbox.js”)は変更せずに済みます。
旧LightboxのJSとCSSを次のように書き換えれば、HTML本文を変更しなくてもImage Lightboxが起動するはずです。

/* 旧Lightboxの呼び出し部を下記に変更すれば Image Lightboxが起動する*/
<link rel=”stylesheet” href=”js/style.css” />
<script src=”js/imagelightbox.min.js”></script>
<script src=”js/activate-lb.js”></script>

2014年7月9日