ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む
今回もグリッドパネルです。今回はJSONPを使ってYouTube Data APIを呼び出して、グリッドに表示するサンプルコードになります。
JSONPを使うことで別ドメインのAPIをJavascriptで呼び出すことができます。Google Data APIはJSONPにも対応しているため、利用が簡単です。
グリッドパネル関連の過去の記事はこちらからです。
- ExtJSで楽しくRIA業務アプリ開発 ExJS入門17 グリッド・パネル 基本編
- ExtJSで楽しくRIA業務アプリ開発 ExtJS入門18 グリッド レンダラーを使ってデザインを変える
- ExtJS入門19 グリッドにページング機能を追加する
- ExtJS入門20 グリッドにフィルタリング機能を追加する
- ExJS入門21 グリッド・セレクション・モデル
- ExJS入門22 グリッドのイベント処理(ダブルクリック、右クリック)
- ExtJS入門23 グリッドへの項目の追加と削除
- ExtJS入門24 エディタブル・グリッドの基本(グリッドパネルをエディタブル・グリッドに変更)
- ExJS入門25 エディタブル・グリッド(Ext.Ajaxを使った編集内容の保存)
- ExJS入門27 もう一つのエディタブル・グリッド ux.RowEditorプラグイン
- ExJS入門28 チェックボックス付きグリッドパネル
リファレンスはこちらから
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);
}
}
});
});
実行結果:
今回のキモは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を利用しています。




[...] 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をグリッドパネルに読み込む [...]
ExJS入門30 Twitter Seach APIを使ったグリッドパネル | ExtJSで楽しくRIA業務アプリ開発
7 5 月 10 at 11:48 AM