HTML5では多くのAPIが追加されていますが、HTMLにおいてもタグや要素が追加されています。今回はその一つ、Aタグに追加されたping属性についてです。
ping属性は以下のように設定します。
To Google
これでAタグをクリックすると http://www.google.co.jp へ遷移するのですが、その際同時に example.com へも POSTメソッドを呼び出します。これがpingということです。
利点
利点としては、
- JavaScriptを書かないで実行できる
- JavaScriptがオフでも実行できる
- 外部URLへの遷移でもトラッキングできる
などが考えられます。特にブロック系の機能を入れたとしてもトラッキングできるのが利点と言えるかも知れません。
対応ブラウザ
対応ブラウザとしてはHTML a ping Attributeによると、IE/Operaを除く主要ブラウザでサポートされています。iOS Safariでも動作します。
Pingされる内容について
調べてみた限りでは特にデータが送られてくる訳ではないようです。また、エラーコード(501など)を返したとしてもリンク先に遷移する動作には影響がありませんので、何かデータを返すと言ったことも無意味と思われます。
使いどころ
サイト内部の遷移であればセッションなどを使ってトラッキングが可能です。解析を行う上で必要になるのは外部サイトへの遷移だと思われます。また、データが送れないのでURLの中にパラメータを追加しておくのが良さそうです。
ping要素は覚えておくと色々な場面で使えそうです。なお、過剰なトラッキングはプライバシー上の問題になるかも知れませんのでご注意ください。
hifiveの入力値チェック(バリデーション)機能であるFormControllerはHTMLタグに設定するだけで入力値チェック機能を追加できます。必須や数値の桁数チェックなどは簡単に行えますが、ワークフローによってはより複雑なフローが求められることでしょう。
そこで今回はより複雑な入力値チェックを実現する方法について紹介します。
1. 正規表現でチェックする
正規表現を用いることでより複雑なパターンによる入力値チェックが可能になります。これは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
| <input id="tel" name="tel" type="text" class="form-control" data-pattern="^[0-9]{2,3}\-[0-9]{2,4}\-[0-9]{3,4}" /> |
なお、正規表現でのエラーの場合、エラーメッセージに正規表現が出てしまいます。これは開発者以外には分かりづらいと思われますので、
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._formController.setSetting({ | |
| property: { | |
| : | |
| tel: { | |
| displayName: '電話番号', | |
| message: '{displayName}のフォーマットが違います', | |
| }, | |
| } | |
| }); |
のようにして message をカスタマイズすることをお勧めします。
2. customFuncを用いる
より複雑な処理の場合、customFuncオプションが利用できます。この場合、 FormController.addRule メソッドを利用します。
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.formController.addRule({ | |
| birthday: { | |
| customFunc: function(value) { | |
| // 処理を書く | |
| } | |
| } | |
| }); |
入力値が問題なかった場合はtrue、問題がある場合はfalseを返すだけです。
非同期処理の場合
入力値を使ってサーバに問い合わせてレスポンスを受け取る場合があります。例えばユーザIDがユニークかどうかチェックする場合です。
そうした時には Promise オブジェクトを返すようにし、検証した結果が問題なければresolve、問題ある場合はrejectを返すようにします。
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.formController.addRule({ | |
| userId: { | |
| customFunc: function(value) { | |
| var dfd = h5.async.deferred(); | |
| h5.ajax('existUser', { | |
| // 非同期処理 | |
| }).done(function(resp) { | |
| // 入力値に問題なかった場合 | |
| dfd.resolve({ | |
| // 何かデータがあれば指定 | |
| }); | |
| // 入力値に問題があった場合 | |
| dfd.reject({ | |
| // 何かデータがあれば指定 | |
| }); | |
| }); | |
| return dfd.promise(); | |
| } | |
| } | |
| }); |
3. 入力値をグルーピングする
電話番号を-(ダッシュ)ごとに区切ったり、年月日を別な入力欄に分けることはよくあります。そして、それら複数の入力欄を一つに扱って入力値の検証に使うでしょう。その場合は data-h5-input-group-container でグループ名を定義します。この時にも各入力項目に対するバリデーション条件が指定できます。
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 data-h5-input-group-container="birthday"> | |
| <input name="year" type="text" data-max="[2015,true]" data-required />年 | |
| <input name="month" type="text" data-required />月 | |
| <input name="day" type="text" data-required />日 | |
| </div> |
このように定義すると入力チェック時に一つのデータとして扱えるようになります。
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.formController.addRule({ | |
| birthday: { | |
| customFunc: function(value) { | |
| // 分けて取り出す | |
| var y = value.year; | |
| var m = value.month; | |
| var d = value.day; | |
| } | |
| } | |
| }); |
入力値のチェックは常に求められる機能ですが、実際にどうチェックを行うかは業務フローによって異なってくることでしょう。hifiveのバリデーションライブラリは業務システムの設計に合わせて柔軟に実装できます。ぜひ導入してください。
ユーザの入力値を検証するのはWebアプリケーションを開発する上で大事な機能です。従来はユーザの入力をサーバサイドで検証し、入力エラーがあれば再度フォームをエラーメッセージとともに表示するのが一般的でした。しかしこの場合、レンダリングにかかる時間であったり、入力を再現するのが面倒(特にファイル送信など)でした。
そこで最近ではJavaScriptを使った入力チェック(バリデーション)が使われるようになっています。もちろんサーバサイドでの入力チェックはこれまで通り必要ですが、まずJavaScript側でチェックをすることで、ユーザストレスを軽減したUXが提供できるようになります。
そこで今回はhifiveの提供する入力値検証ライブラリ、FormControllerの使い方を紹介します。
ベースとなるコントローラ
まず元になるコントローラのコードを紹介します。 .confirmをクリックすると入力値の検証を行うこととします。
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 reportController = { | |
| __name: 'ReportController', | |
| __ready: function() { | |
| }, | |
| '.confirm click': function(context, $el) { | |
| // 入力値の検証 | |
| }, | |
| }; | |
| h5.core.expose(reportController); | |
| })(jQuery); | |
| $(function() { | |
| h5.core.controller(document.body, ReportController); | |
| }); |
ベースとなるHTMLについて
さらにベースとなるHTML(body内)は次のようになります。UIライブラリとして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
| <body> | |
| <div class="edit container "> | |
| <form class="form-horizontal"> | |
| <div class="report-content"> | |
| <div class="msg alert alert-danger"></div> | |
| <div class="worklog"> | |
| <div class="common-items row"> | |
| <div class="col-sm-4"> | |
| <div class="form-group"> | |
| <label class="col-sm-3 control-label" for="reportDate">日付</label> | |
| <div class="col-sm-9"><input id="reportDate" name="reportDate" type="date" class="form-control"></div> | |
| </div> | |
| </div> | |
| <div class="col-sm-8"> | |
| <div class="form-group"> | |
| <label class="col-sm-3 control-label" for="startTime">勤務時間</label> | |
| <div class="col-sm-9"> | |
| <div class="input-group"> | |
| <input id="startTime" name="startTime" type="time" class="form-control"> | |
| <span class="input-group-addon">~</span> | |
| <input id="endTime" name="endTime" type="time" class="form-control"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="section-wrap"> | |
| <div class="section"> | |
| <div class="section-header row"> | |
| <div class="col-sm-6"> | |
| <div class="form-group"> | |
| <label class="col-sm-2 control-label" for="category">報告区分</label> | |
| <div class="col-sm-10"> | |
| <input id="category" name="category" type="text" class="form-control"> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-sm-6"> | |
| <div class="form-group"> | |
| <label class="col-sm-3 control-label" for="title">タイトル</label> | |
| <div class="col-sm-9"><input id="title" name="title" type="text" class="form-control"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="section-content form-group"> | |
| <label class="col-sm-1 control-label" for="comment">報告内容</label> | |
| <div class="col-sm-11 comment"><textarea id="comment" name="comment" class="form-control"></textarea></div> | |
| </div> | |
| <div class="section-img form-group"> | |
| <label class="col-sm-1 control-label">添付画像</label> | |
| <div class="col-sm-11 img-input-wrap"> | |
| <input class="form-control" accept="image/*" name="img" type="file"/> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="btn-wrap text-center"> | |
| <div class="btn-group"> | |
| <button class="cancel">キャンセル</button> | |
| <button class="confirm">確認する</button> | |
| </div> | |
| </div> | |
| </form> | |
| </div> | |
| </body> |
FormControllerを設定する
まず js/index.js に対してFormControllerを利用する設定を行います。
元:
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 reportController = { | |
| __name: 'ReportController', | |
| __ready: function() { | |
| : |
修正後:
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 reportController = { | |
| __name: 'ReportController', | |
| // バリデーションコントローラの設定 | |
| _formController: h5.ui.FormController, | |
| __meta: { | |
| _formController: { | |
| rootElement: 'form' | |
| } | |
| }, | |
| __ready: function() { | |
| : |
rootElementというのはバリデーション対象になるフォームのことです。今回はフォームが一つなので form としていますが、複数ある場合は id やクラス名で指定できます。
次に __ready 内で FormControllerの設定を行います。今回は個別の入力項目に対してエラー表示を行うstyleと、フォーム全体のエラーメッセージを表示するcompositionというプラグインを利用します。他にも
- bsBalloon
- message
- balloon
といったプラグインが用意されており、自分で新しいプラグインを作ることもできます。
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._formController.addOutput(['style', 'composition']); |
そして、プラグインに関する設定を行います。
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._formController.setSetting({ | |
| output: { | |
| style: { | |
| errorClassName: 'has-error', | |
| replaceElement: function(element) { | |
| return $(element).closest('.form-group'); | |
| } | |
| }, | |
| composition: { | |
| container: this.$find('.msg'), | |
| wrapper: 'div' | |
| }, | |
| }, | |
| }); |
エラークラス名などはBootstrapのものを使うように指定しています。全体のエラーメッセージは .msg に対して表示するように指定しています。
バリデーションを実行する
バリデーションは確認ボタンを押したタイミングで実行します。
元:
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(context, $el) { | |
| // 初期化 | |
| context.event.preventDefault(); | |
| : |
修正後:
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(context, $el) { | |
| // 初期化 | |
| context.event.preventDefault(); | |
| // バリデーション実行 | |
| if (!this._formController.validate().isValid) { | |
| this.$find(".msg").show(); | |
| return false; | |
| } else { | |
| this.$find(".msg").hide(); | |
| } | |
| : |
バリデーション自体は this._formController.validate() にて実行されます。その返却値としてオブジェクトが返ってきますので、その isValid を使ってバリデーション結果が確認できます。
バリデーションが失敗した場合は、 .msg を可視化しつつ、処理を完了しています。バリデーションが成功した場合は .msg を非表示にしています。
index.html の修正
続いて 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
| <input id="startTime" name="startTime" type="time" class="form-control"> |
修正後:
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
| <input id="startTime" name="startTime" type="time" class="form-control" data-required /> |
このように data-required を追加するだけでstartTimeに対する必須チェックが追加されます。
同じように、
元:
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
| <input id="category" name="category" type="text" class="form-control"> |
修正後:
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
| <input id="category" name="category" type="text" class="form-control" data-required /> |
元:
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="col-sm-9"><input id="title" name="title" type="text" class="form-control"></div> |
修正後:
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="col-sm-9"><input id="title" name="title" type="text" class="form-control" data-required /></div> |
元:
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="col-sm-11 comment"><textarea id="comment" name="comment" class="form-control"></textarea></div> |
修正後:
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="col-sm-11 comment"><textarea id="comment" name="comment" class="form-control" data-required data-size="[10,200]" /></textarea></div> |
この報告欄については data-size も使っています。これによって10文字から200文字までの入力という制限を追加しています。
ラベルを日本語化する
ここまでの変更で試すと、エラーメッセージの一部が英語になっているのが分かるかと思います。
categoryは必須項目です
titleは必須項目です
commentは必須項目です
これでは見栄えがよくありませんので、 js/index.js の this._formController.setSetting に設定を追加します。
元:
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._formController.setSetting({ | |
| output: { | |
| style: { | |
| errorClassName: 'has-error', | |
| replaceElement: function(element) { | |
| return $(element).closest('.form-group'); | |
| } | |
| }, | |
| composition: { | |
| container: this.$find('.msg'), | |
| wrapper: 'div' | |
| }, | |
| } | |
| }); |
修正後:
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._formController.setSetting({ | |
| output: { | |
| style: { | |
| errorClassName: 'has-error', | |
| replaceElement: function(element) { | |
| return $(element).closest('.form-group'); | |
| } | |
| }, | |
| composition: { | |
| container: this.$find('.msg'), | |
| wrapper: 'div' | |
| }, | |
| }, // カンマを忘れずに! | |
| property: { | |
| title: { | |
| displayName: 'タイトル' | |
| }, | |
| category: { | |
| displayName: '報告区分' | |
| }, | |
| comment: { | |
| displayName: '報告内容' | |
| } | |
| }, | |
| }); |
propertyを使って、各入力項目毎に displayName 設定を追加します。ここでラベルを設定してあげることで、入力エラーが
報告区分は必須項目です
タイトルは必須項目です
報告内容は必須項目です
といった具合に日本語化されます。
バリデーションのデモはこちらで試せます。確認ボタンをクリックするとエラーが表示されます。JavaScriptのコード自体はごく短く、設定しか記述していないのを確認してください。
バリデーションを使いこなし、よりユーザビリティの高いWebアプリケーションを目指してください!
JavaScriptはシングルスレッドで動作するので、ネットワーク処理などが非同期で行われるようになっています。そうしないとAjaxを使っている間、何も入力や画面スクロールなども受け付けなくなります。
しかし非同期実行のしわ寄せとして、コールバックが多くなってネストが深くなったり、Promiseでも処理が分かりづらくなります。例えば非同期処理を伴ったループ処理を書こうとすると、次のようになります。
loop([1, 2, 3, 4, 5, 6], function(key, value, promise) {
value = value * 2;
promise.resolve(value);
}).then(function(results) {
console.log(results);
})
function loop(ary, call) {
var results = {};
return new Promise(function(resolve, reject) {
var keys = Object.keys(ary);
var index = 0;
function each_loop(key, value, index) {
if (typeof key == 'undefined') {
return resolve(results);
}
return new Promise(function(res, rej) {
call(key, value, {resolve: res, reject: rej})
}).then(function(msg) {
results[key] = msg;
index++;
each_loop(keys[index], ary[keys[index]], index);
},
function(msg) {
return reject(msg);
});
}
each_loop(keys[index], ary[keys[index]], index);
});
}
/*
$ node promise_test.js
{ '0': 2, '1': 4, '2': 6, '3': 8, '4': 10, '5': 12 }
*/
他のプログラミング言語に比べてとても難解なものになってしまいがちです。
そこで使ってみたいのがyieldです。JavaScript 1.7からの構文になりますが、多くのブラウザでサポートが開始されています。
yieldの使い方
簡単な使い方を紹介します。Google ChromeのDevToolsなどで試せます。

まず最初にジェネレータを生成します。特徴は function* ではじまることです。
function* generator(){
yield 1;
yield 2;
yield 3;
yield 4;
}
そしてこのジェネレータを実行します。そうするとジェネレータオブジェクトが生成されます。
g = generator();
// generator {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window}
そうするとすぐにyieldが実行される訳ではなく、停止した状態になっています。実行するには next() メソッドを使います。
g.next();
// Object {value: 1, done: false}
valueはyieldの返却値です。doneがfalseになっているのが分かります。つまり、まだyield文があるということです。さらに実行します。
g.next();
// Object {value: 2, done: false}
g.next();
// Object {value: 3, done: false}
g.next();
// Object {value: 4, done: false}
g.next();
// Object {value: undefined, done: true}
4まで終わるとdoneがtrueとなって返ってきます。これが基本的な使い方です。
yieldを使った処理について
基本的な使い方が見た通り、doneのステータスを見ながらfalseであれば次のyieldを実行していくようにすれば非同期処理が順番に実行できるようになります。まずジェネレータは次のようになります。
function* generator() {
yield new Promise(function(resolve, reject) {
console.log("Execute after 1000ms")
setTimeout(function() {resolve("1000ms waited.")}, 1000);
});
yield new Promise(function(resolve, reject) {
console.log("Execute after 3000ms")
setTimeout(function() {resolve("3000ms waited.")}, 3000);
});
yield new Promise(function(resolve, reject) {
console.log("Execute after 500ms")
setTimeout(function() {resolve("500ms waited.")}, 500);
});
}
そして生成されたジェネレータをwhileでループ処理します。
var g = generator();
function Loop(g) {
var p = g.next();
if (p.done) return;
p.value.then(function(msg) {
console.log(msg);
Loop(g);
});
}
Loop(g);

そうすると正しい順番で 1000ms、3000ms、500ms停止してから処理を実行します。大事なのはPromiseオブジェクトを返すようにするという点と、ループ処理部分はジェネレータを再帰的に呼び出す必要があるので関数で囲まなければならないということです。
yieldを使うことで、非同期処理がネストせず、同期処理のように書けます。コードの見通しが格段に良くなりますので、不具合の発生が抑えられるようになるでしょう。Webアプリケーションなどで非同期処理の発生が見込まれる場合、元々全体を関数で囲んでしまっておいても良いかもしれません。
なお、yield自体はまだ一部のブラウザでサポートされていませんので、その場合はBabelを使って変換するのが良さそうです。
Pitaliumを使うとスクリーンショットベースのテストができます。そしてもしエラーが発生した際にはPitalium Explorerを使って正解時の画像と、失敗時の画像を比べることができます。
今回はその画像の比較方法を紹介します。
Quick flipping

前後の画像を切り替えて表示します。同じ場所を切り替えるので、ちょっとした変化に気付くことができるでしょう。上部の「Expected」「Actual」のタブをクリックすることで、表示する画像を切り替えられます。
2-up

二つの画像を左右に並べて比較します。高さにずれがあったりする場合は、2-upが気付きやすいでしょう。
Swipe

二つの画像を重ねて表示し、スライダーを使って左右を切り替えます。前後のコンテンツで水平方向の差異があった時に便利です。
Onion skin

スライダーで徐々に画像を切り替えます。透明度を差し替えているので、コンテンツが異なる場合は表示がおかしいと感じるはずです。
Edge overlapping

スクリーンショットのエッジ(輪郭)を検出して、その差異を表示します。青と赤のラインで異なって表示されるので、どこが異なるかは一目瞭然でしょう。ただしエッジなので、背景色が異なるといった場合は分かりません。
細かいところはルーペで確認できます。

基本的にはEdge overlappingでだいたいの確認はできますが、色の違いなどSwipeを使って検出することになるでしょう。それぞれの機能を使い分けて、効率的なテスト結果確認を行ってください。
hifive 1.2では入力値の検証(バリデーション)機能が追加されました。これはHTMLタグのdata-*要素に設定する入力値の検証機能です。今回はそのタグに設定する要素について紹介します。
設定パターンは13個
現在の検証として設定できるパターンは13個となっています。例えば requiredであれば、 data-required という指定を行います。
required
入力値の必須チェックです。null/undefined/空文字が検出できます。
<input data-required />
assertNull
入力値がnullまたはundefinedであることをチェックします。何かデータが入っているとエラーになります。
<input data-assertNull />
assertNotNull
入力値がnullまたはundefinedでないことをチェックします。ラジオボタンの必須チェックなどに使えます。
<input data-assertNotNull />
max
最大値のチェックです。一つ目の数字が最大値、二つ目をtrue指定した場合はその最大値も含めることになります。
<input data-max="10,true" /> <!-- 10以下 -->
<input data-max="10" /> <!-- 10未満 -->
min
最小値のチェックです。一つ目の数字が最小値、二つ目をtrue指定した場合はその最小値も含めることになります。
<input data-min="10,true" /> <!-- 10以上 -->
<input data-min="10" /> <!-- 10より大きい -->
assertFalse
値がfalseであるかどうかをチェックします。
<input data-assertFalse />
assertTrue
値がTrueであるかどうかをチェックします。
<input data-assertTrue />
future
値が日付型、かつ現在時刻より未来であるかどうかチェックします。
<input data-future />
past
値が日付型、かつ現在時刻より過去であるかどうかチェックします。
<input data-past />
digits
数字の桁数判定を行います。整数部分が最初の引数で示す桁数以下であり、かつ小数部分が二つ目の引数で示す桁数以下となっているかチェックします。
<input data-digits="3,2" /> <!-- 100.33はOK。100.222はエラー -->
pattern
正規表現による入力値のパターンをチェックします。
<input data-pattern="^[0-9]{2,4}\-[0-9]{2,4}\-[0-9]{2,4}$" /> <!-- 電話番号の簡易チェック -->
size
値の大きさをチェックします。プロパティまたは配列の数をチェックすることができます。
<input data-size="2,5" /> <!-- 2〜5個の選択が可能 -->
customFunc
関数を指定します。第一引数に値がくるので、trueを返せば検証OKです。
<input data-customFunc="myFunc" />
検証パターンを使いこなせば、複雑な入力チェックの仕組みも簡単に実現できます。HTMLタグ上であればメンテナンスもしやすいので、誰でもすぐに変更できるようになるでしょう。
APAC最大規模のオープンソース・ソフトウェアカンファレンス、FOSSASIAが3月17〜19日、シンガポールにて開催されました。
その2日目、18日にhifiveの登壇をしてきました。

内容としては日本の大企業におけるシステム開発の現状とhifiveによる課題の解決です。社内システムというのは一度稼働し始めると5〜15年くらいの稼働が求められます。そうした時に今時のWebフレームワークではあっという間にトレンドが変わってしまいます。そこで作られているのがhifiveです。
hifiveはHTML5 Webフレームワークの他、開発を補助するツールとPitaliumなどのソフトウェアからなるプラットフォームになります。Pitaliumはスクリーンショットを撮影して、差分を可視化することでWebブラウザでのテストが簡単になるソフトウェアになります。
APACとあってオフショアなどの話は興味を持ってもらえたようです。ただ、日本独自の事情というのは分かりづらかったかと思います。とは言えhifive自体は日本に限らず利用していけるソフトウェアになりますので、今後も英語圏に向けて情報発信していこうと考えています。
hifiveが提供している業務システム開発で使えるUIライブラリの紹介です。今回はタイルコンテナを紹介します。タイルコンテナはドラッグ&ドロップで互いの位置を入れ替えるようなコンテナになります。
動作デモはこちらで確認できます。使ってみているところは下の画像を参照してください。

使い方
まず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
| <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> |
そして全体を覆っているクラスに対して h5.ui.components.tileContainer.tileContainerController を適用します。
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.core.controller('.columns', h5.ui.components.tileContainer.tileContainerController); |
後はデザインですが、例えば次のようにします。
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
| .box_content { | |
| border: 2px solid #000; | |
| padding: 5px; | |
| border-radius: 5px; | |
| margin: 5px; | |
| height: 200px; | |
| width: 300px; | |
| } | |
| .box_content h1 { | |
| font-size: 1.2em; | |
| color: #ffffff; | |
| background-color: #797979; | |
| height: 30px; | |
| } | |
| .column2 { | |
| width: 620px | |
| } |
これだけでドラッグ&ドロップでタイルを移動できる機能ができあがります。
動作デモはこちらで確認できます。ダッシュボード系サービスなどで使ってみてください。
Webフロントエンド開発を行っていると、手元の環境でさくっとHTTPサーバを立ち上げたいと思うことがあるかと思います。専用のソフトウェアを使うのも良いですが、ダウンロードするのさえ億劫です。
そこで各種言語、ワンライナーで実行できるHTTPサーバをまとめて紹介します。今回はライブラリなどを用意せずに実行できるものに限っています。
Ruby
まずはRubyから。2つ方法があります。
ruby -rwebrick -e'WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd).start'
# または
ruby -run -ehttpd . -p8000
個人的には上の方法が好みで、aliasでwebsコマンドとして登録しています。でも下の方がシンプルで分かりやすいですね。
Python
Python 2系の場合、
python -m SimpleHTTPServer 8000
が有名ですが、3系の場合
python -m http.server 8000
と実行するようになっています。
PHP
PHPは5.4以上からビルトインWebサーバが入っています。
php -S 127.0.0.1:8000
IIS Express
恐らくVisual Studioなどをインストールすると追加でインストールされるIIS Expressですが、コマンドプロンプトから利用ができます。
C:\> "C:\Program Files (x86)\IIS Express\iisexpress.exe" /path:C:\MyWeb /port:8000
pathはWebのルート、portがポート番号です。その場で使うだけであれば便利ですね。
その他の言語
node.js、Perlについてはライブラリをインストールすれば使えますが、デフォルトのままでは方法がなさそうでした。
個人的によく使うのはRuby/Pythonのワンライナーですが、PHPも-Sオプションだけなので手軽に使えそうです。いずれもデフォルトでは入っていないWindowsであればIIS Expressを使った方法をコマンドプロンプトファイルにしておくと便利そうです。
皆さんの開発環境でも使ってみてください。
hifiveで提供しているUIライブラリの一つ、右クリックメニュー(コンテクストメニュー)の使い方を紹介します。
まずはサンプルです。

任意のDOM以下に対して右クリックメニューを有効にしたり、メニュー内容の切り替えもできます。
動作しているサンプルはこちらで確認できます。
複雑な処理も可能ですが、今回は簡単に実装できる方法を紹介します。
必要なライブラリ
今回のメニュー表示はhifive本体の他、次のライブラリが必要になります。
作り方
まずHTMLですが次のように記述します。この .contextMenuBox 以下に対して右クリックメニューが有効になります。そして、メニューとして表示する内容は対象になるDOM以下に記述します。今回は .contextMenu 以下の内容になります。
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="contextMenuBox"> | |
| <ul class="dropdown-menu contextMenu" role="menu" aria-labelledby="dLabel"> | |
| <li><a tabindex="-1" href="#">Action</a></li> | |
| <li><a tabindex="-1" href="#">Another action</a></li> | |
| <li><a tabindex="-1" href="#">Something else here</a></li> | |
| <li class="divider"></li> | |
| <li><a tabindex="-1" href="#">Separated link</a></li> | |
| <li class="dropdown-submenu"> | |
| <a tabindex="-1" href="#">More options</a> | |
| <ul class="dropdown-menu"> | |
| <li><a tabindex="-1" href="#">Second level link</a></li> | |
| <li><a tabindex="-1" href="#">Second level link</a></li> | |
| <li><a tabindex="-1" href="#">Second level link</a></li> | |
| <li><a tabindex="-1" href="#">Second level link</a></li> | |
| <li><a tabindex="-1" href="#">Second level link</a></li> | |
| <li class="dropdown-submenu"> | |
| <a tabindex="-1" href="#">More options</a> | |
| <ul class="dropdown-menu"> | |
| <li><a tabindex="-1" href="#">Third level link</a></li> | |
| <li><a tabindex="-1" href="#">Third level link</a></li> | |
| <li><a tabindex="-1" href="#">Third level link</a></li> | |
| <li><a tabindex="-1" href="#">Third level link</a></li> | |
| </ul> | |
| </li> | |
| </ul> | |
| </li> | |
| </ul> | |
| </div> |
そして、JavaScriptは次のように記述します。h5.ui.ContextMenuController を指定するだけで完了です。これで .contextMenuBox に対して右クリックメニューが有効になります。
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 contextMenuTestController = { | |
| __name: 'ContextMenuTestController', | |
| contextMenuController: h5.ui.ContextMenuController, | |
| __ready: function(context) { | |
| }, | |
| }; | |
| h5.core.controller('.contextMenuBox', contextMenuTestController); | |
| }); |
さらにメニューを選択した際のイベントを管理したい場合はコントローラ内で次のように記述します。DOMが取れますので自由に処理ができるでしょう。
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
| 'a click': function(context, $el) { | |
| // イベント処理 | |
| $("body").append($el.text() + "が選択されました<br />"); | |
| } |
さらに複数のDOMについて管理したり、メニューの内容をダイナミックに変更したりするサンプルは右クリックメニューをご覧ください。ごく簡単に右クリックメニューが実現できますので、UI/UXの向上に役立ててください。