« capistrano で本番環境にデプロイ | メイン | 標準Java APIを使用したWebサービスへのアクセス »

SWFAddress2.0を利用した「状態」による機能制御はてなブックマークに追加 livedoorクリップに追加 Yahoo!ブックマークに追加 del.icio.usに追加 イザ!ブックマーク ニフティクリップに追加

こんにちは、JavaScript担当の(株)アークウェブの竹村です。

以前、「Flash|Ajaxベストサイトセレクション20」でご紹介していた
「Gucci」のサイトですが、今もなお、Ajaxによる画面遷移を行っています。

さて、この「Gucci」のサイトを語る上で外せないのが、オンラインショッピング ページのURLです。

例えば、↓こちらのバッグのURLへアクセスすると、バッグの詳細画面が表示されます。
http://www.gucci.com/us/us-english/us/spring-summer-08/web-exclusives/#0-179859-197020BCB1G7007

# 以下に商品を表すIDが振ってあります。

これを取ってアクセスすると、↓このカテゴリトップが表示されます。
http://www.gucci.com/us/us-english/us/spring-summer-08/web-exclusives/

このように商品詳細へ直接リンクを張ることを「ディープリンク」と呼ぶようです。
今回は、このディープリンクを実装する概念とライブラリをご紹介します。

レジュメは↓このようになっています。

  • SWFAddress2.0
  • タブ切り替えのサンプル
  • 初期化処理
  • イベントハンドラの処理
  • イベント駆動との違い
  • 状態の中のパラメータ
  • ディープリンクにアクセスしてみる
  • 次回予告


まず、SWFAddress2.0というディープリンクをお助けするライブラリがありますので、
このライブラリを使いながら、概念を理解していきましょう。

SWFAddress2.0

元々は、Flashにディープリンクをつけるためのライブラリとして登場しました。
Flashは 1画面上で画面遷移するので、ディープリンクが付けられなかったためです。

ただし、このライブラリは DHTML や Ajax でも利用可能なように作られています。

以下で、タブ切り替えを題材にサンプルを見ながら説明していきます。

タブ切り替えのサンプル

まず、普通にタブ切り替えを自作で作った場合は↓このようになるかと思います。

普通のタブ切り替え

タブをクリックしたら内容が切り替わるだけのサンプルです。

<script type="text/javascript" src="js/prototype.js"></script> <script type="text/javascript"> document.observe("dom:loaded", initialize, false); function initialize() { // タブクリック時のイベントハンドラの設定 $('tab_a').onclick = function(){ changeTab('tab_a'); }; $('tab_b').onclick = function(){ changeTab('tab_b'); }; $('tab_c').onclick = function(){ changeTab('tab_c'); }; // 初期状態 changeTab(); } function changeTab(sTarget) { switch(sTarget) { case 'tab_a': default: $('tab_a').className = 'active'; $('contents_a').show(); $('tab_b').className = 'unactive'; $('contents_b').hide(); $('tab_c').className = 'unactive'; $('contents_c').hide(); break; case 'tab_b': $('tab_a').className = 'unactive'; $('contents_a').hide(); $('tab_b').className = 'active'; $('contents_b').show(); $('tab_c').className = 'unactive'; $('contents_c').hide(); break; case 'tab_c': $('tab_a').className = 'unactive'; $('contents_a').hide(); $('tab_b').className = 'unactive'; $('contents_b').hide(); $('tab_c').className = 'active'; $('contents_c').show(); break; } } </script> (...) <span id="tab_a">TabA</span> <span id="tab_b">TabB</span> <span id="tab_c">TabC</span> <div class="contents" id="contents_a">これは TabA のコンテンツです。</div> <div class="contents" id="contents_b">This is contents of TabB.</div> <div class="contents" id="contents_c">TabC ノ コンテンツ デアル。</div>

※tag_aに関する部分のみ赤文字にしています。

initializeで、タブクリックのイベントハンドラを設定して、
changeTab関数で指定したタブを開くように組んであります。


では、SWFAddressを利用してタブ切り替えを作ってみます。

SWFAddress2を利用したタブ切り替え

iframeだとうまくいきませんね。。
お手数ですが、↓こちらにアクセスしてください。

▼SWFAddress2を利用したタブ切り替え
http://okra.ark-web.jp/~takemura/public/js/swfaddress2/sample_tab.html

<script type="text/javascript" src="js/prototype.js"></script> <script type="text/javascript" src="js/swfaddress.js"></script> <script type="text/javascript"> document.observe("dom:loaded", initialize, false); function initialize() { // タブクリック時のイベントハンドラの設定 $('tab_a').onclick = function(){ SWFAddress.setValue('tab_a'); }; $('tab_b').onclick = function(){ SWFAddress.setValue('tab_b'); }; $('tab_c').onclick = function(){ SWFAddress.setValue('tab_c'); }; // SWFAddressのイベント設定 SWFAddress.addEventListener(SWFAddressEvent.CHANGE, changeTab); } function changeTab(event) { // alert("■value:"+event.value+" ■path:"+event.path+" ■id:"+event.parameters["id"]); switch(event.path) { case '/tab_a/': default: $('tab_a').className = 'active'; $('contents_a').show(); $('tab_b').className = 'unactive'; $('contents_b').hide(); $('tab_c').className = 'unactive'; $('contents_c').hide(); break; case '/tab_b/': $('tab_a').className = 'unactive'; $('contents_a').hide(); $('tab_b').className = 'active'; $('contents_b').show(); $('tab_c').className = 'unactive'; $('contents_c').hide(); break; case '/tab_c/': $('tab_a').className = 'unactive'; $('contents_a').hide(); $('tab_b').className = 'unactive'; $('contents_b').hide(); $('tab_c').className = 'active'; $('contents_c').show(); break; } } </script> (...) <span id="tab_a">TabA</span> <span id="tab_b">TabB</span> <span id="tab_c">TabC</span> <div class="contents" id="contents_a">これは TabA のコンテンツです。</div> <div class="contents" id="contents_b">This is contents of TabB.</div> <div class="contents" id="contents_c">TabC ノ コンテンツ デアル。</div>

違っているのは、initializeの部分と、changeTabの引数が event になっています。

まずは initialize から見ていきましょう。

初期化処理

function initialize() { // タブクリック時のイベントハンドラの設定 $('tab_a').onclick = function(){ SWFAddress.setValue('tab_a'); }; $('tab_b').onclick = function(){ SWFAddress.setValue('tab_b'); }; $('tab_c').onclick = function(){ SWFAddress.setValue('tab_c'); }; // SWFAddressのイベント設定 SWFAddress.addEventListener(SWFAddressEvent.CHANGE, changeTab); }

SWFAddress.setValue('tab_a'); が実行されると、URLの末尾が #tab_a のように表示されます。

これが SWFAddress の現在の「状態」を表しています。
つまり「tab_a」の状態ということですね。

その下の SWFAddress.addEventListener の第1引数の SWFAddressEvent.CHANGE は
「状態」が変わった時を意味します。

第2引数の changeTab はイベントハンドラです。

では、イベントハンドラを見てみます。

イベントハンドラの処理

function changeTab(event) { // alert("■value:"+event.value+" ■path:"+event.path+" ■id:"+event.parameters["id"]); switch(event.path) { case '/tab_a/': default: $('tab_a').className = 'active'; $('contents_a').show(); $('tab_b').className = 'unactive'; $('contents_b').hide(); $('tab_c').className = 'unactive'; $('contents_c').hide(); break;

※長いので、tab_aとデフォルトの場合だけ表示しています。

引数に取る event は、SWFAddress から渡されます。

alert 部分のコメントアウトを外し、TabBをクリックすると

■value:/tab_b/ ■path:/tab_b/ ■id:undefined

と表示されます。

この event.path を使って「状態」に応じたタブ状況を作っていたわけです。

イベント駆動との違い

上記で作った 2つのプログラムですが、前者はイベントハンドラに「動作」を
設定しておく、いわゆる『イベント駆動』でした。

これに対して、後者はイベントハンドラに「状態」を設定しておき、状態が
変わったらそれを通知するようにセットしています。


どちらも、イベントに対して動作する点は変わりませんが、イベントを動作として
捕らえるか、状態として捕らえるかの違いがあります。

つまり、「状態をtab_bに変更せよ」という命令を受けたら、単にtab_bの状態を
作ればよいだけなのです。

今イベントハンドラが実行されたのか、後からディープリンクでアクセスされたのかを
意識することなく、単純に命令された状態を復元するだけでよい。ということです。

状態の中のパラメータ

上記の alert を見たときに、idってなんだ? と思われた方もいると思います。
これは、QueryStringに含まれるパラメータです。

次の例は、PopBoxの画像をクリックした時に、このパラメータを使って画像拡大を
実行するようにしています。

PopBoxによるパラメータの例

やっぱりiframeではダメなので、リンク先を示しておきます。

▼PopBoxによるパラメータの例
http://okra.ark-web.jp/~takemura/public/js/swfaddress2/sample_popbox.html

先ほど作ったタブの中にPopBoxを仕込んだ画像を入れてあります。
PopBoxについては↓こちらで学習できます。

PopBoxなので画像の部分は↓このようになっています。

<img id="pop_a" class="PopBoxImageSmall" alt="アークウェブ忘年会の画像" src = "samples/thm01.jpg" pbsrc = "samples/img01.jpg" pbCaption = "アークウェブ忘年会の画像" pbRevertText = "クリックで画像を閉じます" />

普通のPopBoxでは、このimgタグの中に onclick イベントハンドラで Pop という
関数を呼んで画像拡大をおこなっていましたが、今回は画像拡大を1つの「状態」として
扱いたいので、外しています。

では、画像がクリックされた時の状態を保持するためにイベントハンドラの設定を
追加している箇所を見てみましょう。

document.observe("dom:loaded", initialize, false); function initialize() { (...) // 画像クリック時のイベントハンドラの設定 $('pop_a').onclick = function(){ SWFAddress.setValue('tab_a/?pop=pop_a'); }; $('pop_b').onclick = function(){ SWFAddress.setValue('tab_b/?pop=pop_b'); }; $('pop_c1').onclick = function(){ SWFAddress.setValue('tab_c/?pop=pop_c1'); }; $('pop_c2').onclick = function(){ SWFAddress.setValue('tab_c/?pop=pop_c2'); }; // SWFAddressのイベント設定 (こっちは変わってません) SWFAddress.addEventListener(SWFAddressEvent.CHANGE, changeTab); }

各タブの中に、画像が全部で4つあるのでそれぞれSWFAddress.setValueで状態を
登録しています。

?以降がパラメータになります。普通にリクエストパラメータのGETと同じですね。

次に、このイベントを受ける changeTab を見ていきます。

function changeTab(event) { // alert("■value:"+SWFAddress.getValue()+" ■path:"+SWFAddress.getPath()+" ■pop:"+SWFAddress.getParameter("pop")); switch(SWFAddress.getPath()) { case '/tab_a/': default: $('tab_a').className = 'active'; $('contents_a').show(); $('tab_b').className = 'unactive'; $('contents_b').hide(); $('tab_c').className = 'unactive'; $('contents_c').hide(); popImage(SWFAddress.getParameter("pop")); break; (...) } } function popImage(pop) { if ($(pop)) { // タイトルを変更して画像をPop! SWFAddress.setTitle($(pop).alt+' | '+gsBaseTitle); Pop($(pop), 100, 'PopBoxImageLarge'); } }

今回は、上のタブ切り替えのサンプルとは違う方法で、値を取得するようにしました。

以前:event.value, event.path, event.parameters["pop"]
今回:SWFAddress.getValue(), SWFAddress.getPath(), SWFAddress.getParameter("pop")

さて、この場合の alert もコメントを外して表示したら、どのように
表示されるかというと

■value:/tab_b/?pop=pop_b ■path:/tab_b/ ■pop:pop_b

と表示されます。

path は変わらないので今まで通りのタブ表示/非表示の処理が走ります。

popImage という関数を追加しています。changeTab 関数は、
パラメータで受け取った pop を渡して、画像拡大のトリガーである
Pop 関数を実行するようにしています。

Pop 関数の手前の SWFAddress.setTitle は titleタグを変更することができます。
これによって、ブラウザの「戻る」をリストさせたときに
どこにもどれるのか一目瞭然となります。

ディープリンクにアクセスしてみる

上記のPopBoxのサンプルから、ディープリンクを使ってアクセスしてみます。

▼TabCの画像1(pop_c1)を表示した状態にアクセス!
http://okra.ark-web.jp/~takemura/public/js/swfaddress2/sample_popbox.html#/tab_c/?pop=pop_c1

遷移先画面で「TabC」に切り替わって、自動的に画像1が拡大表示されたと思います。

次回予告

次回は、マッシュアップアプリを作りながら、このSWFAddressの実演をしてみようと
思っています。

お楽しみに~☆