ExtJSで楽しくRIA業務アプリ開発

株式会社sus4 開発チーム

ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む

コメントが1件あります

このエントリーを含むはてなブックマークはてなブックマーク - ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む この記事をクリップ!Livedoorクリップ - ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む Yahoo!ブックマークに登録 BuzzurlにブックマークBuzzurlにブックマーク このエントリをつぶやくこのWebページのtweets Share on Tumblr FC2ブックマークへ追加 newsing it! この記事をChoix! Googleブックマークに追加 Bookmark this on Delicious Digg This

今回もグリッドパネルです。今回はJSONPを使ってYouTube Data APIを呼び出して、グリッドに表示するサンプルコードになります。
JSONPを使うことで別ドメインのAPIをJavascriptで呼び出すことができます。Google Data APIはJSONPにも対応しているため、利用が簡単です。

JSONPでYouTube Data APIを利用

JSONPでYouTube Data APIを利用

グリッドパネル関連の過去の記事はこちらからです。

リファレンスはこちらから
ExtJS -3.0 日本語APIドキュメント – Ext.data.DataProxyクラス
http://extdocs.xenophy.com/?class=Ext.data.DataProxy

ExtJS -3.0 日本語APIドキュメント – Ext.data.ScriptTagProxyクラス
http://extdocs.xenophy.com/?class=Ext.data.ScriptTagProxy

HTML:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>ExtJS名古屋勉強会 Youtube API</title>

    <!--Ext JS CSS-->
    <link rel="stylesheet" href="../js/ext/resources/css/ext-all.css" type="text/css" />
    <!--Ext JS-->
    <script type="text/javascript" src="../js/ext/adapter/ext/ext-base.js"></script>

    <script type="text/javascript" src="../js/ext/ext-all.js"></script>
    <script type="text/javascript" src="grid-youtube.js"></script>
    <style TYPE="text/css">
    <!--
        .search {background-image: url(../img/icon/magnifier.png) !important;}
    -->
    </style>
</head>
<body>
    <div style="width:500px;margin:0 auto;padding:15px;background-color:#D3E1F1;font-size:small;">
        <p style="font-weight:bold;padding:3px;margin-bottom:10px;">
            YouTube DATA APIを利用するグリッド(JSONPとして利用する)
        </p>

        <div id="grid"></div>
        <br/>
        Java Script:<a href="grid-click.js">grid-youtube.js</a><br/>
        YouTube Data API:<a href="http://code.google.com/intl/ja/apis/youtube/overview.html" target="_blank">YouTube の API とツール - Google Code</a>
    </div>
</body>
</html>

Java Script:


Ext.onReady(function(){
    //各ページ辺りの表示数
    var perPage = 10;

    //ストアの設定
    var store = new Ext.data.JsonStore({
        //クロスドメインになるYouTube Data APIをJSONPとして利用するためScriptTagProxyを使う。
        proxy:new Ext.data.ScriptTagProxy({
            url:"http://gdata.youtube.com/feeds/api/videos",
        }),
        baseParams:{
            format:1,
            'max-results':perPage,
            'start-index':1,
            vq:'extjs',
            alt:'json-in-script'
        },
        paramNames:{
            start:'start-index',
            limit:'max-results',
        },
        autoLoad:true,
        root:'feed.entry',
        idProperty:'id.$t',
        totalProperty:"feed.openSearch$totalResults.$t",
        fields:['author','id','title','media$group','link','content','published','category','updated'],
    });

    //各レンダラーの設定
    var imgRenderer = function(value,meta,rec,rIndex,cIndex,store){
        return String.format('<div"><img src={0}>{1}</div>',
                  store.getAt(rIndex).data.media$group.media$thumbnail[0].url,
                  value.$t);
    };

    var titleRenderer = function(value,meta,rec,rIndex,cIndex,store){
        var data = store.getAt(rIndex).data;
        return String.format('<div><p><b>{0}</b></p>by {1}<p>{2}</p></div>',
            value.$t,
            data.author[0].name.$t,
            data.content.$t.length > 20 ? data.content.$t.substring(0,20) + '...' :data.content.$t

        );
    };

    var grid = new Ext.grid.GridPanel({
        renderTo:'grid',
        height:600,
        loadMask:true,
        store:store,
        autoExpandColumn:'title',
        cm:new Ext.grid.ColumnModel({
            columns:[
                {
                    id:'id', header:'ID', dataIndex:'id', hidden:true
                },
                {
                    id:'img', header:'img', dataIndex:'title', renderer:imgRenderer, width:120
                },
                {
                    id:'title', header:'title', dataIndex:'title', renderer:titleRenderer, width:120
                },

                {
                    id:'duration',
                    header:'Duration',
                    dataIndex:'media$group',
                    renderer:function(value){
                        var totalsec = value.yt$duration.seconds;
                        var min = Math.floor(totalsec / 60);
                        var sec = totalsec % 60;
                        return String.format('{0}:{1}',
                            String.leftPad(min,2,'0'),
                            String.leftPad(sec,2,'0'));
                    },
                    width:120
                }
            ]
        }),
        tbar:[
            '->',
            {
                xtype:'textfield',
                name:'keyword',
                itemId:'keyword'
            },
            {
                text:'Search',
                iconCls:'search',
                scope:this,
                handler:function(){
                    var tbar = grid.getTopToolbar();
                    var value = tbar.getComponent('keyword').getValue();

                    grid.getStore().load({
                        params:{
                            vq:value
                        }
                    });
                }
            }
        ],
        bbar:[
            //YouTube Data APIのリクエストの開始位置が1からであるため、いくつかバグが出ます。
            new Ext.PagingToolbar({
                displayInfo:true,
                pageSize:perPage,
                store:store
            })
        ],
        listeners:{
            //ダブルクリックで別ウィンドウで開く
            rowdblclick:function(grid,rIndex,e){
                var data = grid.getStore().getAt(rIndex).data;
                window.open(data.link[0].href);
            }
        }
    });
});

実行結果:

JSONPでYouTube Data APIを利用

JSONPでYouTube Data APIを利用

今回のキモはJsonStoreになります。これまでのサンプルではurlのコンフィグでAPIのURLを設定していました。しかし別ドメインのAPIを呼び出す場合はurlにコンフィグにフルパスを設定してもXMLHttpRequestオブジェクトのセキュリティ上の制約で正しく動作しません。JavascriptではJSONの代わりにJSONPを使うとことで別ドメインのAPIを利用する仕組みがあります。

JSONPとは – はてなキーワード http://d.hatena.ne.jp/keyword/JSONP

JSON with paddingの略

Javascriptの非同期通信でよく使われるXMLHttpRequestオブジェクトにはSame-Originポリシーが存在し、クロスドメインアクセスができない。

一方,scriptタグを用いると,ドメインの異なるサーバに置いているスクリプトファイルを読み込むことができる。この仕組みを利用し、scriptタグのsrcに、データを取得できるAPIのURLを指定し,ドメインの異なるサーバからデータを取得する仕組みの総称として、JSOPという言葉が使われる。JSONP用の APIでは、関数名+取得データをjson形式で表記して引数とした形式(例.callbackFunc({id:1000,name:aaa}))のレスポンスが一般的で、APIから返されるコールバック関数と同じ名前の関数 (callbackFunc(jsonData))をクライアント側で定義しておけば、データを読み込んだ際にそのコールバック関数が実行される。動的にscriptのDOMを生成することで、非同期でデータが取得できるようになる。

ただし、Same-Originポリシーが存在しないため、機密情報を APIに含める際には十分な注意が必要である。

ExtJSでJSONPを利用する場合はExt.data.ScriptTagProxyを使用してJSONPを実行します。
Ext.data.ScriptTagProxyはJsonStoreのproxyとして設定します。proxyはデータをストアに読み込む設定をカスタムで指定できます。ここにはExt.data.DataProxyクラスのオブジェクトを設定します。Ext.data.ScriptTagProxyはExt.data.DataProxyクラスのサブクラスにです。DataProxyクラスはJSONPを呼び出すための専用のクラスです。サンプルコードではurlコンフィグを指定しているだけですが、より複雑なロード方法を設定できます。
Ext.data.ScriptTagProxyで実行されたAPIはデータが実行可能な関数として取得されます。Ext.data.ScriptTagProxyはその関数を実行して、データを展開してストアに読み込んでいます。特に難しい設定をしなくても自動的に読み込んでくれるのためありがたいです。

今回のサンプルコードのJsonStoreの設定はこれまでより少しややこしくなっているのは、YouTube Data APIの仕様に合わせるためです。baseParamsの値は全て必須です。alt:’json-in-script’でJSONPで呼び出すことをAPIに伝えています。注意点としてはstart-indexが1からでないといけない点です。そのためPagingToolbarで少し不具合が起きていますが、ひとまずそのままにしておきます。また時間があれば解決方法を紹介します。
またrootでドットシンタックス(.)でrootの階層を一段深いところを指定しているのも、初めて出てきました。


	//ストアの設定
    var store = new Ext.data.JsonStore({
        //クロスドメインになるYouTube Data APIをJSONPとして利用するためScriptTagProxyを使う。
        proxy:new Ext.data.ScriptTagProxy({
            url:"http://gdata.youtube.com/feeds/api/videos",
        }),
        baseParams:{
            format:1,
            'max-results':perPage,
            'start-index':1,
            vq:'extjs',
            alt:'json-in-script'
        },
        paramNames:{
            start:'start-index',
            limit:'max-results',
        },
        autoLoad:true,
        root:'feed.entry',
        idProperty:'id.$t',
        totalProperty:"feed.openSearch$totalResults.$t",
        fields:['author','id','title','media$group','link','content','published','category','updated'],
    });

JSONPからデータを読み込んでさえしまえば、これまでのグリッドと同じです。いつものようにColumnモデル等を設定して表示を整えます。YouTube Data APIで取得されるデータは階層が深いので、レンダラーの設定は必須です。


   //各レンダラーの設定
    var imgRenderer = function(value,meta,rec,rIndex,cIndex,store){
        return String.format('<div"><img src={0}>{1}</div>',
                  store.getAt(rIndex).data.media$group.media$thumbnail[0].url,
                  value.$t);
    };

    var titleRenderer = function(value,meta,rec,rIndex,cIndex,store){
        var data = store.getAt(rIndex).data;
        return String.format('<div><p><b>{0}</b></p>by {1}<p>{2}</p></div>',
            value.$t,
            data.author[0].name.$t,
            data.content.$t.length > 20 ? data.content.$t.substring(0,20) + '...' :data.content.$t

        );
    };

		・・・

		cm:new Ext.grid.ColumnModel({
            columns:[
                {
                    id:'id', header:'ID', dataIndex:'id', hidden:true
                },
                {
                    id:'img', header:'img', dataIndex:'title', renderer:imgRenderer, width:120
                },
                {
                    id:'title', header:'title', dataIndex:'title', renderer:titleRenderer, width:120
                },

                {
                    id:'duration',
                    header:'Duration',
                    dataIndex:'media$group',
                    renderer:function(value){
                        var totalsec = value.yt$duration.seconds;
                        var min = Math.floor(totalsec / 60);
                        var sec = totalsec % 60;
                        return String.format('{0}:{1}',
                            String.leftPad(min,2,'0'),
                            String.leftPad(sec,2,'0'));
                    },
                    width:120
                }
            ]
        }),

		・・・

あとは必要におおじてtbarとbbarを設定します。この二つはこれまでにも出てきているので解説を省きます。

これでYouTubeのAPIを利用できるようになります。JSONPの使い方を覚えておけば、そのほかのAPIでJSONPに対応しているものがあれば、簡単に利用してマッシュアップが作れてしまいます。APIの仕様は変更されることもあるので、注意が必要です。今回は2010/5/6の時点のYouTube Data APIを利用しています。

  • Share/Bookmark


佐竹 裕行

1982年生まれ。滋賀→はこだて→名古屋→大垣→名古屋。
2006年名古屋学芸大学映像メディア学科卒、その後IAMAS卒(Studio2、6期生)。2009年にsus4に入社。学生時代はMax/MSP JitterやGainerばっかり使っていたが、現在社内では主にExtとモバイル開発、動画サービスのバックエンドを担当。知る人ぞ知るアノ鍵の人。

One Response to 'ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む'

Subscribe to comments with RSS or TrackBack to 'ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む'.

  1. [...] ExJS入門30 Twitter Seach APIを使ったグリッドパネル 5 月 7th, 2010 @ 11:48 am › 佐竹 裕行 ↓ Leave a comment 前回はJSONPを使ってYouTubeの情報をグリッドに表示するサンプルを紹介しました。今回も外部APIの利用第2弾ということにして、Twitter APIを使ってTwitterのアップデートをグリッドに読み込んでみます。 Twitter Search APIを利用したグリッド 今回はJSONPを使ったAPIの利用に加えて、グリッドを自動更新するためのExt.TaskMgrクラスを使ったサンプルコードの紹介になります。 前回のチュートリアルがお済でない方はこちらからどうぞ ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む [...]

コメントを残す

Get Adobe Flash playerPlugin by wpburn.com wordpress themes