パターンとライブラリで作るAjaxおいしいレシピ
連載一覧へ
パターンとライブラリで作るAjaxおいしいレシピ(2)

prototype.jsでYouTubeをインクリメンタルサーチ


アークウェブ株式会社
志田 裕樹
2007/10/4


モデル:前回のキーワードと異なればJSONPで検索

 次に、モデルクラスを見てみましょう。

youtube.LiveSearch = Class.create({
    /**
    
 * コンストラクタ
    
 */
    initialize: function(keyword) {
        this.previousKeyword = keyword;
    },
    /**
    
 * 前回のキーワードと異なればJSONPで検索
    
 */
    search: function(keyword, callback) {
        if (this.previousKeyword != keyword) {
            var url = 'http://gdata.youtube.com/feeds/videos?' +
                        'vq=#{keyword}&alt=json-in-script&'+
                        'callback=#{callback}&max-results=9';
            url = url.interpolate(
                {keyword: encodeURIComponent(keyword),
                callback: callback});

            jsonp = new JSONscriptRequest(url);
            jsonp.buildScriptTag();
            jsonp.addScriptTag();
            this.previousKeyword = keyword
        }
    },
});
- PR -

 このクラスはメンバ変数として、前回のキーワード「previousKeyword」を持っています。

 searchメソッドで、今回のキーワードと前回のキーワードが異なったら、GData YouTube APIの動画検索用URLを作り、JSONscriptRequestクラスを使って、JSONPの処理を行っています。

 URLを作るために、String#interpolate()を使用していますが、これについてはビューのところで解説します。

参考
・YouTubeの動画検索APIの仕様YouTube Data API Developer's Guide
・GDataのJSONPの仕様Google Data APIs (Beta) Developer's Guide - Using JSON with Google Data APIs

ビュー:prototype.js 1.6.0 rc0のテンプレート機能拡張

 最後にビューのコードを見てみます。

youtube.LiveSearchView = {
    /**
    
 * 検索結果一覧の更新
    
 */
    update: function(videos) {
        var entries = videos.feed.entry;
        var html = "";
        if (! entries) {
            html = '<span class="not_found">' +
                '検索結果が見つかりませんでした。</span>';
        }else {
            entries.each(
            function(entry, index) {
                var template =
                    '<div id="#{id}" class="video">' +
                    '  <a href="javascript:void(0)">' +
                    '    <img class="thumbnail" src="#{thumbnail}"' +
                    '      width="#{width}" height="#{height}"' +
                    '      alt="#{title}" />' +
                    '  </a>' +
                    '  <a href="javascript:void(0)">' +
                    '    <div class="title">#{title}</div>' +
                    '  </a>' +
                    '</div>';
                html += template.interpolate({
                  id:entry.id.$t.match(/\/([^\/]+)$/)[1],
                  thumbnail:entry.media$group.media$thumbnail[0].url,
                  width:entry.media$group.media$thumbnail[0].width,
                  height:entry.media$group.media$thumbnail[0].height,
                  title:entry.title.$t
                });
                if (index % 3 == 2) {
                    html += '<br class="clear" />';
                }
            });
        }
        $('search_results').update(html);
    },
    /**
    
 * クリックされた動画をLightWindowで表示
    
 */
    show: function(video) {
        var so = new SWFObject("http://www.youtube.com/v/"+video.id,
        "video", "425", "353", "7", "#FFFFFF");
        so.write("player");

        myLightWindow.activateWindow({
            href: document.location + '#player',
            width: 425,
            height: 353,
            title: video.getElementsByClassName('title')[0].innerHTML
        });
    }
};

 Googleから受け取るJSONの形式は大まかに次のようになります。

{feed:
    {entry:
        [
            {id:
                ……(略)……,
            media$group:
                {media$thumbnail:
                    [
                        {height: ……(略)……,
                         url: ……(略)……,
                         width: ……(略)……},
                        {height: ……(略)……}
                    ],
                ……(略)……},
            ……(略)……},
            {……(略)……}
        ]
    },
    ……(略)……,
}

 1.6.0 rc0では、1.5.0にあったTemplateクラスの機能と同等の機能が、Stringクラスのinterpolate()メソッドとしても利用できるようになりました。

 update()メソッドでは、受け取ったJSON内の動画配列それぞれに対して、テンプレートを使って実際に表示されるHTMLを生成し、最終的にそれらでsearch_resultsの内容を更新しています。

 show()メソッドでは、SWFObjectを使って受け取ったvideo要素からswfファイル(YouTubeで主に使われているFlash動画の実行ファイル)を<div id='player'>の中に埋め込んだ後、LightWindowの「Inline Content」方式で、その内容を描画させています(参考)。

デザインパターン・ライブラリ・MVCは便利!

 再度、今回使用したAjaxデザインパターンをまとめます。

表 今回のサンプルで使用したAjaxデザインパターン(再掲)
パターン名 説明
Live Searchパターン ユーザーが検索条件を入力している間も随時検索結果を表示
Submission Throttlingパターン イベントが発生するたびにサーバに情報を送信するのではなく、一定の間隔を置いて送信することでサーバの負荷や回線の負荷を軽減
Popupパターン 既存のコンテンツに一時的に前面にレイヤーを重ねて、レイアウトを変更せずに追加情報などを表示したり、ちょっとした作業領域を提供できる

 これ以外に、前回紹介した、「On-Demand Javascriptパターン」「Periodic Refreshパターン」「Page Rearrengementパターン」も使用されています。

 パターンを組み合わせていけば、今回のようなサンプルアプリもかみ砕いて理解できますし、外部APIやライブラリをフル活用すればだいぶ短く書くことができると感じていただけたでしょうか?

 また、MVCに役割を分担すれば可読性を保ちながら、どんどん機能拡張ができることを、イメージしていただけたら幸いです。

 次回も、また新しいAjaxデザインパターンやAjaxライブラリを使い楽しいサンプルをご紹介できればと思っています。

 今回のソースはこちらからダウンロードできますこちらのアプリケーションは2007年10月に、当時のYou TubeのWeb APIを使って作成したものです。その後、You Tube側の仕様の変更などによりアプリケーションが動作しなくなる場合もありますが、あらかじめご了承ください。また、サンプルのライセンスはGPL 2となります

参考文献 

@IT関連記事


古くて新しいAjaxの真実を見極める
「Webインターフェイスの新しい手法」「画期的なWebアプリケーションの仕組み」であるとして開発者たちの人気を集めるAjaxとは何なのか、その真実を見極めてみよう
Web Client & Report」フ ォーラム 2005/8/2

Ajax解体新書

よりAjaxを深く理解するために、ブラウザ上の「見た目」だけに注目するのではなく、実際に目に見えない舞台裏の通信内容をモニタリングしてみよう

最終更新 2006/11/22

Ajax うきうき Watch

Ajaxという流行技術の定義を明確にしながら、Ajaxの動向からうきうきするような面白いもの、確実に押さえておきたいものを厳選してお届けしていく

最終更新 2008/5/26

JavaScriptプログラミング再入門

 Ajax全盛のいま、オブジェクト指向ベースのJavaScript知識は不可欠。過去を振り返りつつ、まずは最新開発事情をチェック

最終更新 2007/9/25

プロフィール:志田 裕樹(しだ ゆうき)

株式会社アークウェブ取締役。Webシステムのシステムエンジニアとして開発に従事している。
Ajax、Ruby on Rails等を使用したWeb 2.0的システムの開発実績を持つ。
オープンソースのECサイト用CMS、Zen Cartの日本語コミュニティでコミッターとして活動している。

1-2-3

 INDEX
パターンとライブラリで作るAjaxおいしいレシピ(2)
prototype.jsでYouTubeをインクリメンタルサーチ
  Page1
今回のサンプルはYouTubeの新APIを使う
サンプルで体験! インクリメンタルサーチとは?
今回のサンプルで使う3つのAjaxデザインパターン
MVCそれぞれの役割を確認
  Page2
7つのJavaScriptファイルを呼び出すHTML
コントローラー:prototype.js 1.6.0 rc0の新機能を使用
Page3
モデル:前回のキーワードと異なればJSONPで検索
ビュー:prototype.js 1.6.0 rc0のテンプレート機能拡張
デザインパターン・ライブラリ・MVCは便利!


リッチクライアント&帳票 全記事一覧へ

TechTargetジャパン

リッチクライアント & 帳票 フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH