‘Ajax’ タグの投稿

コードを読んで理解する – 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’という文字列を入れる必要はなくなります。(2008/12/06追記: 2.04ではrel=’lightbox’は必須ぽいです)
ですが、rel要素に何も入れない場合には、すべてのaタグでスライドショー表示を行おうとするので注意が必要です。’lightbox’という文字列を入れる必要はありませんが、なんらかの文字列を入れておくとよいでしょう。

Spryの$()を使う

prototype.jsと言えばAjaxのライブラリと思われがちです。ただコードを見た人はわかると思いますが名前の通りprototype指向のjavascriptを機能を拡張するライブラリです。
Ajaxを使うどうかとは別問題で、JavaScriptでの処理結果をHTMLで表示する場合は、

みたいなのをあらかじめ書いておいて、

みたいに書くと思います。
prototype.jsを使うとdocument.getElementById(“content”)を$(“content”)と置き換えることができるのでコードを速く書く、短く書くにはもってこいです。
さてAdobeのAjaxフレームワークのSpryにも$(“”)が用意されています。僕が試しているのはver1.6ですが、SpryDOMUtils.jsをincludeするとSpry.$(“”)が使えるようになります。Spryオブジェクトのfunctionで使えるのでprototype.jsの$(“”)と競合することはありません。