コードを読んで理解する – Ajaxでlightbox.jsを使う時に注意するところ

最近lightbox.jsというライブラリを使って遊んでいます。

http://www.huddletogether.com/projects/lightbox/
http://www.huddletogether.com/projects/lightbox2/

lightbox.jsは画像のポップアップ表示を可能にするjavascriptライブラリですが、javascriptを一行も書かずとも

<script type="text/javascript" src="js/lightbox.js"></script>

と入れるだけで
あとは

<a href="images/image-1.jpg" rel="lightbox" title="my caption">image #1</a>

とaタグのrel要素のlightboxと書くと利用できてしまうすぐれものです。

コードを見ればわかりますが利用者にjavascriptを書かなくて済むようにするためにonloadでinitLightboxを呼び出してごにょごにょしています。

Ajaxのページではこのonloadでごにょごにょしているというところに注意点があります。たとえばprototype.jsのAjax.Updaterなどで動的にページの一部を更新する場合に、

<a href="images/image-1.jpg" rel="lightbox" title="my caption">image #1</a>

と入れてもonloadが呼び出されたあとだと意味がありません。通常のaタグのまま動作してしまいます。

さて、どうすればいいか。initLightboxでごにょごにょしているところを追ってみます。

ごにょごにょしていますが、重要なところを抜き出すと
lightboxの場合

if (anchor.getAttribute("href") && (anchor.getAttribute("rel") == "lightbox")){
  anchor.onclick = function () {showLightbox(this); return false;}
}

lightbox 2の場合

2008/12/06追記: 2.04ではmyLightboxというグローバルな変数は使わなくなっていました
// use the string.match() method to catch 'lightbox' references in the rel attribute
if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){
  anchor.onclick = function () {myLightbox.start(this); return false;}
}

と。どちらもやってることはaタグを探して、ref=”lightbox”であればonclickにshowLightboxを表示しretturn falseし、ページ遷移を抑止する。ということだけです。

つまりは、onload以降にAjaxなどで動的に要素を追加する場合は、それぞれ

<!-- lightbox -->
<a href="images/image-1.jpg" rel="lightbox" onclick="showLightbox(this); return false;" title="my caption">image #1</a>
<!-- lightbox2 -->
<a href="images/image-1.jpg" rel="lightbox" onclick="myLightbox.start(this); return false;" title="my caption">image #1</a>

と明示的にonclickに処理を書いてあげれば良いのです。

これで後から追加されたaタグでもlightboxを表示できます。

2008/12/06追記: 2.04ではmyLightbox変数を使わなくなっておりこの技が使えません

さて、lightbox 2では複数の画像でスライドショーもどきな表示を行うことができます。

コードを見てみると、表示を開始するところで・・・・

// if image is NOT part of a set..
if((imageLink.getAttribute('rel') == 'lightbox')){
  // add single image to imageArray
  imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title')));
} else {
  // if image is part of a set..
  // loop through anchors, find other images in set, and add them to imageArray
  for (var i=0; i<anchors.length; i++){
    var anchor = anchors[i];
    if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel'))){
      imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
    }
  }
  imageArray.removeDuplicates();
  while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
}

とrel要素でスライドショーする画像を集めていることがわかります。

本家のサイトではスライドショー表示するときには

<a href="images/image-1.jpg" rel="lightbox[roadtrip]">image #1</a>
<a href="images/image-2.jpg" rel="lightbox[roadtrip]">image #2</a>
<a href="images/image-3.jpg" rel="lightbox[roadtrip]">image #3</a>

というhtmlを例に出しています。

ここまで見たコードをもとにlightbox2では

  • rel要素に’lightbox’という文字が含まれているとonloadでonclickに処理が追加される
  • 同じrel要素をもつものでスライドショーが行える

ということが理解できます。

ちなみに先ほどのAjaxの例で明示的にonclickにlightboxを表示する処理を記述した場合は、
rel要素に’lightbox’という文字列を入れる必要はなくなります。

ですが、rel要素に何も入れない場合には、すべてのaタグでスライドショー表示を行おうとするので注意が必要です。’lightbox’という文字列を入れる必要はありませんが、なんらかの文字列を入れておくとよいでしょう。

2008/12/06追記: 2.04ではrel=’lightbox’は必須ぽいです