hifiveはJavaScriptのフレームワークの他、Webアプリケーションを開発するのに便利なUIライブラリも多数提供しています。
今回はその一つ、タイルコンテナを紹介します。タイルをドラッグ&ドロップで移動してユーザの希望に合わせた配置に自分で組み替えられるライブラリです。
利用イメージ
最初の表示は次のようになります。タイル状の表示が並んでいます。

グレーになっている部分がドラッグできる部分になっています。
タイルをドラッグして移動できます。

幅二つの場合は左右の入れ替え、一つ分の幅の部分にはドロップできません。

コード
まず、スタイルシートとJavaScriptを読み込みます。
<link rel="stylesheet" href="tileContainer.css" />
<script src="tileContainer.js"></script>
次にDOM構築完了のタイミングでタイルコンテナを実行します。
<script type="text/javascript">
$(function() {
h5.core.controller('.columns', h5.ui.components.tileContainer.tileContainerController);
});
</script>
ここで、 .columns はタイルコンテナ表示にするクラス名です。
HTML
HTMLは次のように記述します。
<div class="columns">
<div class="column box_content">
<h1 class="header">カラム1</h1>
</div>
<div class="column box_content">
<h1 class="header">カラム2</h1>
</div>
<div class="column box_content">
<h1 class="header">カラム3</h1>
</div>
<div class="column column2 box_content">
<h1 class="header">2倍幅のカラム</h1>
</div>
<div class="column box_content">
<h1 class="header">カラム4</h1>
</div>
</div>
これで準備は完了です。
使いどころ
この手のUIが便利なのは、業務システムの管理画面やダッシュボードになるのではないでしょうか。ユーザごとに好みが分かれたり、担当毎に必要な情報が異なる場合があります。そういった時にユーザの好きな形に表示が変更できるのはシステムの柔軟性を保つ上でも重要です。
クライアントサイドだけでできるので、サーバサイドの変更がいらないのも大きな利点です。表示位置をサーバサイドに保存する手もありますが、CookieやlocalStrageに保存しておくのも手だと思います。
タイルコンテナの表示はこちらのデモでご覧いただけます。
個人、会社を問わず素早くWebアプリケーションの開発がはじめられるとあって使われるようになっているのがBootstrapです。今回はそんなBootstrapのカスタマイズを素早く行っていけるWebサービスをまとめて紹介します!
StyleBootstrap.info

ナビゲーションバー、ボタン、フォームなどの色、ボーダー、フォントサイズを細かくカスタマイズできます。リアルタイムプレビューがついていますのでその場で雰囲気が分かります。
StyleBootstrap.info: Twitter Bootstrap theme generator
Initializr

Bootstrapのカスタマイズという訳ではありませんが、HTML5 Webアプリケーションを開発するためのベースをカスタマイズしながら作成できます。
Initializr – Start an HTML5 Boilerplate project in 15 seconds!
Beautiful Buttons for Twitter Bootstrappers

ボタンだけをカスタマイズできるサービスです。特にボタンの色だけを多彩にカスタマイズできます。
Beautiful Buttons for Twitter Bootstrappers
Twitter Bootstrap Button Generator

こちらのボタンのカスタマイズに特化しています。ボタンのテキスト、サイズ、色、アイコンなどを選んでボタンを生成します。ちょっとした作業の短縮になりますね。
Twitter Bootstrap Button Generator | PlugoLabs
BootTheme

WebベースでWYSIWYGエディタを使ってBootstrapをカスタマイズできます。ギャラリーには他ユーザが作ったテーマが掲載されています。
BootTheme : Web Designer and Theme Generator for Twitter Bootstrap
PaintStrap
AdobeのAdobe kuler、またはCOLOURloversからカラーテーマを生成します。奇麗なカラーテーマから作れるのでバランスが整ったデザインになるでしょう。
PaintStrap – Twitter Bootstrapテーマをカラースキームから生成
Jetstrap

ドラッグ&ドロップでUIが作れるサービスです。かなり本格的に画面を作り込むこともできます。
Jetstrap – The Bootstrap Interface Builder
Fancyboot

色やグリッドのカラム数に加えて利用する機能自体を絞り込むこともできます。特定の機能だけを使いたいといった場合やJavaScriptプラグインを絞り込みたい場合に使えそうです。
Fancyboot – Customize · Bootstrap
Lavish

任意の写真からカラースキームを読み取ってテーマ化します。好きな写真を選ぶことで、それに合わせたデザインに仕上がると思います。
Lavish – Generate your own Bootstrap color scheme
Bootstrap Live Customizer

Bootstrap全体のカラー変更、フォント、サイズなどをライブプレビュー付きでカスタマイズできます。どの要素がどの部分に当てはまるのかも分かるのでBootstrapのカスタマイズだけでなく、その構造理解にも使えそうです。
Bootstrap Magic

ライブプレビュー付きのBootstrapカスタマイズサービスです。サイト全体もBootstrapで作られているので実例としても興味深いです。
Bootstrap Magic : Generate your own bootstrap theme quickly and easily
LayoutIt!

ドラッグ&ドロップでBootstrapの画面が作成できます。スタイルシートのクラス名も書かれていて、プレビューが分かりやすいです。
LayoutIt! – Interface Builder for Bootstrap
いかがですか。Bootstrapを使えばHTML5なWebアプリケーションが素早く構築できます。そのまま使っても良いですが、自社の雰囲気に合わせたカラーカスタマイズしたいというケースもあるでしょう。そんな時にこういったサービスを使えば素早く雰囲気が変えられるので、ぜひ使ってみて欲しいです。
もちろんデザインだけでシステムは動きませんので、Webアプリケーション化する際にはぜひhifiveを使ってみてください!
Ajaxを使った保存処理の最中やデータレンダリング中など、処理中には誤ったボタン操作やクリックを防止したいと思うことがあるでしょう。そんな時に役立つのがインジケータです。
hifiveでは高機能なインジケータクラス(Indicator)が備わっています。Indicatorを使いこなせばユーザビリティの高いシステム構築に役立つはずです。
処理はコントローラの中で行う
例えばボタンを押された時にインジケータを出したいとします。こちらは押す前です。

押すとインジケータ表示になります。

コードは次のようになります。
'#button click': function(context) {
var indicator = this.indicator({
message: '処理中…'
}).show();
// 非同期処理の中で使用するために退避
var dfd = this.deferred();
setTimeout(function() {
indicator.hide();
dfd.resolve();
}, 800);
return dfd.promise();
},
この手のインジケータを出す処理というのは、非同期処理が多いでしょう。非同期処理のはじまる前にdeferredを定義し、最初にpromiseを返します。その上で非同期処理の完了時にreslveを返すのがコツです。上記のコードの場合、800ms処理を遅延しています。indicatorもhideメソッドで消えます。
対象を変更できる
先ほどの例ではコントローラの監視対象になっているDOM内が処理対象になっていました。次の例では親要素まで含めて操作不可にします。

このボタンをクリックします。

このように parent と書かれたDOMもインジケータ対象になります。
コードは次のようになります。
'#parentBlock click': function(promise, resolve, reject) {
var indicator = this.indicator({
// targetに親コントローラを指定
target: $(this.rootElement).parent(),
message: 'child2 parent block'
}).show();
var dfd = this.deferred();
setTimeout(function() {
indicator.hide();
dfd.resolve();
}, 800);
return dfd.promise();
},
先ほどとの違いはインジケータを作る際のオプションtargetを指定していることです。parent()として親要素を指定しています。このようにインジケータで処理できない領域を指定するのは柔軟に変更できるのが特徴です。
子のコントローライベントを使う
さらに別な例です。以下を見てください。

3つのDOMがあります。この一番親に当たるDOMのボタンをクリックします。

そうするとこのように子のDOMに設定されているインジケータが実行されます。
処理としてはまず親のコントローラに次のように記述します。
'#childrenBlock click': function() {
this.$find('#child3Block').trigger('selfBlock');
this.$find('#child4Block').trigger('click');
},
上の方は selfBlock という独自イベントを呼び出しています。下の方はクリックです。まず上の行の処理は次のコードが呼び出されます。
// トリガーで呼ばれるイベント
'#child3Block selfBlock': function(context) {
// 自身をブロックする
var indicator = this.indicator({
message: 'child1 self block'
}).show();
// 非同期処理の中で使用するために退避
var dfd = this.deferred();
setTimeout(function() {
// 自身のブロックを解除
indicator.hide();
dfd.resolve();
}, 800);
return dfd.promise();
},
さらに下の行も同様です。
'#child4Block click': function(context) {
// 自身をブロックする
var indicator = this.indicator({
message: 'child1 self block'
}).show();
// 非同期処理の中で使用するために退避
var dfd = this.deferred();
setTimeout(function() {
// 自身のブロックを解除
indicator.hide();
dfd.resolve();
}, 800);
return dfd.promise();
},
この二つの処理の違いは、上は独自のイベント、下はクリックイベントということです。そのため、下の方のDOMにあるボタンを押すと、その部分だけインジケータが表示されます。

インジケータ表示部分を細かく制御したり、使い回すのも簡単にできます。
ウィンドウ全体をブロック
インジケータを表示するような処理を行っている場合、ウィンドウ全体を触れないようにしたいと思うかも知れません。そのような対応も可能です。

処理は次のようになります。
'#globalBlock click': function(promise, resolve, reject) {
var dfd = this.deferred();
// BODYをブロックする
var indicator = this.indicator({
target: document.body,
message: 'global block',
promises: dfd.promise()
}).show();
// indicator()にpromiseオブジェクトを渡しているのでresolve()またはreject()されると自動的にindicator.hide()される
setTimeout(function() {
dfd.resolve();
}, 2000);
return dfd.promise();
}
方法としては簡単で、targetオプションにdocument.bodyを渡しています。さらにpromisesオプションにpromiseを渡すことで、resolveやrejectを行うと自動的にインジケータを非表示にしてくれる機能もあります。
プログレス表示
処理中をより効果的に知らせるためにプログレス表示もできます。次の画像の数字部分です。

コードは次のようになります。
'#child6Start click': function(context) {
// インジケータの表示
var indicator = this.indicator({}).show();
// Deferredオブジェクトを作成
var dfd = this.deferred();
var i = 0;
var id = setInterval(function() {
// プログレスバーの非表示
if (i >= 100) {
indicator.hide();
clearInterval(id);
dfd.resolve();
return;
}
// 進捗状況(%)の表示
indicator.percent(i++);
}, 70);
return dfd.promise();
}
こちらの例ではsetIntervalを使って定期的に処理を回して、 indicator.percent(i++); を実行しています。これで数字部分の表示がアップデートしていく仕組みです。
promiseが複数ある場合
最後に一番複雑なパターン、promiseが複数ある場合です。Ajaxを複数並列で処理するといった場合はよくあります。そういった場合に使えるテクニックです。
'#child8Start click': function(context) {
var that = this;
// 4秒掛かる処理
var func1 = function() {
var df1 = that.deferred();
setTimeout(function() {
df1.resolve();
}, 4000);
return df1.promise();
};
// 6秒掛かる処理
var func2 = function() {
var df2 = that.deferred();
setTimeout(function() {
df2.resolve();
}, 6000);
return df2.promise();
};
// func1とfunc2が終わるのを待つので、6秒待つことになる。
var indicator = this.indicator({
promises: [func1(), func2()]
}).show().message('処理中...');
}
見ての通り、インジケータのpromisesオプションは複数のpromiseを指定できるようになっています。この部分は全てのpromiseがresolveまたはrejectになるまで待ちますので、最も長いfunc2の6秒待ってからインジケータが非表示になる仕組みです。
なおこれらの処理は h5.css を読み込んでいる必要があります。.h5-indicatorにスタイル設定がしてありますのでシンプルで効果的なインジケータ表示が簡単にできるようになっています。
今回紹介したコード、画面はhifive Block Sampleに掲載されていますのでぜひ参考にしてください。
いかがだったでしょうか。処理待ちというのはよくありがちですが、JavaScriptでは非同期処理が多いのでユーザが操作を急いでしまってデータに不備が生じるケースが多々あります。そういった問題を未然に防げるインジケータ、ぜひ活用してください。
HTML5/CSS3から利用できるようになったWeb Font。画像を使わずに格好いいロゴ表示を行ったり、可読性の高いテキスト表示を可能にします。しかしフォントを公開してしまうことに対して従来のライセンスの考えや、帯域(ネットワークスピード)の問題も出ています。
そこでWeb Fontをもっと活用すべく、Web Fontのホスティングを行っているサービスを紹介します。これらのサービスを活用すればこれまでとは全く違うデザイン、Webサイト構築が実現するはずです。
FONTPLUS

700を越えるフォントを日本語フォントを扱っています。Webページ内の文章を自動で解析し、使われている文字だけを抽出してWeb Fontにするので、配信フォントのサイズを大幅に軽減できます。PVまたはドメインごとの料金体系となっています。
タイプスクウェア

450フォントが利用できます。モリサワフォントもあります。月1万PVまでは無料、25万PV/月であっても2,000円/月となっています。
アマナイメージズ

330以上のフォントが利用できます。無料でも23書体が利用できます。または月額540円/フォントで利用もできます。
M+ OUTLINE FONTS

M+ OUTLINE FONTSが無料で使えます。ただし通信速度などの保証はありませんのでご注意ください。
日本語Webフォントサービス

月額3,066円で316のフォントが使えます。丸明フォントが提供されています。
日本語Webフォントサービス | 316のデザインフォントが月額3,066円(税込)で手軽に使えます
デコもじ

英和合わせて約600フォントが利用できます。個人、法人向けにそれぞれ有料プランが用意されています(トライアルあり)。
デコもじ|ウェブフォントで、ホームページが、ブログが、もっと楽しくなる♪
もじでぱ

無料のフォントのみ配布しています。ビジネスレベルの高品質なフォントではないかも知れませんが、個性的なフォントが数多く登録されています。
もじでぱ|ウェブフォントでブログ&ホームページの文字(フォント)を自由に変更して楽しもう♪
Web Fonts

一部日本語のフォントも登録されています。英語Web Font配信サービスとしては最大規模ではないでしょうか。
Realtype Project

フォントをWebブラウザ上にキャッシュさせず、かつ使われている文字だけに限定したフォントを生成することでフォントベンダーが安心してフォントを提供できる仕組みを提供しています。
Textar Font

アスキーアートを奇麗に表示するJavaScriptタグおよびWeb Fontを配布しています。
Textar Font – アスキーアート対応ウェブフォント
Google Fonts

英文フォントを中心に638フォントが公開されているGoogleのサービスです。無料で利用できます。
Web Fontを使うメリットとしては、テキストの可読性向上、テキストベースになることによるSEO効果が考えられます。最近ではアイコンフォントとしてWeb Fontの文字を使ってアイコン表示を行うといった試みも増えています。
問題は帯域で、特に日本語フォントは文字数が多いのが難点でした。今回紹介したような配信サービスではHTMLページ上で使われている文字(特に漢字)を特定することでフォントを動的に生成し、配信サイズを軽減しています。こうした工夫を自分たちで作り込むのは困難なので外部サービスを使うメリットが多いにあると思われます。
前回に続いてデータモデル、バインドの説明を行っていきます。初期データの表示が終わりましたので、続いてTodoの登録と、チェックボックスを付けた時のイベントを説明します。なおソースコードはGitHubにアップしてありますので参考にしてください(todo.html)。実際に動いているデモはこちらになります。
Todoを登録する
Todoを登録するということは、
- データの入力
- 登録ボタンのクリック
- Todoモデルを新規作成
- 入力テキストを消す
- 表示(Todo一覧)を更新
といった順番でフローを行っていくということです。
データの入力

データの入力はテキストボックスに行います。これはHTML(todo.html)に記述があります。
<form id="todoRegForm">
<div class="todo-form corner-all box">
<div class="todo-form-right">
<input type="button" id="btnRegist" class="corner-all ui-button gray" value="登録" tabindex="2">
</div>
<div class="todo-form-left">
<input type="text" id="txtTodo" class="corner-all ui-text txt-todo" placeholder="TODO" tabindex="1">
</div>
</div>
</form>
登録ボタンのクリック

そして処理をハンドリングしているのは javascripts/controller/todoController.js になります。
'#btnRegist click': function(context) {
this._insertToDo(context);
},
この部分で #btnRegist がクリックされるのを監視しています。クリックされると呼ばれるのは _insertToDoです。同様にTodoのテキストボックスでリターンキーが押された場合(フォームがサブミットされた場合)も処理しておきます。
'#todoRegForm submit': function(context) {
this._insertToDo(context);
},
このようにイベントハンドリングを使うことで同じ処理の使い回しが簡単にできるようになります。
_insertToDo: function(ctx) {
var $txtTodo = this.$find('#txtTodo');
if ($txtTodo.val() === '') {
alert('TODOを入力して下さい。');
} else {
this.todoLogic.add($txtTodo.val());
$txtTodo.val('');
}
// formのsubmitが動作しないよう伝播を止める
ctx.event.preventDefault();
},
この処理の中では簡易的な入力チェックと、todoLogicへの追加だけを行っています。ビュー周りの処理は行っていません。
Todoモデルを新規作成
ではその todoLogic.add を見てみましょう。
add: function(content) {
var item = this.model.create({
id: this._getNewId(),
status: false,
content: content,
insertDate: +new Date()
});
this.todos.push(item);
},
ロジックに紐づくモデル(Todoモデル)の作成をして、それを this.todos に追加しています。
表示(Todo一覧)を更新
上述の通り、ロジックでもやはりビュー周りの処理は行っていません(ロジックはビューと切り離すべきなので当然ですが)。
では実際に表示処理をどこで行っているかというと、元々コントローラを初期化した時点で次のように記述しています。
todoLogic: sample.todo.logic.TodoLogic,
:
__ready: function() {
var that = this;
this.todoLogic.init().done(function(data) {
that.view.bind('h5view#tmplTodos', {
todos: data
});
});
},
ロジックが関連づいているため、ロジックに紐づくモデルへのデータ追加によって h5view#tmplTodos の表示が自動で更新される仕組みになります。さらにこの処理はロジック中の、
todos: h5.core.data.createObservableArray(),
によって todos を監視対象と指定することで実現しています。一覧系のデータ変更に対してビューの処理を必要としないのはとても楽ですね。
Todoを完了する

では次にTodoのチェックボックスを入れた時の処理を見ていきます。HTMLでは次のようになっています。
<tbody data-h5-loop-context="todos">
<tr>
<td class="status">
<input type="hidden" data-h5-bind="id" />
<input type="checkbox" class="ui-check" data-h5-bind="attr(checked):checked"/>
</td>
<td class="content">
<span data-h5-bind="content;style(text-decoration):contentStyle"></span>
</td>
</tr>
</tbody>
そしてこのチェックボックスのクリックイベントを監視しているのが todoController.js になります。
'#list tbody input[type="checkbox"] click': function(context) {
var target = context.event.currentTarget;
var id = this._getSelectedItemId($(target).closest('tr'));
var checked = target.checked;
this.todoLogic.update(id, {
status: checked
});
context.event.stopPropagation();
},
この行で発生したイベントかは context.event.currentTarget で取得ができます(ここではチェックボックスが取得されています)。
_getSelectedItemId というのは選択されている行のidを取得するメソッドです。$(target).closest(‘tr’) を引数で渡している通り、チェックボックスの親要素にあたるtr要素を渡しています。
_getSelectedItemId: function(targetElem) {
return $(targetElem).find('input[data-h5-bind="id"]').val();
},
そして実際のデータ更新処理は this.todoLogic.update にて行っています。
update: function(id, data) {
var item = this.model.get(id);
item.set(data);
},
updateはidを使って該当するデータを取り出して ハッシュで渡されている data に基づいてデータ更新を行っています。なぜ this.model.get(id) でデータが取得できるかというと、todoModel.js で次のように初期化をしているからです。
var todoModel = todoManager.createModel({
name: 'TodoModel',
schema: {
// ID
id: {
id: true,
type: 'integer'
},
:
JSONの要素idに対してid(アイデンティティとしてのid)を true にすることでデータ取得ができるようになります。
この場合においても表示処理は一切行っていません。データの更新をすれば自動的に表示が切り替わるようになっています。
例えばこちらのWebデモにおいて、

sample.todo.controller.TodoController.todoLogic.model.get(1).set({content: "Test"})
とJavaScriptコンソールで実行すると、一番上のタスクの内容がTestに変わるのが確認できるはずです。コントローラ、ロジック、モデルが連携しているからこそ、このような動きが可能になっています。

では次回は最後にTodo詳細の表示と細かな情報修正について紹介します。
Web技術の良いところはブラウザさえあれば実行確認ができて、テキストエディタだけで作れてしまう所ではないでしょうか。さらに今回紹介するようなサービスはWeb上にHTML5/JavaScript/CSS3を保存して共有できるので、HTML5の新しいAPIを試すのに使ったり、テクニックを披露するのに使えますよ。
JSFiddle

多種多様なJavaScriptフレームワークの読み込みも可能で、HTML/JavaScript/スタイルシートの記述ができます。
Create a new fiddle – JSFiddle
CodePen

グラフィックス系の投稿も良く見かけるWebプレイグラウンドです。
CodePen – Front End Developer Playground & Code Editor in the Browser
JS Bin

2ペイン構成で左側がエディタ、右側にプレビューが出せるようになっています。
JS Bin – Collaborative JavaScript Debugging
CSSDeck

特にCSS3でのテクニックが多いようです。
HTML5, CSS3, JS Demos, Creations and Experiments | CSSDeck
jsdo.it

カヤックさんのサービスです。英語、日本語、中国語で提供されています。
jsdo.it – Share JavaScript, HTML5 and CSS
Cssizer.com

JavaScriptはなく、スタイルシートのリアルタイム反映に特化しています。
Cssizer.com | Real Time CSS Editing
scratchpad.io

HTMLのbody部だけを変更できるサービスです。URLを共有して編集できます。
D3.js Playground

データの高度なビジュアル化を行うD3.jsに特化したプレイグラウンドです。
Html5 Snippet

HTML5に特化しています。JavaScript/CSS3の記述を行えます。
CSSDesk – Online CSS Sandbox

スタイルシートの編集ができます。JavaScriptはありません。
dabblet.com

縦3つに分割されているのが印象的なスタイルシートプレイグラウンドです。JavaScriptはα版として提供されています。
Codecademy Labs

オンラインプログラミング学習サイトCodecademyで提供されているJavaScript実行環境です。
Mozilla Thimble

Mozillaが提供するHTMLプレイグラウンドです。JavaScriptの自動実行の切り替え機能があります。
Liveweave

4つに区切られた画面構成が特徴的です。右下に実行結果が表示されます。
Liveweave – HTML5, CSS3 & JavaScript playground for web designers & developers
tmpltr

HTML/JSON/CSSという組み合わせでJavaScriptを実行するのではなく、JSONデータをHTMLテンプレートと組み合わせて表示するサービスになっています。
HTMLiveCode

シンプルなHTMLプレイグラウンドです。自由にHTML/JavaScript/CSSが実行できます。
HTMLiveCode – Browser-based editor for HTML/CSS/JS prototyping
いかがでしたか。自分の作品を作るのはもちろん、他の人の作品を見ても勉強になるでしょう。また友人や同僚とみんなで一つのプロジェクトを試したり、JavaScriptの実行結果を確認したりするのも便利です。
Webサーバを立てたりしなくとも、これらのサービスを使えばHTML5アプリケーションが簡単に試せます。どんどん作ってHTML5の世界に飛び込んでください!
サーバサイド開発ではMVCと呼ばれる仕組みが一般的に使われるようになっています。しかしWebアプリケーションにおいてはまだまだ利用が進んでいないようです。
hifiveではデータモデルという仕組みによって情報の一元化ができるようになっています。データモデルが使えるようになると、HTML5 Webアプリケーションの開発がぐっと効率的になるでしょう。
データモデルの基本
データモデルの基本については チュートリアル(データモデル編) を参考にしてください。今回はサンプルのTodoアプリをベースに見ていきます。なおソースコードはGitHubにアップしてありますので参考にしてください(todo.html)
今回はまず、初期データの表示までを解説します。
最初の表示

このようにタスクの一覧が表示されます。 javascripts/todo.js を見ると次のように処理を行っています。
$(function() {
h5.core.controller('#content', sample.todo.controller.TodoController);
});
これにより、 #content 以下に sample.todo.controller.TodoController が関連づけられます。コントローラーは javascripts/controller/todoController.js になります。
コントローラでの処理
todoController では __readyメソッドを使ってコントローラ化した後に処理を実行しています。コールバックされるメソッドについては コントローラのライフサイクルについて を参考にしてください。
__name: 'sample.todo.controller.TodoController',
todoLogic: sample.todo.logic.TodoLogic,
__ready: function() {
var that = this;
this.todoLogic.init().done(function(data) {
that.view.bind('h5view#tmplTodos', {
todos: data
});
});
},
todoLogic として関連づけている sample.todo.logic.TodoLogic を初期化しています。 promise を使っていますので 実行完了後、doneメソッドが呼ばれます。
そこでデータ(タスクの一覧)を受け取り、viewに関連づけています。
ロジックの処理
次に todoLogicのinitメソッドを見てみます。ファイルは javascripts/logic/todoLogic.js です。
:
model: sample.todo.model.ToDoModel,
todos: h5.core.data.createObservableArray(),
:
init: function() {
var df = this.deferred();
var that = this;
$.ajax({
url: SAMPLE_DATA_FILEPATH,
dataType: 'json',
cache: false,
success: function(data) {
var dataItems = that.model.create(data);
that.todos.copyFrom(dataItems);
df.resolve(that.todos);
},
error: function() {
alert('サンプルデータの読み込みに失敗しました。');
}
});
return df.promise();
},
Ajaxを使ってタスク一覧を取得しています。 SAMPLE_DATA_FILEPATH は json/todo.json になります。このファイルはタスクが配列になっているだけです。取得が成功した際に、
var dataItems = that.model.create(data);
that.todos.copyFrom(dataItems);
を実行しています。ここでモデルを作り、さらにロジックに定義されている todos に対してデータアイテムをコピーしています。dataはタスクの配列になっていますので、
var dataItems = that.model.create(data);
で生成されるdataItemsも配列になります。なおmodelというのは sample.todo.model.ToDoModel になります。
再度コントローラ
モデルが生成された後、 deferred に対してデータモデルを送っています。その結果、コントローラのdoneに対してデータモデルが送られてくる仕組みです。先ほどのコントローラー側のソースコードをもう一度掲載します。
__ready: function() {
var that = this;
this.todoLogic.init().done(function(data) {
that.view.bind('h5view#tmplTodos', {
todos: data
});
});
},
doneの後、h5view#tmplTodos に対してデータをバインドしています。HTMLテンプレートは todo.html の中に定義してあります。コメントで括っておくことで隠せるようになっています。
<!--{h5view id="tmplTodos"}
<table class="todo-list" id="list">
<thead>
<tr><th> </th><th>内容</th></tr>
</thead>
<tbody data-h5-loop-context="todos">
<tr>
<td class="status">
<input type="hidden" data-h5-bind="id" />
<input type="checkbox" class="ui-check" data-h5-bind="attr(checked):checked"/>
</td>
<td class="content">
<span data-h5-bind="content;style(text-decoration):contentStyle"></span>
</td>
</tr>
</tbody>
</table>
-->
data-h5-loop-context=“todos” という定義によって、tbody 以下を todos の回数分ループ処理します。data-h5-bind を用いることでJavaScriptから柔軟にデータをメンテナンスできるようになります。その他表示については データバインド用のHTML記述仕様 を参考にしてください。
今回はまず初期表示について紹介しました。単純にJSONデータを表示するのに比べると手順が多いですが、この後のタスク追加や変更、ステータス変更などにおいてバインドの仕組みが大いに役立ってきます!
hifiveではいわゆるMVCの他にロジックと呼ぶ機能があります。ロジックとは、
- 複雑な計算
- サーバ通信
- ローカルDB操作
など画面操作を含まない通信、計算処理を記述するものと定めています。
処理を外出しすることで、コントローラはビューとロジックの取り回しをするだけで良くなります。それによって可読性、保守性、再利用性、テストが容易になるといったメリットが生まれます。
図として描くと次のようになります。

ロジックは純粋に計算処理、DB周りの処理に特化することで複雑な処理を外出しできるようになります。
デモ
まずはデモで動きを見てみましょう。
このような画面が最初に表示されています。

検索ボタンを押すと、外部からデータを取得してそれを一覧として表示します。

コントローラー
では最初にコントローラのコードを見てみます。
var itemSearchController = {
__name: 'ItemSearchController',
__templates: 'template.ejs',
/**
* 商品検索ロジック
*/
itemSearchLogic: itemSearchLogic,
/**
* 検索ボタン押下アクション
*/
'#searchBtn click': function(context) {
var $resultDiv = this.$find('#resultList');
var that = this;
$resultDiv.empty();
// 画面で選択されたカテゴリ
var category = $('#select-category option:selected').val();
this.itemSearchLogic.getItemList(category)
.done(function(resultData) {
that.view.append($resultDiv, 'template1', {
listData: resultData
});
})
.fail(function(errMsg) {
alert('取得に失敗しました' + errMsg);
});
}
};
コントローラが行っている処理としては、ボタンが押されたイベントを取得し、 itemSearchLogic.getItemList を実行しています。ロジックはデフォルトで Deferred を持っていますので、done/fail/thenなどのキーチェーンメソッドが使えます。これにより、いわゆるコールバック地獄になるのを防止し、見通しの良いコードが書けるようになります。
ロジック
次のロジックのコードを見てみましょう。
var itemSearchLogic = {
__name: 'ItemSearchLogic',
/**
* 商品リスト(商品名と税込価格)を取得する。
*
* @param categoryId {Number} カテゴリID
* @returns 商品リスト
*/
getItemList: function(categoryId) {
var dfd = this.deferred();
var result = null;
this._getItemData(categoryId)
.done(function(data) {
result = $.map(data, function(obj) {
dfd.notify(data.length);
obj.price = Math.floor(obj.price * 1.05);
return obj;
});
dfd.resolve(result);
})
.fail(function(error) {
dfd.reject(error.message);
});
return dfd.promise();
},
/**
* カテゴリIDから商品(商品名と税抜価格)リストをサーバから取得する。
*
* @param categoryId {Number} カテゴリID
* @returns 商品リスト
*/
_getItemData: function(categoryId) {
return $.ajax({
type: 'GET',
dataType: 'json',
url: './itemList' + categoryId
});
}
};
ロジックの処理では最初に deferred を定義しています。後は核処理の状態によって resolve(成功)やfail(失敗)などのステータスを変更しています。非同期処理になりますので、あらかじめ dfd.promise() を返却しています。
ロジックで行っていることは、コントローラーが表示処理を行いやすいようにデータを取得、加工する処理になります。このメリットとしては、
- ロジックのメソッドがテストしやすい
- メソッド単位で再利用がしやすい
- コントローラのコードが短い
などがあります。ビューが絡むとテストがとても面倒になりますが、ロジックには表示処理がないのでユニットテストが書きやすく、品質も保証しやすくなります。また、似たような処理があった場合にコントローラ内部に処理があるとビューと結びついてしまって再利用がしづらいですが、ロジックは切り離されているのがメリットです。
表示処理を行うコントローラの中にデータの加工処理が入ると、コードがとても複雑になってしまいます。見通しの良いコードを保つためにもロジックを活用しましょう。
コントローラだけで行う場合
例えば今回のコードをコントローラだけで実装すると、このようになるかと思います。
'#searchBtn click': function(context) {
var $resultDiv = this.$find('#resultList');
var that = this;
$resultDiv.empty();
// 画面で選択されたカテゴリ
var category = $('#select-category option:selected').val();
$.ajax({
type: 'GET',
dataType: 'json',
url: './itemList' + category
})
.done(function(resultData) {
resultData = $.map(resultData, function(obj) {
dfd.notify(resultData.length);
obj.price = Math.floor(obj.price * 1.05);
return obj;
});
that.view.append($resultDiv, 'template1', {
listData: resultData
});
})
.fail(function(errMsg) {
alert('取得に失敗しました' + errMsg);
});
単純な処理なのでまだ見通しは悪くありませんが、商品リストを取得する処理を他でも再利用したいとなったらどうでしょう。その場合、同じテンプレートを使うとは限りません。Deferredは非同期処理なのでうまく書き出すのも難しいかもしれません。そういった後々の行程を考えるとあらかじめコントローラとロジックに分離しておくメリットが分かってもらえるのではないでしょうか。
今回のデモはGitHub上にアップしてあります(logic.html)。ぜひ動作を確認してください。
6月14日(土)、いわゆるhtmldayに朝日新聞メディアラボ×hifiveによる学生向けプログラミングイベントhifive Student Challengeが開催されました。HTML5 Japan Cupへの応募も狙ったHTML5アプリケーション作成ハッカソンです。

今回はその模様をお届けします。なお当日はリアルタイムにFacebookページにてハッカソンの模様を配信していました。
午前中はアイディアソン
午前10時から開催されたhifive Student Challengeはまず、学生同士の自己紹介にはじまりました。その後はすぐにアイディア出しです。まずは個人個人でアイディアを考えます。既に来る時点からアイディアを考えてきたという強者もいらっしゃいました。

今回のお題としては以下があります。
- 朝日新聞社提供のニュース記事を活かす
- hifiveを使ったWebアプリケーションを作る
hifiveについては開発時に用いるものなので、アイディア出しとしては朝日新聞社提供のニュース記事がキーになってきます。特にHTML5 Japan Cupにおいて朝日新聞社のテーマは ニュース記事を活かした、20代、30代向けモバイルゲーム となっていますので、ゲームを活かしていかに面白い見せ方ができるかがアイディアの基礎になってきます。
アイディア発表

一人3つくらいのアイディアが出てきたところで、次にそれを別な視点からとらえていきます。全く違う要素を加えてみたり、ミニマムな視点でとらえる、大きくする、時間的な要素を加えると言った具合です。そうすることでアイディアのタネにもっと新しい面白さを加えられるようになります。
それが終わったところでチームに分かれてアイディアの発表です。個人個人で思い思いに作ってもいいですが、やはりハッカソンの楽しみはチーム戦です。とはいえはじめて会った人同士で上手にアイディアをミックスできない点はhifiveのSEがフォローし、今日一日という制限された中でいかにアイディアを実現させるかを話し合っていきました。
午後から開発

そして午後から実際に開発に入っていきます。各自のPCには既にhifiveの開発環境が整っており、Eclipseを使ってTomcatを実行し、ローカルでhifiveを使った開発ができるようになっています。さらにGitでチーム内でリポジトリを共有できるようになっています。
今回は限られた時間の中で開発を進めるため、サーバサイドの仕組みはあらかじめ準備していました。朝日新聞社の記事データも取り込んでおり、検索や記事一覧をJSONフォーマットで取り出せるようになっています。また、各チームのアイディアの中で出たデータをストアする仕組みや認証なども用意しています。
hifiveを使おう
さてここまで来て大きな問題になるかと思われたのが思いのほか参加者にプログラミング経験者が少なかったことです。サーバサイドのプログラミング言語は経験があってもJavaScriptは経験がないという方もいます。そのような状況の中、開発がスムーズにいくのかが鍵だったのですが、適切なサポートとhifiveのデバッグ機能によってハマってしまう機会は多くありませんでした。
もちろん学生の皆さんが優秀で吸収力に優れていたこともありますが、初心者であっても経験があるメンバーがサポートすれば開発は十分に進められるのがhifiveの強みと言えます。
時間切れ、そして発表

本日の予定は18時までであり、17時まで開発を行った後、17時半から発表の予定となっていました。各チームとも思っていた機能がすべて実装できたとは言いがたい様子です。とはいえ見栄えを整え、17時半からは立派な発表となりました。
Sakuraiチームはニュース記事を読むことでステータスをアップし、他のキャラクターをバトルするゲームを開発していました。一つのジャンルに特化することはもちろん、バランスよくニュースを読むことでキャラクターをパワーアップさせることもできます。
Sushizチームはニュース記事を読んだり、記事を題材にした討論を交わすことで得られるポイントを仮想街の建物や土地購入に充てるという育成ゲームを考えました。配信が終わったニュース記事は友人の街へいって読むことができるなどソーシャル要素も入っています。
各自の感想
やはり限られた時間の中で自分のアイディアをすべて発揮するのは難しかったようです。しかし皆さんの感想の中にプログラミングを覚えたいという言葉が入っていたのがとても印象的でした。プログラミングを覚えることで自分のアイディアを実現できる嬉しさ、苦労して作ったものが実際に思ったように動いたときの喜びはとても大きかったのではないでしょうか。
作成した作品はHTML5 Japan Cupにそのまま応募し、賞を獲得にいたるのは難しいかもしれません。幸い、応募リミットまではまだ半月あります。このペースで開発できればもしかするとすごい作品になるかも知れません!
皆さん、お疲れさまでした!
システム開発は順当に行くだけとは限りません。むしろ開発よりもデバッグやテストの方が使っている時間が多かったりもします。そのため、効率的なデバッグ環境があるというのは大きな利点になるでしょう。
hifiveではそのためのhifive開発者ツールを用意しています。複雑になりがちなJavaScript開発もhifive開発者ツールを使えばすっきり見通しの良い開発が続けられるはずです。
デバッグツールの設定
まずは設定からです。といってもとても簡単で、
<script src="//code.htmlhifive.com/h5-dev-tool.js"></script>
を読み込むだけです。またはこちらからダウンロードしたZipファイルを解凍して、同じフォルダ内に入れて読み込んでください。
注意点としては、 h5.dev.js を読み込んだ後に h5-dev-tool.js を読み込むようにしてください。
hifive開発者ツールを起動
JavaScriptファイルを読み込む記述をしたら、HTMLファイルをブラウザから開きます。

Google Chromeなどポップアップウィンドウをデフォルト禁止しているブラウザではこのような注意アラートが出るかも知れません。ポップアップブロックを解除して再読み込みしてください。

こちらがhifive開発者ツールが開いた状態になります。左下にあるウィンドウはWebアプリケーション、右上にあるのがhifive開発者ツールです。
hifive開発者ツールの主な機能
では主な機能を順番に見ていきます。まずメソッドの内容が分かります。

あるコントローラーのあるロジックにおけるメソッドが分かるようになっています。0と表示されているのはメソッドがコールされた回数です。
次にトレースです。トレースではメソッドの呼び出しと終了がリストになって表示されます。これでどういった処理が行われたかが一目で分かるようになります。

さらにトレースでは右クリックで該当関数に飛べるようになっています。
コントローラレベルではイベントハンドラを見ることもできます。例えば下の図の場合、 #calc click に対してイベントがついているのが分かります。

ちょっとこの画像では分かりづらいのですが、 #calc click をマウスオーバーすると、左側の = ボタンがハイライトされます。つまりイベントハンドラと結びついたDOMをハイライトしてくれます。これはどのイベントがどのDOMと関連しているかが一目で分かるので開発効率があがるはずです。
さらにコントローラ自身を選んだ場合、そのコンテナがハイライトされます。これでコントローラがどのDOMを監視しているかが一目で分かります。

便利なところ
hifiveはMVCフレームワークなので、ファイル名の命名規則や配置を決めておくことで誰でも開発に加わりやすいです。とはいえ、大型なWebアプリケーションのある一部を修正してほしいと言われてもとっかかりがないと始めることすらできないと思います。
そこでhifive開発者ツールを使うと画面を見つつ、該当する画面中の該当するメソッドがどこにあるのかすぐに突き止められるようになります。さらにトレースを見ながら処理を追いかけていくことで、どこを修正すべきかと言ったあたりをつけるのも簡単になるでしょう。
デバッグ時においてもロガーやトレースを組み合わせることで開発効率はぐっとアップするはずです。JavaScriptのMVCフレームワークはいくつかありますが、hifiveはこういった業務の中で求められるであろう機能が充実しているのが大きな特徴になります。ぜひご利用ください!
今回のコードはGitHub上にアップしてあります(calc.html)。また開発者ツールの詳細はこちらにあります。あわせてご覧ください。
