業務アプリデモ開発をベースにhifiveを学ぼう(3)「ツリービューの実装」
前回に引き続いて今回はツリービューを実装します。動作は次のようになります。
要件としては
- ツリービューの初期表示
- ツリービューの折りたたみ、伸張
となります。
JS Treeビューの導入
ツリービューの表示自体はjsTreeというライブラリを使います。
このライブラリをlib/jstree以下に配置し、index.htmlにて読み込みます。
<!– jstree –> | |
<link rel="stylesheet" href="lib/jstree/themes/default/style.css" /> | |
<script type="text/javascript" src="lib/jstree/jstree.js"></script> |
js/AppPurchaseManagerController.jsの修正
次に js/AppPurchaseManagerController.js に対してツリービューを読み込むように設定をします。
var controller = { | |
: | |
_treeViewController: sample.TreeViewController, |
さらにAjaxや計算処理を行うためのロジックを追加します。
var controller = { | |
: | |
_appLogic: sample.AppPurchaseManagerLogic, |
そして、コントローラーが使える状態になったタイミングのイベント、__readyにてツリービューコントローラーを呼び出します。
__ready: function() { | |
// ツリービュー(エクスプローラ)にデータを設定 | |
this._treeViewController.setTreeData(this._appLogic.getShortcutTree()); | |
}, |
これでコントローラの修正は完了です。
AppPurchaseManagerLogicの処理
次にAppPurchaseManagerLogicについて記述していきます。ファイルは js/AppPurchaseManagerLogic.js になります。処理内容は次のようになります。Ajaxでデータを取得するだけです。
(function() { | |
var controller = { | |
__name: 'sample.AppPurchaseManagerLogic', | |
getShortcutTree: function() { | |
return sample.util.ajax(sample.consts.url.FILE_TREE); | |
} | |
}; | |
h5.core.expose(controller); | |
})(); |
sample.consts.url.FILE_TREE は sample.util 内で定義される変数です。
AppPurchaseManagerLogicを読み込むように index.html を修正しておきます。
<script src="js/AppPurchaseManagerLogic.js" /></script> |
util.jsの修正
ここではAjaxをダミーで実行するメソッドを実装します。本番環境では実際にサーバから取得するようにすれば良いでしょう。このようにデータ取得部分を隠蔽することで簡単にデモ環境と本番環境との切り替えができるようになります。
h5.u.obj.expose('sample.util', { | |
: | |
ajax: function(url, data) { | |
// ダミーデータを返す | |
var ret = null; | |
url = url.url || url; | |
switch (url) { | |
case sample.consts.url.FILE_TREE: | |
ret = treeDatas || createTreeDatas(); | |
ret = ret.slice(0); | |
break; | |
} | |
var dfd = h5.async.deferred(); | |
setTimeout(function() { | |
dfd.resolve(ret); | |
}, 0); | |
return dfd.promise(); | |
} |
ダミーデータは一覧などでも使うのでswitch文を使って取り分けられるようにしています。今回は createTreeDatas()
にてデータを生成します。
続けて createTreeDatas()
を実装します。 applicants
と statuses
は他の処理でも使うので関数の外に出しています。
var applicants = ['satoshi', 'takeshi', 'kasumi', 'haruka']; | |
var statuses = ['new', 'investigation', 'approved', 'closed', 'rejected']; | |
function createTreeDatas() { | |
treeDatas = [{ | |
id: 'all', | |
parent: '#', | |
icon: 'jstree-file', | |
text: '全て' | |
}, { | |
id: 'applicant', | |
parent: '#', | |
text: '申請者別', | |
state: { | |
opened: true | |
} | |
}, { | |
id: 'status', | |
parent: '#', | |
text: 'ステータス別', | |
state: { | |
opened: true | |
} | |
}, { | |
id: '10000*100', | |
parent: '#', | |
text: '10000×100', | |
icon: 'jstree-file' | |
}, { | |
id: '10000*10000', | |
parent: '#', | |
text: '10000×10000', | |
icon: 'jstree-file' | |
}]; | |
// 申請者別 | |
for (var i = 0, l = applicants.length; i < l; i++) { | |
var applicant = applicants[i]; | |
treeDatas.push({ | |
id: 'applicant.' + applicant, | |
parent: 'applicant', | |
icon: 'jstree-file', | |
text: applicant | |
}); | |
} | |
// ステータス別 | |
for (var i = 0, l = statuses.length; i < l; i++) { | |
var status = statuses[i]; | |
var text = sample.util.statusTextMap[status]; | |
treeDatas.push({ | |
id: 'status.' + status, | |
parent: 'status', | |
icon: 'jstree-file', | |
text: text | |
}); | |
} | |
return treeDatas; | |
} |
treeDatasというツリービューの元データを作成して返しています。この中で sample.util.statusTextMap という変数を使っていますので、これは sample.utilsの中で定義しておきます。
h5.u.obj.expose('sample.util', { | |
statusTextMap: { | |
'new': '新規', | |
investigation: '検討中', | |
approved: '承認済', | |
closed: '完了', | |
rejected: '棄却' | |
}, | |
: |
最後に定数用のオブジェクトを定義します。
h5.u.obj.expose('sample.consts', { | |
url: { | |
FILE_TREE: 'filetree' | |
} | |
}); |
これでutil.jsの修正は完了です。
js/TreeViewController.jsの追加
最後に js/TreeViewController.js
を追加します。ここで生成されたツリービューのデータを表示します。
まず構造は次のようになります。
var controller = { | |
__name: 'sample.TreeViewController', | |
_$tree: null, // ツリービューのDOM | |
_currentSelected: null, // 選択しているデータについて | |
__init: function() { | |
// 初期設定 | |
}, | |
setTreeData: function(dataOrPromise, opt) { | |
// ツリービューにデータをセット | |
}, | |
h5.core.expose(controller); | |
})(jQuery); |
まず初期設定を行います。
__init: function() { | |
sample.util.createDefaultControllerView(this); | |
this._$tree = this.$find('.jstree'); | |
}, |
ここで sample.util.createDefaultControllerView(this);
とすることで表示処理の下準備(バインド)を行っています。
そして setTreeData を実装します。これはデータを受け取って描画を行う処理になります。
setTreeData: function(dataOrPromise, opt) { | |
if (h5.async.isPromise(dataOrPromise)) { | |
var indicator = this.indicator().show(); | |
dataOrPromise.done(this.own(function(treeData) { | |
this._setTreeData(treeData, opt); | |
indicator.hide(); | |
})); | |
} else { | |
this._setTreeData(dataOrPromise, opt); | |
} | |
}, |
ここで注意するのはAjaxのような非同期処理とそうでない場合を想定しておくということです。その判定として、hifiveでは h5.async.isPromise というメソッドを提供しています。これを使うことで Promiseであればdoneメソッドを受けてから表示処理を行うといった判定ができます。また、Promiseの場合は var indicator = this.indicator().show();
を使ってインジケータ表示を行っています。これは標準で用意しているメソッドになります。
_setTreeData
については以下のようになります。JSTreeを呼び出してデータを設定しているだけです。this.$treeには元々jQueryが入っています。
_setTreeData: function(treeData, opt) { | |
// TODO 各オプションは設定可能 | |
opt = opt || {}; | |
this._$tree.jstree({ | |
core: { | |
animation: opt.animation || 0, | |
multiple: opt.multiple || false, | |
data: treeData | |
}, | |
themes: opt.themes || { | |
stripes: true | |
} | |
}); | |
} |
なお、このファイルもindex.htmlから読み込まれるように指定します。
<script src="js/TreeViewController.js"></script> |
これで準備完了です。実行すると、ツリービューが表示されるかと思います。
今回はデモなのでデータを手動で用意していますが、実際にはAjaxを使ってサーバから取得することになるかと思います。しかし、その場合もutil.jsさえ切り替えれば良いだけです。
このようにAjaxによるデータ取得部分をコントローラによる処理と切り離しておくことでメンテナンス性をあげることができます。さらに同期、非同期処理の両方に対応しておくことでコードも見やすくなるはずです。
今回のコードはGitHubで見られるようになっています。また、動作しているデモはこちらになります。
次回はデータの一覧表示部分について見ていきます。
コメントは受け付けていません。