より大型なWebアプリケーションを開発する上でテンプレートエンジンの利用は欠かせません。テンプレートエンジンはビューとロジックを分離し、メンテナンス性の高いシステムを実現してくれるでしょう。
そこで今回は主なJavaScript(Webブラウザ)向けのテンプレートエンジンを紹介します。
Handlebars.js: Minimal Templating on Steroids

ロジックは殆どなく、if文と繰り返し文くらいしかありません。テンプレートの仕組みとしてはパーシャルにも対応しています。ロジックがない分、ビューを適用する前のJavaScript側できちんとデータを整形した上で渡す必要があります。
{{ mustache }}

mustacheもまたロジックの少ないテンプレートですが、JavaScript以外の言語にも対応しているのがポイントです。ロジックが複雑になるとJavaScriptでしか使えなくなりますが、シンプルである分幅広い言語(Ruby/Python/Erlang/PHP/Perl/Java/Objective-C/Swift/Dartなど)をサポートしています。
Underscore.js

Underscore.jsはJavaScriptに便利なロジックを追加してくれるライブラリですが、その一つにテンプレート機能があります。機能は多くありませんが、Underscore.jsが持つ機能でサポートできるでしょう。
JsRender/JsViews

有名なjQuery Template(現在は開発終了)の作者が開発しているテンプレートエンジンです。とは言えjQueryには非依存です。自分でカスタムタグを作ることができるので、ビューとロジックが分離しやすくなっています。
Hogan.js

Twitterの開発しているテンプレートエンジンで、テンプレートをコンパイルするのが一つの特徴となっています。これによってテンプレートがJavaScriptに変換され、実際に描画が高速になります。
EJS – JavaScript Templates

EJSはhifiveでも使っているテンプレートエンジンです。RubyのERBにインスパイアされているので、構文もよく似ています。Railsライクなヘルパー機能、テンプレートキャッシュ、パーシャルなど多機能なエンジンです。
A JavaScript library for building user interfaces | React

Reactは厳密にはテンプレートではありませんが、ビューを作る上で最近注目されています。特徴はVirtualDOMを使い、DOMの状態を意識することなく使えることでしょう。JSXと呼ばれるテンプレートフォーマットになり、この記述に好き嫌いが分かれるようです。
pure.js – Javascript Template Engine

HTMLの中に値を埋め込んでいくようにビューを作成するテンプレートエンジンです。機能は殆どありませんが、シンプルなので習得は容易そうです。
Dust.js by LinkedIn

LinkedIn社が開発しているテンプレートエンジンです。コンパイル機能、ヘルパー、フィルター、パーシャル、ブロックといった機能があります。@や#など独自のタグ機構が備わっています。
Nunjucks

Mozillaの開発するテンプレートエンジンです。jinja2にインスパイアされて開発しています。軽量で高速、機能拡張サポート、フィルターなどの機能があります。実際、Mozillaプロジェクトの多くで実用されています。
いかがでしょうか。テンプレートエンジンを使いこなせばWebアプリケーションの作業分離がしやすくなり、開発が効率化します。JavaScriptではサーバサイドのものと異なり、多機能さよりも軽量さやシンプルさが求められるようです。ロジック側でのサポートが欠かせないと言えるでしょう。
今回は引き続き業務アプリのデモを通じてhifiveの機能を紹介します。今回は親子連携についてです。
親子連携はいわゆる Master – Detailと呼ばれるもので、親で選んだ内容を子に伝えることで描画を更新したり、処理を行うというものになります。
今回のデモでは2つの親子連携が行われています。
ツリービューでの選択
ツリービューで項目を選択すると、右側のグリッドが更新されます。この処理は js/AppPurchaseManagerController.js に記載されています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| '.shortcut selected': function(ctx) { | |
| : | |
| this._gridViewerController.setData(this._appLogic.searchPurchaseDatas(query)); | |
| } |
queryというのは絞り込み条件になります。それを使って js/AppPurchaseManagerLogic.js の searchPurchaseDatas を呼び出します。実際にはutil.ajaxを使っています。結果はグリッドで描画するデータの配列になります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| searchPurchaseDatas: function(query) { | |
| return sample.util.ajax(sample.consts.url.SEARCH_WORKFLOW, query); | |
| }, |
GridViewerController.js の setData ではデータを受け取った後、描画処理を行います。ここで注意したいのは、データがPromiseオブジェクトの場合があるということです。その場合、Promiseであるかどうかを判定し( if (h5.async.isPromise(data)) { )その結果を使って再度自分自身をコールしています。これによって非同期処理でも同期のように扱えるようになります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| setData: function(data, dummyColNums) { | |
| if (h5.async.isPromise(data)) { | |
| var indicator = this.indicator(); | |
| indicator.show(); | |
| data.done(this.own(function(d) { | |
| this.setData(d, dummyColNums); | |
| indicator.hide(); | |
| })); | |
| return; | |
| } | |
| this._gridWrapperController.setData(data, dummyColNums); | |
| this.$find('.dataLength').text(data.length); | |
| }, |
実際には js/grid/GridWrapperController.js の setData に処理を委譲しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| setData: function(data, dummyColNums) { | |
| this._gridController.setData(data, dummyColNums); | |
| }, |
さらに処理を js/grid/DatagridController.js に処理を渡しています。ここで実際の表示処理を行っています。画面を部品ごとに分割したり、ラッパーを挟むことで機能を分割できるようになり、メンテナンス性が維持されます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| setData: function(data, dummyColNums) { | |
| : | |
| var dataSource = datagrid.createDataSource({ | |
| idProperty: 'id', | |
| type: 'local', | |
| param: data | |
| }); | |
| // paramを再生成する | |
| this._createDefaultParam(dummyColNums); | |
| // FIXME (0,0)にグリッドをスクロール | |
| this._gridController._viewController._vPos = 0; | |
| this._gridController._viewController._hPos = 0; | |
| this._gridController.activate(dataSource, this._param); | |
| this._gridController.search(); | |
| this._triggerLengthChange(); | |
| }, |
グリッドで選択
グリッドで行を選択した後のイベントは次のように処理されます。まず行を選択した時点で gridChangeDataSelect イベントが呼ばれます。処理を行うのは js/grid/DatagridController.js です。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| '{rootElement} gridChangeDataSelect': function() { | |
| var ids = this._gridController.getSelectedDataIdAll() | |
| this.trigger('showDetail', ids); | |
| }, |
ここでは選択されているIDを集めて、showDetailイベントを発火しています。このイベントは js/AppPurchaseManagerController.js によって監視されています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| '.gridViewer showDetail': function(ctx) { | |
| var id = ctx.evArg; | |
| if (!id) { | |
| return; | |
| } | |
| var isMass = ($.isArray(id) ? id[0] : id).indexOf('_') === '0'; | |
| var data = this._appLogic.getPurchaseById(id); | |
| this._detailController.setData(data, isMass); | |
| }, |
そして js/DetailController.js のsetDataが呼ばれます。ここではデータを作成し、 view.updateを使って描画処理を行います。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| setData: function(data) { | |
| : | |
| var dataAry = $.isArray(data) ? data : [data]; | |
| var details = []; | |
| for (var i = 0, l = dataAry.length; i < l; i++) { | |
| var d = dataAry[i]; | |
| details.push({ | |
| id: d.id, | |
| : | |
| applicationDate: d.applicationDate | |
| }); | |
| } | |
| this.view.update('{rootElement}', 'purchaseDetail', { | |
| details: details | |
| }); | |
| this.refresh(); | |
| }, |
その他の処理
その他、画面上でボタンを押した際の処理などがありますが、いずれも実際の処理は行わずにイベントを発火しています。例えば以下は承認済みにする処理です。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| '.confirm click': function(ctx, $el) { | |
| var ids = '' + $el.data('confirm-targets'); | |
| ids = ids.split(','); | |
| if (!ids.length) { | |
| return; | |
| } | |
| if (!confirm(ids.length + '件のデータを"承認済"にします。よろしいですか?')) { | |
| return; | |
| } | |
| this.trigger('confirmPurchase', { | |
| ids: ids | |
| }); | |
| }, |
confirmPurchaseというイベントは js/AppPurchaseManagerController.js にて購読しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| '{rootElement} confirmPurchase': function(ctx) { | |
| var ids = ctx.evArg.ids; | |
| var promise = this._appLogic.confirmByIds(ids); | |
| this.indicator({ | |
| promises: promise | |
| }).show(); | |
| promise.done(this.own(function(datas) { | |
| this._detailController.confirmExecuted(datas); | |
| this._gridViewerController.refresh(); | |
| alert(datas.length + '件の申請を承認しました'); | |
| })); | |
| }, |
このように hifive では購読とイベントを使ってデータの伝搬と描画を行っています。その結果としてHTMLとデータ操作を分離し、メンテナンスやテストしやすいシステム構築が可能になります。
今回のコードはGitHubにアップロード されています。また、デモはこちらにて試せます。
hifiveではこのような構築法が容易になるように設計されています。ぜひお試しください。
IDEというと機能が多い分、ダウンロードサイズが大きかったり、動作がもっさりしているものが多いのではないでしょうか。そこで最近ではWebブラウザ上で動くIDEが増えています。今回はその代表例を紹介します。
Cloud9 – Your development environment, in the cloud

40以上の言語をサポートしたWeb IDEです。Dockerコンテナになっており、aptを使って自由にパッケージをインストールできるようになっています。Rails/Django、WordPressなど各種システムも利用できます。
Codeanywhere · Cross Platform Cloud IDE

バージョン管理、ターミナルを備えています。書いたコードはFTP/SFPT、Dropbox、Google Driveなどに保存ができます。コラボレーション機能もあるので、企業でも利用ができるでしょう。
Codenvy | On-Demand Developer Workspaces

インタフェースとしてはEclipseに近いものとなっています。クラウドでの利用の他、ローカルでインストールして使うこともできます。
Koding for Teams | Configure any development environment in one click

リアルタイムコラボレーション機能が備わったクラウドIDEです。書いたコードはHeroku、Dockerをはじめとして各種クラウドへデプロイできます。
ShiftEdit – Online IDE | ShiftEdit

ターミナル、プレビュー、バージョン管理と差分表示、テーマのカスタマイズといった機能が備わっています。チャット機能もあるので、メンバーと対話しながら開発が進められます。
Orion – Open Source Web and Cloud Development Environment

Ecpliseが開発しているWeb IDEです。機能的にはまだEclipseには及びませんが、着実にバージョンアップしています。Gitインタフェースが備わっています。
Ceylon Web IDE

本格的な開発ができると言う訳ではありませんが、Web IDEです。Web上でコードを書いて実行もできます。書いたコードはGistに保存ができます。
HTML5アプリをWeb上で開発するというのは、プレビューの確認がしやすいという利点があります。さらに企業であれば個々のPCにインストールする必要がなくなったり、コードの管理をクラウド上で行えるので各PCにデータを残さなくて済むようになります。
HTML5によって、Web IDEはここ数年で一気に実用性が増してきたように感じます。ぜひ触れてみてください。
前回に引き続き業務アプリのデモを開発していきます。今回はちょっと趣向を変えてグリッドビューを紹介します。
すでに実装済みなグリッドビューが以下になります。

優先度、申請月を使ってデータのフィルタリングができます。

ヘッダーと左側の2カラムはスクロールしても表示は固定されています。

そして業務アプリとしてよくありがちなソートであったり、カラムのドラッグ&ドロップによる移動も可能です。

かなり多くの機能が実装されているのでコードについての詳細は省きますが、GitHubにて確認できます。対象は、
- lib/hifive/ui/datagrid.css
- lib/hifive/ui/datagrid.js
- js/GridViewerController.js
- js/grid/DatagridController.js
- js/grid/GridWrapperController.js
になります。
データの表示については js/AppPurchaseManagerController.js の __readyにて実装しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| this._gridViewerController.setData(this._appLogic.searchPurchaseDatas()); |
ロジック(js/AppPurchaseManagerLogic.js)の searchPurchaseDatasから取得したデータを使って、グリッドビューコントローラにデータをセットしています。この処理では以下のようにgridWrapperController(js/grid/GridWrapperController.js)へ処理を送っています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| setData: function(data, dummyColNums) { | |
| : | |
| this._gridWrapperController.setData(data, dummyColNums); | |
| this.$find('.dataLength').text(data.length); | |
| }, |
js/grid/DatagridController.jsがデータグリッドとしての機能を実装しています。データの表示、カラムの移動や固定、ソート、フィルタリングなどデータグリッドとして必要な機能がこの中で実現しています。
hifiveのUIライブラリであるグリッドビューを使うことで、業務システムにありがちな要件を備えたグリッドが実装できるようになります。
今回のコードはGitHubで見られるようになっています。また、動いているサンプルはこちらで確認できます。ぜひご覧ください。
前回に引き続いて今回はツリービューを実装します。動作は次のようになります。

要件としては
- ツリービューの初期表示
- ツリービューの折りたたみ、伸張
となります。
JS Treeビューの導入
ツリービューの表示自体はjsTreeというライブラリを使います。
このライブラリをlib/jstree以下に配置し、index.htmlにて読み込みます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!– 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 に対してツリービューを読み込むように設定をします。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var controller = { | |
| : | |
| _treeViewController: sample.TreeViewController, |
さらにAjaxや計算処理を行うためのロジックを追加します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var controller = { | |
| : | |
| _appLogic: sample.AppPurchaseManagerLogic, |
そして、コントローラーが使える状態になったタイミングのイベント、__readyにてツリービューコントローラーを呼び出します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| __ready: function() { | |
| // ツリービュー(エクスプローラ)にデータを設定 | |
| this._treeViewController.setTreeData(this._appLogic.getShortcutTree()); | |
| }, |
これでコントローラの修正は完了です。
AppPurchaseManagerLogicの処理
次にAppPurchaseManagerLogicについて記述していきます。ファイルは js/AppPurchaseManagerLogic.js になります。処理内容は次のようになります。Ajaxでデータを取得するだけです。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (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 を修正しておきます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script src="js/AppPurchaseManagerLogic.js" /></script> |
util.jsの修正
ここではAjaxをダミーで実行するメソッドを実装します。本番環境では実際にサーバから取得するようにすれば良いでしょう。このようにデータ取得部分を隠蔽することで簡単にデモ環境と本番環境との切り替えができるようになります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 は他の処理でも使うので関数の外に出しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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の中で定義しておきます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| h5.u.obj.expose('sample.util', { | |
| statusTextMap: { | |
| 'new': '新規', | |
| investigation: '検討中', | |
| approved: '承認済', | |
| closed: '完了', | |
| rejected: '棄却' | |
| }, | |
| : |
最後に定数用のオブジェクトを定義します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| h5.u.obj.expose('sample.consts', { | |
| url: { | |
| FILE_TREE: 'filetree' | |
| } | |
| }); |
これでutil.jsの修正は完了です。
js/TreeViewController.jsの追加
最後に js/TreeViewController.js を追加します。ここで生成されたツリービューのデータを表示します。
まず構造は次のようになります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var controller = { | |
| __name: 'sample.TreeViewController', | |
| _$tree: null, // ツリービューのDOM | |
| _currentSelected: null, // 選択しているデータについて | |
| __init: function() { | |
| // 初期設定 | |
| }, | |
| setTreeData: function(dataOrPromise, opt) { | |
| // ツリービューにデータをセット | |
| }, | |
| h5.core.expose(controller); | |
| })(jQuery); |
まず初期設定を行います。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| __init: function() { | |
| sample.util.createDefaultControllerView(this); | |
| this._$tree = this.$find('.jstree'); | |
| }, |
ここで sample.util.createDefaultControllerView(this); とすることで表示処理の下準備(バインド)を行っています。
そして setTreeData を実装します。これはデータを受け取って描画を行う処理になります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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が入っています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| _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から読み込まれるように指定します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script src="js/TreeViewController.js"></script> |
これで準備完了です。実行すると、ツリービューが表示されるかと思います。

今回はデモなのでデータを手動で用意していますが、実際にはAjaxを使ってサーバから取得することになるかと思います。しかし、その場合もutil.jsさえ切り替えれば良いだけです。
このようにAjaxによるデータ取得部分をコントローラによる処理と切り離しておくことでメンテナンス性をあげることができます。さらに同期、非同期処理の両方に対応しておくことでコードも見やすくなるはずです。
今回のコードはGitHubで見られるようになっています。また、動作しているデモはこちらになります。
次回はデータの一覧表示部分について見ていきます。
IDE(統合開発環境)というとVisual StudioやEclipseなど大きなアプリケーションというイメージがありますが、Web IDEはWebブラウザさえあればすぐに開発が可能になります。
今回はそんなWeb IDEを提供するオープンソース・ソフトウェアを紹介します。
Tern

IDEというよりも任意のテキストエリアに対してIDE相当の入力補完機能や変数を探す機能を追加します。対応している言語はJavaScriptになります。自作のWebサービスにてJavaScriptのコードを入力しやすくしようと考えるならば導入してみると良さそうです。
nudgepad/nudgepad: Build working prototypes in your browser.

Node.jsベースのコードをWeb IDE上で記述し、そのまま実行できるソフトウェアです。nodeやbashをWeb上で実行する機能もあります。
coreh-deprecated/nide: Beautiful IDE for Node.js

こちらもNode.js向けのアプリをWebブラウザ上で開発できます。package.jsonも編集ができます。バージョン管理機能も備えていて、TimeMachineライクに表示ができます。
c9/core: Cloud9 Core – Part of the Cloud9 SDK for Plugin Development

Cloud9はWeb IDEをクラウドサービスとして提供しています。そしてコアになる部分をオープンソースとして公開しています。クラウドで提供できるレベルなので、テーマ機能や入力補完機能など、かなり多機能となっています。
Code editor awesomeness : ICEcoder

対応している言語はPHP、JavaScript、HTML、CoffeeScriptなどで主にWebシステム開発に向いたIDEとなっています。MySQL管理機能やコンソールなども提供されています。
typesafehub/activator: Typesafe Activator

Scala用というのが大きな特徴になります。そしてコードを編集すると、その場でコンパイルがかかって実行結果の確認まで行えます。テストの仕組みも提供されています。
Codiad/Codiad: Web Based, Cloud IDE

40以上の言語に対応したWeb IDEになります。プラグインによる機能拡張、エラーチェック、リアルタイムコラボレーション機能などがあります。
b3log/wide: A Web-based IDE for Teams using Go programming language/Golang.

Go向けのWeb IDEになります。一台のマシンで立てれば、他のユーザはGo環境がなくとも開発が行えるようになります。ビルドや実行も可能です。
bodil/catnip: A web based Clojure IDE
Clojure向けのWeb IDEになります。プレゼンテーションモードという機能があります。Windows向けにはインストーラーも配布されています。
joshmarinacci/ElectronIDE: New web based Arduino IDE
WebベースのArduino IDEです。IoTをはじめていく中でArduinoを使ってみるという方はこちらから入ると開発環境を作らずに使えるようになりそうです。
Web IDEもずいぶんと高機能化しており、かつサーバ環境のパワーを使って高速なコンパイルやテスト実行ができるようになっています。企業の情報統制などを考える中で、Web IDEによる情報集約は現実的になっているかも知れません。
HTML5開発はWeb IDEとの相性がとても良くなっています。DevToolsと合わせて高速な開発をサポートしてくれる存在と言えそうです。
では今回から業務アプリケーションを実際に作っていきたいと思います。まず最初にDevided Boxを実装します。これは画面を枠線で分割し、かつそれをマウスでドラッグして担当者の好きな画面構成に変更できる機能です。
実際に動かすと次のようになります。

要点としては幾つかあり、
- 黒い枠線をドラッグして画面構成がダイナミックに変更できる
- 3ペインのいずれも右上にあるアイコンをクリックして折りたためる
- ウィンドウをリサイズした時にペインの構成も追従する
これらの機能をhifiveの一機能であるDividedBoxを使いつつ、実装していきたいと思います。
実行環境について
実際に動かす際にはWebサーバが必要になります。環境の構築方法については拙作のITpro Report – 手軽にHTML5/JavaScript開発を始めるための環境構築法:ITproを参考にしてください。
HTMLについて
まずHTMLですが、hifive/jQuery/Bootstrapを読み込みます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
| <meta http-equiv="pragma" content="no-cache" /> | |
| <meta http-equiv="cache-control" content="no-cache" /> | |
| <meta name="viewport" content="width=device-width"> | |
| <!– IE8以下なら1系、それ以外なら2系のjQueryを使用する –> | |
| <!–[if lt IE 9]> | |
| <script src="lib/jquery/jquery-1.11.1.js"></script> | |
| <![endif]–> | |
| <!–[if gte IE 9]><!–> | |
| <script src="lib/jquery/jquery-2.1.1.js"></script> | |
| <!–<![endif]–> | |
| <link rel="stylesheet" href="lib/bootstrap/3.3.2/css/bootstrap.min.css"> | |
| <link rel="stylesheet" href="lib/hifive/h5.css" /> | |
| <script src="lib/bootstrap/3.3.2/js/bootstrap.min.js"></script> | |
| <script src="lib/hifive/ejs-h5mod.js"></script> | |
| <script src="lib/hifive/h5.dev.js"></script> | |
| </head> | |
| <body> | |
| </body> | |
| </html> |
さらにペインの折りたたみやドラッグでの移動を可能にするライブラリである AccordionPanel および DividedBox を読み込みます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <link rel="stylesheet" href="lib/hifive/ui/DividedBox.css"> | |
| <link rel="stylesheet" href="lib/hifive/ui/AccordionPanel.css"> | |
| <script src="lib/hifive/ui/DividedBox.js"></script> | |
| <script src="lib/hifive/ui/AccordionPanel.js"></script> |
bodyタグの内容について
Bodyタグ内ですが、次のようになります。appRootクラス以下にアプリケーションを展開してきます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div class="desktop dividedBox vertical"> | |
| <div class="header fixedSize"></div> | |
| <div class="appRoot autoSize"></div> | |
| </div> |
JavaScriptの実装
まず js/AppPurchaseManagerController.js というファイルを作成します。これはWebアプリケーション以外のウィンドウなどを管理します。例えばビューの作成およびウィンドウをリサイズした時のイベントハンドリングを行います。そして、 __nameで指定されている sample.AppPurchaseManagerController という変数名でグローバルにアクセスできるようにしています(h5.core.exposeを使うことで実現します)。ウィンドウのリサイズをハンドリングするため、_accordionPanelControllerも紐付けています。これは先ほど読み込んだAccordionPanel.jsが提供しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function() { | |
| var controller = { | |
| __name: 'sample.AppPurchaseManagerController', | |
| _accordionPanelController: h5.ui.container.AccordionPanelController, | |
| __init: function() { | |
| // ビューを作成 | |
| sample.util.createDefaultControllerView(this); | |
| }, | |
| '{window} resize': function() { | |
| this._accordionPanelController.refresh(); | |
| }, | |
| '{rootElement} boxSizeChange': function(ctx) { | |
| } | |
| }; | |
| // コントローラを外部公開 | |
| h5.core.expose(controller); | |
| })(); |
次のこの sample.AppPurchaseManagerController を利用する PageController.js を作成します。このコントローラはWebアプリケーション全体に関わってきます。このようにコントローラを分割しておくことで機能の切り分けがしやすくなります。
__postInitメソッドを使って、初期化処理後のデザイン変更を行っています。また、ウィンドウをリサイズした際にDivided Boxもリフレッシュします。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function($) { | |
| var pageController = { | |
| __name: 'sample.PageController', | |
| __templates: 'template/sample-template.ejs', | |
| _dividedBoxController: h5.ui.container.DividedBox, | |
| _appPurchaseManagerController: sample.AppPurchaseManagerController, | |
| appRootDividedBox: h5.ui.container.DividedBox, | |
| __meta: { | |
| _appPurchaseManagerController: { | |
| rootElement: '.appRoot' | |
| } | |
| }, | |
| __postInit: function() { | |
| // ヘッダ直後のdividerは非表示 | |
| this._dividedBoxController.hideDivider(0); | |
| }, | |
| '{window} resize': function() { | |
| this._dividedBoxController.refresh(); | |
| } | |
| }; | |
| h5.core.expose(pageController); | |
| })(jQuery); |
先ほど、sample.AppPurchaseManagerControllerの中で sample.util.createDefaultControllerView(this); を実行しています。これはテンプレートのレンダリングになります。それらの処理を行うのは util.js になります。これは各コントローラの共通メソッドを実装しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function() { | |
| h5.u.obj.expose('sample.util', { | |
| createDefaultControllerView: function(ctrl, param) { | |
| ctrl.view.update(ctrl.rootElement, ctrl.__name, param); | |
| }, | |
| }); | |
| })(); |
テンプレートとして渡している sample-template.ejs の内容は次のようになります。idとそれを利用するコントローラ名を一致させていますが、これは上記 createDefaultControllerView がそう指定しているからです。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script type="text/ejs" id="sample.AppPurchaseManagerController"> | |
| <div class="dividedBox horizontal fill fullHeight"> | |
| <div class="box panelBox fill" data-default-state="normal" | |
| data-box-name="ショートカット"> | |
| <div class="contentWrapper"> | |
| <div class="shortcut fullHeight"></div> | |
| </div> | |
| </div> | |
| <div class="dividedBox vertical full fullHeight"> | |
| <div class="box panelBox fill autoSize" data-default-state="normal" | |
| data-box-name="一覧"> | |
| <div class="gridViewer fullHeight"></div> | |
| </div> | |
| <div class="box panelBox fill autoSize" data-default-state="normal" | |
| data-box-name="詳細"> | |
| <div class="detail fullHeight"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </script> |
最後にPageControllerを実行する index.js を作成します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function($) { | |
| $(function() { | |
| h5.core.controller('.desktop', sample.PageController); | |
| }); | |
| })(jQuery); |
これで desktop クラスに対して sample.PageController がバインドされます。
HTML側の修正
作成したJavaScriptファイルおよびCSSファイルを読み込みます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <link href="css/sample.css" rel="stylesheet" /> | |
| <script src="js/util.js"></script> | |
| <script src="js/AppPurchaseManagerController.js" /></script> | |
| <script src="js/PageController.js" /></script> | |
| <script src="js/index.js"></script> |
sample.cssについては細かく説明しませんが、こちらのファイルを利用してください。
これで実装が完了し、動作するようになりました。

今後、機能を順番に開発していくことを踏まえてコントローラを分割しています。分割しておくことで各機能が明確に分かれ、理解するのが容易になったり、肥大化を防止できるようになります。
ここまでの実装をhifiveのサンプルページ にて公開しています。コードはGitHub上に公開していますので確認したい時に参考にしてください。次回は左側のペインにツリービューを実装します。
今回から実際に業務でよく使われるようなアプリケーション開発を通じてhifiveの使い方を紹介していきたいと思います。利用するのは以下のような画面の、業務システムであればよくあるような仕組みの申請ツールになります。

左側にステータスに応じてフォルダツリーが並んでいます。ここで項目を選択すると、右上に一覧が表示されます。動作は次のようになります。

そして一覧の中から選択すると、右下に詳細が表示されます。一覧からは複数選択ができます。最後に承認ボタンを押すことで、データが承認されます。承認されたデータはステータスが更新されますので、承認済みのリストに入ります。
さらに画面上の仕切りはマウスで動かせるようになっています。

今回はJavaScriptでデータを生成していますが、Ajaxを使ってサーバから取得するようにすれば、検索/選択/更新という業務システム上よくある案件が実現できるようになります。
アプリケーションの動作はこちらからも確認できます。
では次回以降、細かく機能を紹介していきます。
hifive – HTML5企業Webシステムのための開発プラットフォーム
![]()
思いついたWebサイトのアイデアを簡単に、かつすぐに実用的な形にする際に非常に便利なのがCSSフレームワークです。その中でもっとも主流と言えるのがBootstrapですが、2015年の12月にBootstrap v4が正式リリースされました。バージョンアップに伴い、bootstrap4で対応しているサービスも続々リリースされています。そこで今回は、bootstrap4に対応したサービス、ライブラリーそしてテーマを中心に9つほどご紹介したいと思います。
ライブラリ
reactstrap
reactstrapは簡単にReactでBootstrap 4を簡単に使うことのできるコンポーネントです。
nmp経由でのインストールは、以下のコードで出来ます。
npm install --save reactstrap react-addons-transition-group react react-dom
たとえば、以下のような記載で簡単におしゃれなbootstrapのボタンを設置することができます。

import React from 'react';
import { Button } from 'reactstrap';
export default (props) => {
return (
<Button color="danger">Danger!</Button>
);
};
Bootstrap 4 ruby gem
Bootstrap 4 ruby gem はRuby on Rails あるいはCompassでBootstrap 4 を使うことができるツールです。
Ruby on Railsの場合
Ruby on Railsで使いたい場合は、Gemfileに以下を記載します。
gem 'bootstrap', '~> 4.0.0.alpha3'
注意として、sprockets-railsのバージョンは最低v2.3.2になります。また、bootstrapのスタイルをImportするためにapplication.scssをapp/assets/stylesheets/に設置してください。利用は以下のコードでできます。
@import "bootstrap";
Compassの場合
Rails抜きで使用したい場合もRubygemsでインストールするところまでは同じです。
既存のプロジェクトがある場合はconfig.rbにて読み込みます。
require 'bootstrap'
そしてBootstrapを以下のようにインストールします
bundle exec compass install bootstrap
プロジェクトがない場合は、以下のようにbootstrap supportとともに作成できます。
$ bundle exec compass create my-new-project -r bootstrap --using bootstrap
もしくは、Gemfileを使うこともできます。
$ compass create my-new-project -r bootstrap --using bootstrap
なお、使い方は動画でも確認できます。
テーマ・テンプレート
Material Design for Bootstrap
昨今のデザインのトレンドでありGoogleが提唱しているのマテリアルデザインをbootstrapのCSSとJavaScriptを用いて簡単に実現できるテンプレートがMaterial Design for Bootstrapです。
導入についてはIntroduction · Bootstrap Material Designが詳しいです。
Land.io
Bootstrap 4のテンプレートとUIキットを用いてレスポンシブなランディングページを作りたいならば導入しておきたいのがLand.ioです。スライダーを導入した画面やUIキットを用いて、動画を導入した画面などが簡単に作成できます。
Engage
Bootstrap 4とHTML5を用いたフルでレスポンシブに対応した無料のテンプレートがEngageになります。カスタマイズも容易に行えるので、ビジネスでの活用もおすすめです。
Bootstrap Four
ブログを立ち上げる際によく使われるのがWordPressですが、Bootstrap 4を用いているテーマがBootstrap Fourになります。
Bootstrap 4 Dashboard
Bootstrap 4で新たに加わった特徴(5グリッド、cards、 emでの大きさ調整、flexbox, Normalize.css、大きめのフォントサイズ)の全てに対応したテンプレートが Bootstrap 4 Dashboardです。
Modular Admin
無料のBootstrap 4を使ったダッシュボードのテーマが、Modular Adminになります。
その他
DataTables
jQueryを用いて、htmlのテーブルをよりインタラクティブにできるプラグインがDataTablesです。こちらは元々Bootstrap3にも対応していましたが、Bootstrap4でも問題なく使えるようになってます。
PurityM
中小規模のWebサイト作成用アプリケーションであるMobiriseウェブサイトビルダーのテーマの中にはBoostrap4対応のテーマ、PurityMがあります。PurityMを使えばBootstrap4を用いたページをHTMLの知識なしに10分程度で作成できます。
また、ソーシャルのシェアボタンやグーグルマップやグーグルフォント、パララックス、全面動画背景なども容易に使えます。
まとめ
今回は Bootstrap4に対応したライブラリ、サービスを紹介しました。Boostrapを用いることで、独自に一から作る場合に比べてモバイル対応や、こったカード型レイアウトなどを簡単に実現できます。
紹介したサービスを用いて皆さんの作業工数が削減してください。
思いついたWebサイトのアイデアを簡単に、すぐに実用的な形にする際に非常に便利なのがCSSフレームワークです。その中でもっとも主流と言えるのがBootstrapですが、2015年の12月にBootstrap v4が正式リリースされました。どのように変更が加わったのか気になっている方も多くいるかと思います。そこで今回はバージョンアップの詳細を紹介します。
Bootstrap 4で大きく変わった点をBootstrap 4 alpha · Bootstrap Blogを参考に記載していきます。
- CSSプリプロセッサーをLESSからSassへ変更
- グリッドシステムの改善
- 「Extra large」が追加され、より細かくブレイクポイントが指定できるようになりました。例えばSassに組み込むならば以下のような書き方ができます。
@include media-breakpoint-up(xl) { ... }
- Flexboxの使用が可能
- _variables.scss にある $enable-flex をtrueにすることでflexboxを利用したCSS拡張も利用できるようになりました。ただし、IE9では使えないので注意が必要です。
- サムネイルやパネル、wellsはcardsへ統合
- cardsのサンプルコードです。
class=“card-title”>Card title
class=“card-text”>Some quick … content.
</div> </div>
- HTMLリセットを新しいモジュールに統合
- box-sizing: border-box, marginでの微調節などは1つのSassファイルで管理できるようになりました。
- カスタマイズオプションを刷新
- gradients、transitionsおよびshadowsなど、これまではLESSファイルに記載があり別ファイルの作成の必要があったものが、Sassの変数で変えられるようになりました。
- IE8のサポート終了
- サイズ指定は、pxではなくremとemに変更になりました。もしもIE8が必要ならば、v3を使用してください。
- すべてのJavaScriptのプラグインを書き直し
- ツールチップとポップオーバー用の自動配置ツールの改善
- その他(代表的なもの)
- フォームコントロール機能が新しくなりました
- マージンとパディングのclassが追加されました
- 新しいユーティリティのclassが追加されました
まとめ
IE8のサポート停止など、よりHTML5やES6への強化が目立ちます。Bootstrap 4は、モバイル環境により最適化されたといえます。Bootstrapを活用し、工数の大幅削減を目指しましょう。










