[FORM USABILITY 01]細部にこだわるコーディングで操作性を高める
ここからは、ユーザビリティの高い入力フォームをどのように実装するのか、ソースコードを見ながら解説していく。使い勝手のいいフォームを実装するには、地味な部分に少しの手間をかけることが重要だ。なお、ここで用いるコードはEDIMOのサイトで実際に使われているものを、今回の執筆に合わせてアレンジしたものである。
ブラウザのバリデーションを停止する
JSで独自のバリデーション機能を実装したい場合は、ブラウザ側が標準で備えているバリデーション機能を停止させる必要がある。そこで、form要素にnovalidate属性を付与する。
label要素でクリックエリアを広げる
input要素の入力エリアは比較的広い。しかし、マウス操作が難しいユーザーや、スマートフォンなどで閲覧するユーザーからすると、十分なエリアが確保できているとは言えない。そこで、label要素を利用する。
通常、label要素は、checkboxやradioボタンのクリックエリアを広げる目的で使われることが多い。今回のフォームでは各入力項目のラベル部分に対してlabel要素を用いて、クリックエリアを広げている(01、02)。
<!-- 中略 -->
<label class="form-table-text" for="js-form-company" onclick="">
会社名
<span class="mark">任意</span>
</label>
<!-- 中略 -->
<input class="input" id="js-form-company" type="text" placeholder="株式会社LIG" name="company" data-key="company">
<!-- 中略 -->
01 HTMLの抜粋(sample/index.html)。このようにfor属性とid属性をひも付けておくことで、label要素部分がクリックされたときもinput要素にフォーカスが当たるようになる。また、一部のタブレットとスマートフォンではlabel要素に対してタッチイベントを検知できないことがあるので、それを回避するためにすべてのlabel要素にonclick属性も設定している
02 label要素でクリックエリアを確保
各項目のラベル部分をクリックすると、入力欄にフォーカスされるようにしている
type属性で入力しやすくする
input要素の属性で特に重要なのはtype属性だ。HTML5ではtype属性のバリエーションが豊富になり、メールアドレス入力用の「type="email"」や電話番号入力用の「type="tel"」などがある。これらの属性を項目内容に応じて使い分ければ、ユーザーがデータを入力する際の助けとなる(03)。
03 type属性に対応したスマホ での入力の様子
電話番号欄では、入力キーが電話番号仕様になった状態から入力できる(図は、iOS9&Safariでの画面)
textarea要素に文字数制限を設定する
textarea要素にはinput属性に設定した属性のほか、maxlength(最大入力可能文字数)とminlength(最小入力可能文字数)の属性も加えた。これにより、ユーザーは設定された文字数の範囲内でしか入力できないため、長文による迷惑メールに対する防止にもなる(04)。
04 テキストエリアでの文字数制限
maxlengthを「3000」に設定しており、3,001文字以上は入れられないようになっている
[FORM USABILITY 02] jQueryで簡易的なバリデーション機能を実装する
続いて、「必須項目が未入力のときはエラーを表示し、すべての必須項目が入力されたら送信ボタンが有効になる」という簡易的なバリデーション機能を追加する。この機能をJavaScriptで実装することで情報が入力されたタイミングでエラーの有無を返すことができるため、スムーズにユーザーを送信まで導くことができる。
(function () {
'use strict';
var $form = $('#js-form'),
$data = $form.find('.js-require'),
$button = $form.find('.button');
// ↓--------------------------------------------------↓ F
var validations = {
user: false,
comment: false
}
// ↑--------------------------------------------------↑ F
// ↓--------------------------------------------------↓ A
function setError(elm){
elm.addClass('is-error');
}
// ↑--------------------------------------------------↑ A
// ↓--------------------------------------------------↓ B
function removeError(elm){
elm.removeClass('is-error');
elm.addClass('is-success');
}
// ↑--------------------------------------------------↑ B
// ↓--------------------------------------------------↓ C
function keyHandler(self){
var dataKey = self.data('key');
var $target = $('#js-form-' + dataKey);
var val = self.val();
if(val === ""){
setError($target);
} else {
removeError($target);
}
}
// ↑--------------------------------------------------↑ C
// ↓--------------------------------------------------↓ D
function checkValidations(self) {
var dataKey = self.data('key');
var key = self.attr('id').substr(8);
var val = self.val();
if(val === ""){
validations[key] = false;
} else {
validations[key] = true;
}
}
// ↑--------------------------------------------------↑ D
// ↓--------------------------------------------------↓ E
function allowButton(){
if(validations.user === true &&
validations.comment === true
){
$button.removeClass('is-disable');
} else {
$button.addClass('is-disable');
}
}
allowButton();
// ↑--------------------------------------------------↑ E
// ↓--------------------------------------------------↓ G
$data.on('change keyup focusout', function(){
keyHandler($(this));
checkValidations($(this));
allowButton();
});
// ↑--------------------------------------------------↑ G
})();
01 JavaScript(sample/assets/form.js)
エラー時の処理を用意する
まずは、エラー時に入力欄の見た目が変わるように、JS側でclass属性を付与する関数setError(A)を用意する。後ほど詳しく解説するが、任意のタイミングで呼び出され、class属性「is-error」を付与し、入力欄をオレンジ色にする。
エラー解除時の処理を用意する
次に、入力欄に情報が問題なく入力された際、エラーのスタイルを解除し、成功したとき用のclass属性を付与する関数removeError(B)を用意する。任意のタイミングで呼び出され、class属性「is-error」を外して、class属性「is-success」を付与し、入力欄の見た目を変える。
バリデーションを行いclass属性を付与する
続いて、入力欄に情報が入力された際、それをエラーと見なすかどうかの判定を行う関数KeyHandler(C)を用意する。今回は「必須項目に情報が入力されているかいないか」のみの判定を行っている。具体的には、入力欄に何も情報が入力されていなければ関数Aを呼び、入力されていれば関数Bを呼ぶという仕組みだ。
バリデーションを行い内部的なチェックを行う
内部チェックを行う関数checkValidations(D)を用意する。ロジックは関数Cとほぼ同じだが、ここではすべての必須項目の入力状況を調べ、エラーの有無をオブジェクト「validations」に記録している(F)。この関数Dは後の関数Gで使う。
ボタンの有効化・無効化を行う
さらに、ボタンが押せるかどうかの関数allowButton(E)を用意する。内部的なバリデーションを行う関数Dによって、全入力欄が問題なしと判定されればボタンが有効化され、
エラーが残っていれば無効化される。
関数実行のタイミングを設定する
最後に、これまでに用意した関数を呼び出すタイミングの命令を記述する(G)。今回は3つのイベント「change」「keyup」「focusout」を設定した。こうしておけば、ユーザーがデータを入力しているタイミングで関数が実行され、リアルタイムにバリデーションを行える。
Text:尾谷真希子
デザイナー。京都工芸繊維大学を卒業後、グラフィックデザインやコピーライティングの仕事を経て、WebサイトやアプリなどのUIデザインに携わる。2015年、株式会社LIGに入社。
Text:堀口誠人
フロントエンジニア。ずっと日本で暮らしたかったため、ベトナム出張のあるWeb制作会社の内定を辞退し、2012年に株式会社LIGに入社。2015年、フィリピンに派遣される。 http://liginc.co.jp/