こんにちは。笹山です。
前回Ext.grid.GridPanelを用いてシンプルな時刻表を作成しました。
まだまだ物足りないので機能を追加していきます。
せっかくなのでExtJS3.0の新機能を用いてもっとリッチにしていこうと思います。
(前回のGridは実際のところExtJS3.0でなくても作成できます。)
今回は以下の機能追加を行います。
- ページング機能を追加する
- Gridの高さを自由に変更可能にする
- Gridの各Cellにマウスを合わせた時、内容をツールチップに表示する
※今回は全便の時刻表データを使ってサンプルを作成します(8月時刻表全便データ)
新機能ライブラリの追加
ExtJS3.0のサンプルサイトで紹介されている新機能を使用するには、新機能用のライブラリが必要です。
新機能用のライブラリは、ExtJS3.0を展開したexmaple\uxフォルダ以下にあります。(新機能なのに何でexampleフォルダなんだろう?)
必要なファイルは以下になります。
- ext-3.0.0\examples\ux\ux-all.js
- ext-3.0.0\examples\ux\css\ux-all.css
- ext-3.0.0\examples\ux\images以下のファイル全て
前回作成したサンプルをもとに変更を加えていきます。
- grid-timetable.htmlのHEADタグ内に「新機能に必要なファイル」と「全便の時刻表データファイル」を追加します
※override-paging-memory-proxy.jsについては新規作成します1 2 3 4
<link rel="stylesheet" type="text/css" href="path/ux-all.css" /> <script type="text/javascript" src="path/ux-all.js"></script> <script type="text/javascript" src="path/timetable-data.js"></script> <script type="text/javascript" src="path/override-paging-memory-proxy.js"></script>
※linkタグ、scriptタグ中の「path」 : ファイルを配置したディレクトリ名に変更してください
- grid-timetable.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="path/ext-all.css" />
<link rel="stylesheet" type="text/css" href="path/ux-all.css" />
<script type="text/javascript" src="path/ext-base.js"></script>
<script type="text/javascript" src="path/ext-all.js"></script>
<script type="text/javascript" src="path/ux-all.js"></script>
<script type="text/javascript" src="path/ext-lang-ja.js" charset="UTF-8"></script>
<script type="text/javascript" src="path/timetable-data.js"></script>
<script type="text/javascript" src="path/override-paging-memory-proxy.js"></script>
<script type="text/javascript" src="path/grid-timetable.js"></script>
<title>伊丹空港 8月時刻表</title>
</head>
<body>
<h1>伊丹空港 8月時刻表</h1>
<div id="grid-timetable"></div>
</body>
</html> |
Ext.ux.data.PagingMemoryProxyのメソッドオーバーライド
Ext.ux.data.PagingMemoryProxyを利用したサンプルを作成している際に以下のバグを発見しました。
- Gridのカラムソートの昇順、降順が逆に処理される
- Gridのカラムソートの降順が正常に動作しない(最後のデータから表示しているだけ)
これを修正するためにExt.ux.data.PagingMemoryProxyのdoRequest メソッドのオーバーライドを行います。
エディタで新しいファイルoverride-paging-memory-proxy.jsを作成します。
- override-paging-memory-proxy.js(新規作成)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | Ext.override(Ext.ux.data.PagingMemoryProxy,{ doRequest: function(action, rs, params, reader, callback, scope, options){ params = params || {}; var result; try { result = reader.readRecords(this.data); } catch (e) { this.fireEvent('loadexception', this, options, null, e); callback.call(scope, null, options, false); return; } // filtering if (params.filter !== undefined) { result.records = result.records.filter(function(el){ if (typeof(el) == 'object') { var att = params.filterCol || 0; return String(el.data[att]).match(params.filter) ? true : false; } else { return String(el).match(params.filter) ? true : false; } }); result.totalRecords = result.records.length; } // sorting if (params.sort !== undefined) { // use integer as params.sort to specify column, since arrays are not named // params.sort=0; would also match a array without columns var dir = String(params.dir).toUpperCase() == 'DESC' ? -1 : 1; var fn = function(r1, r2){ return r1 == r2 ? 0 : r1 < r2 ? -1 : 1; /* ↑↑↑↑↑↑↑↑↑↑↑↑ ※ux-all.jsでは、 return r1 < r2; になっています */ }; result.records.sort(function(a, b){ var v = 0; if (typeof(a) == 'object') { v = fn(a.data[params.sort], b.data[params.sort]) * dir; } else { v = fn(a, b) * dir; } if (v == 0) { v = (a.index < b.index ? -1 : 1); } return v; }); } // paging (use undefined cause start can also be 0 (thus false)) if (params.start !== undefined && params.limit !== undefined) { result.records = result.records.slice(params.start, params.start + params.limit); } callback.call(scope, result, options, true); } }); |
| Methods | 説明 |
|---|---|
| override |
既存クラスのメソッドをオーバーライドします メソッドが存在しない場合は追加されます |
作成したoverride-paging-memory-proxy.jsをgrid-timetable.htmlに追加してください。
ページング機能を追加する
前回はExt.data.ArrayStoreを使用して配列をそのままStoreに渡していましたが、今回はExt.data.Storeのproxyを使用してデータを取得します。
Storeはproxyを使用して外部データを取得します。proxyにはJSON形式でデータを取得するHttpProxyやメモリ内のデータを取得するためのExt.data.MemoryProxyがあります。
今回使用するExt.ux.data.PagingMemoryProxyはExt.data.MemoryProxyが拡張されたものでメモリ内のデータのページングやソートを行うことができます。
それでは、前回のgrid-timetable.jsにページング機能を追加してきます。
- 「全便の時刻表データファイル」を使用しますので、ソース中に直接書いていたtimeTableData配列を削除します
- (変更①) StoreをExt.data.ArrayStoreからExt.data.Storeへ変更しproxyからデータを取得するようにします
- (変更②) Ext.grid.GridPanelのBottomToolbarにExt.PagingToolbarを作成します
- (変更③) Storeへロードを行う際に、HTTPパラメータを指定してデータをロードします
- grid-timetable.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | Ext.onReady(function(){ var store = new Ext.data.Store({ /* 変更① ここから */ proxy: new Ext.ux.data.PagingMemoryProxy(timeTableData), remoteSort: true, baseParams: {sort: 'itamiTime', dir: 'ASC'}, reader: new Ext.data.ArrayReader({ fields: [ {name: 'destination'}, {name: 'airline'}, {name: 'flightName'}, {name: 'model'}, {name: 'itamiTime', type: 'date'}, {name: 'objectTime', type: 'date'}, {name: 'type'} ] }) /* 変更① ここまで */ }); var grid = new Ext.grid.GridPanel({ title: '時刻表', frame: true, height: 350, width: 750, renderTo: 'grid-timetable', stripeRows: true, trackMouseOver:true, store: store, columns: [ { header: '対象空港', sortable: true, dataIndex: 'destination' }, { header: '航空会社', sortable: true, dataIndex: 'airline', renderer: function(v, params){ var airlineColor = v; if (v == 'ANA') { airlineColor = '<span style="color: #003399;">' + v + '</span>'; } else if (v == 'JAL') { airlineColor = '<span style="color: #cc0000;">' + v + '</span>'; } else if (v == 'IBEX') { airlineColor = '<span style="color: #F552A8;">' + v + '</span>'; } else { var codeShare = v.split('/'); if (codeShare.length == 2) { if (codeShare[0] == 'IBEX' && codeShare[1] == 'ANA') { airlineColor = '<span style="color: #F552A8;">' + codeShare[0] + '</span>' + '/' + '<span style="color: #003399;">' + codeShare[1] + '</span>'; } else { // 何もしない } } } return airlineColor; } }, { header: '便名', sortable: true, dataIndex: 'flightName' }, { header: '機種', sortable: true, dataIndex: 'model' }, { header: '伊丹空港時間', sortable: true, dataIndex: 'itamiTime', renderer: Ext.util.Format.dateRenderer('H:i') }, { header: '対象空港時間', sortable: true, dataIndex: 'objectTime', renderer: Ext.util.Format.dateRenderer('H:i') }, { header: '出発/到着種別', sortable: true, dataIndex: 'type' } ], bbar: new Ext.PagingToolbar({ /* 変更② ここから */ pageSize: 30, store: store, displayInfo: true }) /* 変更② ここまで */ }); store.load({ /* 変更③ ここから */ params:{ start:0, limit:30, sort:'itamiTime', dir: 'ASC' } }); /* 変更③ ここまで */ }); |
- 変更① 2行目~17行目
Ext.data.Store Config Options 説明 proxy データオブジェクトへのアクセスを提供するプロキシーオブジェクトを指定します remoteSort true:並び替えをproxyに要求して処理します
false:キャッシュ中のデータ(現在Grid表示されているデータ)で並び替えを行いますbaseParams HTTP リクエスト時に常に送られるパラメータのオブジェクトです
Ext.ux.data.PagingMemoryProxyではstart,limit,sort,dir,filterのパラメータを受け取り、処理が可能です
start,limitパラメータはbaseParamsを指定しなくてもページング処理の際、自動で設定されますパラメータ 説明 sort ソートする項目名を指定します dir ソートする方向を指定します reader DataReader オブジェクトを指定します Ext.ux.data.PagingMemoryProxy Config Options 説明 - ページンググリッドが可能なMemoryProxyです(メモリ内のデータから読み込みます) Ext.data.ArrayReader Config Options 説明 fields データをどのようにマッピングするか定義します パラメータ 説明 name レコード内でfieldを参照する際に用いるnameです
ColumnModelのdataIndexプロパティによって参照されますtype 表示できる値に変換するためのデータタイプです
指定しない場合は、autoとなり変換を行いません - 変更② 89行目~93行目
Ext.grid.GridPanel Config Options 説明 bbar Gridパネル下部のツールバーです Ext.PagingToolbar Config Options 説明 pageSize 1ページ単位で表示するデータの数です store ページングツールバーがデータソースとして使用するExt.data.Storeを指定します displayInfo displayMsg(ページングステータスメッセージ)を表示します - 変更③ 96行目~103行目
Ext.grid.GridPanel Methods 説明 load 設定されたReaderを用いてProxyからレコードキャッシュをロードします Options 説明 params リモートデータソースに対してHTTPパラメータとして渡すプロパティを指定します
Ext.ux.data.PagingMemoryProxyでは以下のパラメータを受け取り、処理が可能です
start:データ開始位置
limit:1ページ当たりのデータ件数
sort:ソートする項目名
dir:ソートする方向
たったこれだけの変更でページング機能が実現できます。今回はメモリ内のデータでページング機能を行いました。proxyをExt.data.HttpProxyに変更すれば、サーバからXML、JSON形式でデータを取得してこれを実現することが可能です。
ページング機能を拡張する
ExtJS3.0の新しい機能でページングの機能を簡単に便利に、カッコ良くできます。
- (拡張①)スライドでページング可能にする
- (拡張②)プログレスバーで進捗確認、ページング可能にする
- grid-timetable.js
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | var grid = new Ext.grid.GridPanel({ // ~省略 bbar: new Ext.PagingToolbar({ pageSize: 30, store: store, displayInfo: true, plugins: [ new Ext.ux.SlidingPager(), /* 拡張① */ new Ext.ux.ProgressBarPager() /* 拡張② */ ] }) // ~省略 |
たったこれだけです。
Ext.PagingToolbarのpluginsオプションに指定するだけで簡単に実現できます。
Gridの高さを任意のサイズに変更可能にする
ここまでのGrid(時刻表)高さは固定でした。
データがサイズ内に収まらない場合は、スクロールして見る必要がありました。
そこでGrid(時刻表)の高さを任意のサイズに変更できるようにします。
- (拡張③)Grid(時刻表)の高さを任意のサイズに変更可能にする
- grid-timetable.js
19 20 21 22 23 24 25 26 27 28 | var grid = new Ext.grid.GridPanel({ // ~省略 plugins: new Ext.ux.PanelResizer({ /* 拡張③ ここから */ minHeight: 100, maxHeight: 800 }), /* 拡張③ ここまで */ // ~省略 |
| Config Options | 説明 |
|---|---|
| minHeight | 変更可能最小サイズ(pixel) |
| maxHeight | 変更可能最大サイズ(pixel) |
Ext.grid.GridPanelのpluginsオプションに指定するだけでこれも簡単に実現できます。
GridのCell内容をツールチップに表示する
今回のGrid(時刻表)では問題ないですが、文字列が長すぎてCell内に収まりきらない場合があります。
そのようなときのために、GridのCell上でマウスオーバしたときにツールチップを表示させてみます。
- (拡張④)GridのCell内容をツールチップに表示する
- grid-timetable.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Ext.onReady(function(){ Ext.QuickTips.init(); /* 拡張④ */ // ~省略 var grid = new Ext.grid.GridPanel({ // ~省略 columns: [ { header: '対象空港', sortable: true, dataIndex: 'destination', renderer: function(v, params) { /* 拡張④ ここから */ params.attr = 'ext:qtitle="対象空港"' + ' ext:qwidth="100"' + ' ext:qtip="' + v + '"'; return v; } /* 拡張④ ここから */ }, // ~省略 |
- 拡張④ 3行目
Ext.QuickTips Methods 説明 init 全体のQuickTipsのインタフェースを初期化し、QuckTipsを使用可能にします。 - 拡張④ 16行目~20行目
Ext.grid.GridPanel Config Options 説明 renderer セルの与えられたデータ値にHTMLマークアップを生成するために使用される関数です rendererに使用する無名関数function(v, params)で以下のHTML属性を追加することでツールチップ表示が可能になります。
属性 説明 ext:qtitle ツールチップのタイトルです ext:qwidth ツールチップの幅(pixel)です ext:qtip ツールチップで表示する内容です ※一般的なHTMLタグに直接上記属性を指定することもできます。
これも簡単に実現できてしまいました。
一般的なHTMLタグにも属性指定して簡単にツールチップを表示できるなんて素敵です。
最後に
だいぶん時刻表がカッコ良くなってきました。
ほとんどコードを書くことなく機能が実現できて感動しました。
次回ももう少し時刻表に機能を追加していこうと思っています。
お楽しみに!
ExtJS3.0 Gridデモ 「伊丹空港 8月時刻表(全便) その2」









1月 12th, 2010 at 10:42
[...] ExtJS3.0でWebアプリケーションのテーブルをリッチにしよう(その1) ExtJS3.0でWebアプリケーションのテーブルをリッチにしよう(その2) [...]