リアルタイム入力チェックは今のWEBページでは割りと標準化されつつあるけど、
ライブラリを選定したり、画面の表示を考えたりと何かと面倒。
HTML5の機能で追加されたバリデーション機能を利用すればそういった煩わしさから開放されるのでは?
と思いたち、外部ライブラリを一切使わずにリアルタイム入力チェックを実装してみた。
コード
<section>
<form id="sampleForm">
<label>
半角英数字以外を入力してみよう
<input
type="text" id="input" placeholder="半角英数字で入力"
pattern="^[0-9A-Za-z]+$" required>
</label>
<button type="submit" id="submit">送信</button>
</form>
</section>
<script>
"use strict";
var form = document.getElementById("sampleForm"),
input = document.getElementById("input"),
submit = document.getElementById("submit");
input.addEventListener("input", function() {
if (!input.value) {
input.setCustomValidity("");
submit.click();
return;
} else if (false === form.checkValidity()) {
input.setCustomValidity("半角英数字以外の値が入力されました。");
submit.click();
return;
}
input.setCustomValidity("");
});
</script>
何をしているか?
- inputボックスに入力があるたびに、formの妥当性を
form.checkValidity()
を見て検証 - 検証結果が
false
だったらformをsubmitしてブラウザのバリデーションを実行 -
setCustomValidity
を利用して独自のメッセージを設定
ちょっとハマった
formのsubmitを行うとき、form.submit()
で実行出来るだろうと思っていたのだが、
Uncaught TypeError: Property 'submit' of object #<HTMLFormElement> is not a function
と言われてしまう(chromeのコンソールの場合)。
これはform中にsubmit要素を持ったbuttonがあるため、formにsubmitプロパティが提供されなくなってしまったためだ。
そこでsubmitボタンを削除して、form.submit()
してみたが、今度はHTML5のバリデーションが実行されずにリクエストが送信されてしまった。
どうしたものかと思い、submitボタンを再度つけて、submit.click()
でプログラム中からsubmitボタンをクリックしてあげることで解決した。
仕様を読んでいないので予測なのだけど、
上記のことから、HTML5のバリデーションはsubmitボタンのclickイベントから起動しているのではないのかな?
まとめ
とても手軽にリアルタイム入力チェックが実装出来ますね。
実際の入力値のチェックはサーバサイドで行うものですし、
HTML5に対応していないブラウザは気にしない!と判断してシステムを作る場合、有効に活用出来るような気がしています。
まとめを書いた後に実用を兼ねて機能を強化してみた(追記)
そういえば、復数入力欄があるのが普通だよなと思って実用を兼ねたコードを書いてみた
実用を考えたコード
<meta charset="utf8">
<section>
<form id="sampleForm">
<label>
半角英数字以外を入力してみよう
<input
type="text" class="validate" id="input" placeholder="半角英数字で入力"
pattern="^[0-9A-Za-z]+$" required data-validity-msg="半角英数字のみで入力して下さい。">
</label><br>
<label>
メールアドレスしかダメです
<input
type="email" class="validate" id="email" placeholder="メールアドレスを入力"
required data-validity-msg="メールアドレスの形式で入力して下さい。">
</label><br>
<button type="submit" id="submit">送信</button>
</form>
</section>
<script src="html5_validation.js">
(function() {"use strict";
/**
* インプットボックスにvalidateイベントを設定
*/
function setValidate(e) {
var input = e.target;
// インプットボック全てにdisabled属性を付与後、
// イベントのあった要素のdisabled属性を削除してvalidate対象を限定する
elementsToAttribute(input_boxes, "disabled", "", function() {
input.removeAttribute("disabled");
input.setCustomValidity("");
if (true === input.hasAttribute("required") && !input.value) {
submit.click();
} else if (false === input.checkValidity()) {
input.setCustomValidity(input.getAttribute("data-validity-msg"));
submit.click();
}
elementsOutAttribute(input_boxes, "disabled");
});
}
/**
* 要素のリスト全てに属性を追加する
*/
function elementsToAttribute(elements, attr, val, cb) {
for (var i=0; i<elements.length; ++i) {
elements[i].setAttribute(attr, val);
}
if (cb) cb();
}
/**
* 要素のリスト全から属性を削除する
*/
function elementsOutAttribute(elements, attr, cb) {
for (var i=0; i<elements.length; ++i) {
elements[i].removeAttribute(attr);
}
if (cb) cb();
}
var submit = document.getElementById("submit"),
input_boxes = document.querySelectorAll(".validate");
for (var i=0; i<input_boxes.length; ++i) {
try {
input_boxes[i].addEventListener("input", setValidate);
} catch (e) {
console.log(e);
}
}
// end proc.
})();
実用を兼ねて変えたところ
- カスタムvalidityメッセージを
data-validity-msg
属性に設定するようにした - 入力した要素のみに
validate
を機能させたかったのでformの入力要素にdisabled
属性を与えた後に、入力のあった要素からdisabled
要素を削除するようにした。
実用を考えてみてのまとめ
更にケースを考慮すると、min
、max
、maxlength
などに対応するコードも必要になり、手軽感が更になくなります!!
全然気軽に書けないですね;;これならライブラリを活用したほうが…