ケーススタディ:入力値チェック#1
ここまででもかなりのボリュームとなってしまいましたが,
今回は,
フォームのHTML
<form id="userform" name="userform" action="" method="post">
<fieldset>
<legend>ユーザー登録</legend>
<p>
<label for="username">ユーザー名</label>
<input type="text" name="name" value="" id="username" class="text" required="required">
</p>
<p>
<label for="useremail">メールアドレス</label>
<input type="text" name="email" value="" id="useremail" class="text" required="required">
</p>
<p>
<label for="userpass">パスワード</label>
<input type="password" name="pass" value="" id="userpass" class="text" required="required">
</p>
<p>
<label for="userpass_sub">パスワード(確認)</label>
<input type="password" name="pass2" value="" class="text" id="userpass_sub">
</p>
<p class="submit">
<input type="submit" id="usersubmit" value="送信" class="button" id="usersubmit">
</p>
<p id="errors"></p>
</fieldset>
</form>
まず,
送信ボタンを押した際に,
jQueryを使った実装
jQuery(function($){
//htmlの構築を待つ
var query = '#userform input:text,#userform input:password';
var $inputs = $(query).focus(function(evt){
$(this).css('background','white');
// inputにフォーカスしたとき背景色を白に戻す
}); // input要素はキャッシュしておく
var message = {name:'ユーザー名',email:'メールアドレス',pass:'パスワード'};
var $password = $('#userform input:password');
$('#userform').submit(function(evt){ // 送信時の処理
var isError = false, errors = [];
var noBlank = ($inputs.filter(function(i,input){
// requiredになっていて,値が入力されてないinputをフィルタリング
return input.required && !input.value && errors.push(message[input.name]);
// エラーメッセージ用に空だったinputに対応するメッセージを取得
}).css('background','#ffff66').eq(0).focus().size() === 0);
// フィルタされた要素について背景色を黄色にして1つ目の要素にフォーカスをあてる,
// その時の要素数が0でなければ空のinputがあったとみなす
var pass = $password.map(function(i,v){return v.value});
// passwordの値を取得して配列に入れる
var matchedPass = pass[0] === pass[1];
// パスワードの一致を確認
if (noBlank && !matchedPass) {
// 入力漏れがなくて,パスワードが一致しない場合
$password.css('background','#ffff66').eq(0).focus();
$('#errors').text('パスワードが一致していません');
isError = true;
}
if (errors.length) { // エラーメッセージが存在する場合
$('#errors').text(errors.join(',')+'は必須です');
isError = true;
}
if (isError) {
$('#errors').show().delay(3000).hide('fast');
//エラーメッセージを表示して,3秒後に隠す
}
return noBlank && matchedPass;
});
});
やや強引ですが,
続いて,
ライブラリを使わない入力値チェック実装
(function(){
var addEvent;
if(document.addEventListener) {
addEvent = function(node,type,handler){
node.addEventListener(type,handler,false);
};
} else if (document.attachEvent) {
addEvent = function(node,type,handler){
node.attachEvent('on' + type, function(evt){
handler.call(node, evt);
});
};
} else {
addEvent = function(node,type,handler){
var _handler = node['on' + type];
node['on' + type] = function(evt){
if (_handler) {
_handler.call(node, evt||window.evt);
}
handler.call(node, evt);
};
};
}
var message = {name:'ユーザー名',email:'メールアドレス',pass:'パスワード'};
addEvent(window,'load',function(){
var form = document.getElementById('userform');
var errorNode = document.getElementById('errors');
var inputNodes = form.getElementsByTagName('input');
var passwords = [];
var timer;
for (var i = 0, inputsLen = inputNodes.length;i < inputsLen; i++){
var input = inputNodes[i];
if (input.type === 'text' || input.type === 'password') {
addEvent(input,'focus',function(){
this.style.background = 'white';
});
if (input.type === 'password') {
passwords.push(input);
}
}
}
addEvent(form,'submit',function(evt){
var noBlank = true;
var errors = [];
for (var i = 0;i < inputsLen; i++){
var input = inputNodes[i];
if (input.getAttribute('required') && !input.value) {
input.style.background = '#ffff66';
if(noBlank) {
input.focus();
noBlank = false;
}
errors.push(message[input.name]);
}
}
var matchedPass = passwords[0].value === passwords[1].value;
if (noBlank && !matchedPass) {
passwords[0].focus();
passwords[1].style.background = '#ffff66';
errorNode.innerHTML = 'パスワードが一致していません';
}
if (!noBlank) {
errorNode.innerHTML = errors.join(',')+'は必須です';
}
if (!noBlank || !matchedPass) {
if (evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
errorNode.style.display = 'block';
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function(){
errorNode.style.display = 'none';
timer = null;
}, 3000);
}
});
})
})();
一気に80行ほどのコードになってしまいました。こちらを順に解説していきます。