« ひとりサービスの雛型をつくる(リキッドレイアウト、GetText、Acts as Authenticated) | メイン | PHP での簡単なマッシュアップ »

Flickrとのマッシュアップ!(PopBoxとdhtmlxGrid) その1はてなブックマークに追加 livedoorクリップに追加 Yahoo!ブックマークに追加 del.icio.usに追加 イザ!ブックマーク ニフティクリップに追加

こんにちは、JavaScript担当の竹村です。

先日、Adobe MAX Japanに行ってまいりました。
ケビン・リンチ氏の「重要なのは"UI"ではなく"コンテンツ"」という部分にいたく共感しまして、JavaScriptを使って"コンテンツ"を構築してみようかと思い立ちました。

それでは、どのような"コンテンツ"を作ってみるかを検討します。

rough_image.jpg
↑クリックで拡大

手書きでスミマセン^^;
簡単に説明すると画像系のAPIでコンテンツの素を取ってきて、それをMyリストに登録し、選りすぐったMyリストにコメントを付けて保存。他人が保存したリストも見れるようにして、面白い組み合わせを作って楽しもう!
といったところです。

題して!
『画像検索マッシュアップ - 僕のお気に入り』というサービス名で作ります。

さっそく、タスクを考えました。

  1. [検索]をクリックすると、Flickr検索の画像検索APIを利用して画像検索を要求します
  2. レスポンスをHTMLに描画します
  3. この画像をクリックすると、PopBoxで大きく表示されます
  4. 表示された画像の[追加]をクリックすると、Myリストに追加できます
  5. [保存]すると、、、

[保存]から先の動作はとりあえず置いておいて、まずは1~4を作りましょう。


できあがりサンプルも置いておきますので、あわせてご覧ください。

▼画像検索マッシュアップ - 僕のお気に入り 【タスク1~4まで】
sample_image.jpghttp://okra.ark-web.jp/~takemura/public/js/my_favorite/

1.Flickrの画像検索のリクエスト送信

まずは、Flickrの画像検索APIを使って、入力した『キーワード』に該当する画像を手に入れます。
とはいえ、実はFlickrのAPIを使うには API Key を取得する必要があります。

▼Flickr API Keyの取得
http://www.flickr.com/services/api/keys/

取得できたら、いよいよAPIを使ってみましょう。

リクエスト パラメータ

 // リクエストURLの生成
 var sUrl = 'http://www.flickr.com/services/rest/?'+
    'api_key=#{api_key}&method=#{method}&text=#{text}&'+
    'per_page=#{per_page}&format=#{format}&jsoncallback=#{callback}';
 sUrl = sUrl.interpolate({
   api_key : 'あなたのFlickr API キー',
   method : 'flickr.photos.search',
   text : $F('search-keyword'),
   per_page: 20,
   format : 'json',
   callback: 'jsonFlickrApi'
   });

『http://www.flickr.com/services/rest/』のURLに、パラメータを渡しています。
#{...}は、変数名.interpolate({key:value[,key:value,...]})
変数名に含まれる#{key}をvalueに置換する prototype.js 1.6.0 の機能です。
interpolateで変換した後は、返値を取得し直す必要があるので注意してください。

その他にもユーザ名での検索や、タグでの検索がパラメータとして用意されています。
↓こちらの記事がパラメータを含め詳しく書いてありました。

▼第2回 JavaScriptからFlickr APIで画像検索
http://itpro.nikkeibp.co.jp/article/COLUMN/20061101/252356/

あ、そういえば、text: $F('search-keyword') となっていますが、$Fもprototype.jsの機能です。引数で指定したidのフォーム値を返します。

<input id="search-keyword" type="text" name="keyword" value="モーターショー" />

デフォルトのままなら、『text: モーターショー』で検索します。

scriptタグによるリクエスト発行

scriptタグを書いてFlickr APIへのURLを渡すわけですが、ここで使いやすいライブラリがあります。

▼jsr_class.jsライブラリ
http://www.xml.com/pub/a/2005/12/21/json-dynamic-script-tag.html

jsr_class.jsというライブラリで↓このように記述するとscriptタグを追加してくれます。

 <script type="text/javascript" src="js/jsr_class.js"></script>
 (...)
 // script タグの発行
 goJsr = new JSONscriptRequest(sUrl);
 goJsr.buildScriptTag();
 goJsr.addScriptTag();

これにて、Flickr APIへのリクエスト発行は完了です!

2.APIのレスポンスを画面に表示

Flickr APIへのリクエスト パラメータに下記のように設定していました。

   format : 'json',
   callback: 'jsonFlickrApi'

Flickr APIはこのcallbackの関数を実行してくれます。また、指定したフォーマットを
引数として取れます。上記の場合は json を指定してありました。

ではコールバック関数について見ていきましょう。

Flickr APIのコールバック関数

function jsonFlickrApi(oJson) {
 // データが取得できているかチェック
 if (oJson.stat != 'ok') return;
 var aPhotoList = oJson.photos.photo;
 
 // script タグの削除
 goJsr.removeScriptTag();
 
 // 現在の画像領域をクリア
 Element.remove('photo_detail');
 var oDiv = document.createElement('div');
 oDiv.id = 'photo_detail';
 $('photo_area').appendChild(oDiv);
 
 // 各画像の描画
 for (var i = 0 ; i < aPhotoList.length ; i++) {
  // 5件毎に改行
  if (i % 5 == 0) new Insertion.Bottom(oDiv, '<br/>');
  // 画像を設定して、画像表示部分へ追加書き込み
  var sImg = '<img class="PopBoxImageSmall" '+
     ' src="http://static.flickr.com/#{server}/#{id}_#{secret}_s.jpg" '+
     ' pbsrc="http://static.flickr.com/#{server}/#{id}_#{secret}.jpg" '+
     ' pbCaption="<a href=\'javascript: addMylist('+ i +');\'>[Myリスト追加]</a>" '+
     ' title="#{title}" '+
     ' onclick="Pop(this, 100, \'PopBoxImageLarge\')" />';
  new Insertion.Bottom(oDiv, sImg.interpolate(aPhotoList[i]));
 }
 gaPhotoList = aPhotoList;

直後の ok かどうかのチェックを行っています。メンテナンス等で取得できなかった場合の処理は割愛しました。

goJsr.removeScriptTag();」は、先ほど『scriptタグによるリクエスト発行』で追記したscriptタグを削除します。

「現在の画像領域をクリア」というブロックで行っているのは、2回目の[検索]ボタンクリックの際に、前の画像を削除するのに指定しています。

Element.remove('photo_detail');」は、prototype.jsの機能で$('photo_detail')エレメントを削除します。その後、DOMのdocument.createElementで divタグを生成して、再度消せるように id を振って親エレメントに割り付けしています。

次に画像の描画周りについて説明します。

画像の描画

この部分は、PopBox用に色々な属性が指定してあるので、一見複雑そうに見えますが、
PopBoxを使わない場合は↓こんなところです。

  var sImg = '#{title}';
  new Insertion.Bottom(oDiv, sImg.interpolate(aPhotoList[i]));

あまり説明がいらないほどシンプルですね。

Insertion.Bottomは、prototype.jsの機能です。第1引数の要素に第2引数の内容を後ろに追加します。追加する内容は、imgタグで画像のURLが指定してあるものを interpolate で置換して返値を渡しています。

では、お待ちかね(?)のPopBoxによる画像の拡大です。

3.PopBoxによる大画像の表示

…と、行きたいのですが、ちょっとまた長くなりすぎになってきました。。
一旦、詳しく説明するのはここまでとして、さらっと、どんなことを
やったのかソースと共に書いておきます。

  // 画像を設定して、画像表示部分へ追加書き込み
  var sImg = '<img class="PopBoxImageSmall" '+
     ' src="http://static.flickr.com/#{server}/#{id}_#{secret}_s.jpg" '+
     ' pbsrc="http://static.flickr.com/#{server}/#{id}_#{secret}.jpg" '+
     ' pbCaption="<a href=\'javascript: addMylist('+ i +');\'>[Myリスト追加]</a>" '+
     ' title="#{title}" '+
     ' onclick="Pop(this, 100, \'PopBoxImageLarge\')" />';

imgタグを配置するときの属性として、srcの他にpbsrcという属性が渡せます。これが、拡大時の画像になります。
拡大画像の下にキャプションを表示でき、pbCaptionの部分で指定できます。

また、title属性を指定すると、画像のaltが自動的に付きます。
onclickイベントハンドラで、拡大画像をポップアップ表示します。

↓こちらにPopBoxのドキュメントがあるので、今回使わなかった機能については確認できます。

▼Pop Box ドキュメント
http://www.c6software.com/Products/PopBox/Documentation.aspx

PopBoxは以上ですが、次回は復習からじっくりやりますのでお楽しみに(?)^^;

4.Myリストの操作

MyリストのExcelのような表示は、dhtmlxGridというライブラリを使用しています。

▼dhtmlxGrid
http://dhtmlx.com/docs/products/dhtmlxGrid/index.shtml

では、ソースと共に概要だけさらっと紹介します。

<link rel="stylesheet" type="text/css" href="js/dhtmlxGrid/dhtmlxgrid.css">
<script type="text/javascript" src="js/dhtmlxGrid/dhtmlxcommon.js"></script>
<script type="text/javascript" src="js/dhtmlxGrid/dhtmlxgrid.js"></script>
<script type="text/javascript" src="js/dhtmlxGrid/dhtmlxgridcell.js"></script>
<script type="text/javascript" src="js/dhtmlxGrid/excells/dhtmlxgrid_excell_link.js"></script>
 (...)
 // Myリスト用DataGridを生成
 goMylistGrid = new dhtmlXGridObject('mylists');
 goMylistGrid.imgURL = "js/dhtmlxGrid/imgs/";
 goMylistGrid.setHeader("image, タイトル");
 goMylistGrid.setInitWidths("100,250");
 goMylistGrid.setColAlign("left,left");
 goMylistGrid.setColTypes("ro,link");
 goMylistGrid.setColSorting("str,str")
 goMylistGrid.setColumnColor("white,#d5f1ff")
 goMylistGrid.init();
 (...)
// Mylistに追加する
function addMylist(no) {
 var oPhoto = gaPhotoList[no];
 var sImg = '<img alt="" '+
  src="http://static.flickr.com/#{server}/#{id}_#{secret}_s.jpg"/>'.interpolate(oPhoto);
 goMylistGrid.addRow(
  1,
  sImg+',#{title}^http://www.flickr.com/photos/#{owner}/#{id}/'.interpolate(oPhoto),
  1);
}
 (...)
<p>Myリスト</p>
<div id="mylists" width="325" height="250"></div>

初期化処理で、MyリストのdhtmlXGridObjectを生成して、各種設定をしています。
ヘッダー部分は、日本語や画像も通ります。

データのCell部分は、リンクや画像が利用できます。

↓dhtmlxGridのドキュメントはこちらにあります。

▼dhtmlxGrid ドキュメント
http://dhtmlx.com/docs/products/docsExplorer/index.shtml?node=dhtmlxgrid


今回は、ほとんどFlickr APIとのマッシュアップ部分だったので、イマイチだったかもしれませんが、次回は中身を詳しく説明していく予定です。