これでできる! クロスブラウザJavaScript入門

第1回 ウェブブラウザとJavaScriptの未来

この記事を読むのに必要な時間:およそ 10.5 分

続いて,submit時の処理を実装します。submit時に空の要素や,パスワードが一致しない場合はsubmitを止めなければいけません。IE以外のブラウザはEventオブジェクトのpreventDefaultメソッドを呼び出すと,デフォルトの動作をキャンセルできます。submitイベントをpreventDefaultすればsubmitを止めることができますし,clickイベントをpreventDefaultすればクリックされなかったことにできます。IEの場合,EventオブジェクトのreturnValueプロパティの値をfalseに設定することで同様の動作が可能です。なお,ここでキャンセルができるのはキャンセルが可能と定義されたイベントのみで,loadイベントなどはキャンセルすることはできません。

submitイベントとキャンセル

addEvent(form,'submit',function(evt){
  var noBlank = true;
  var errors = [];
  /* 中略 */
  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);
  }
});

エラーメッセージを表示し(errorNodeはCSSで非表示にしておきます⁠⁠,setTimeoutで3秒後に非表示に戻します。3秒経過する直前に再びエラーを出すと,2度目のメッセージのほうを非表示にしてしまうので,先のtimerが残っている場合は明示的にクリアするようにしています。

では,必須要素のチェックに入ります。

必須項目の値チェック

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]);
  }
}

input.getAttributeでrequiredの値が空でなく(requiredが設定されているかのチェック⁠⁠,input.valueが空の場合に,inputの背景色を黄色に変えています。さらに,その時点でnoBlankフラグがtrueであれば,それが最初に空だった要素なので,その要素にfocusしつつ,noBlankをfalseにしています。同時に空だった要素に対応するエラーメッセージを配列に入れておきます。

先ほど配列に入れておいたpasswordの値が一致しているかチェックします。

パスワードのチェック

var matchedPass = passwords[0].value === passwords[1].value;
if (noBlank && !matchedPass) {
  passwords[0].focus();
  passwords[1].style.background = '#ffff66';
  errorNode.innerHTML = 'パスワードが一致していません';
  isError = true;
}
if (!noBlank) {
  errorNode.innerHTML = errors.join(',')+'は必須です';
}

空の要素がある場合はそちらのメッセージを優先しています。errorNodeにinnerHTMLでメッセージを挿入しています。テキストの書き換えなので,なるべくならテキストのみを許容する処理を行いところですが,innerText(Firefoxで使えない)やtextContent(IEで使えない)はブラウザ依存があり,createTextNodeを使った場合は以下のように処理が煩雑になります(errorNodeに子要素が1つしかないことを前提としているので,より汎用的にするにはさらに実装が必要です⁠⁠。

テキストノードの挿入

  var textNode = document.createTextNode('パスワードが一致していません');
  if (errorNode.firstChild) {
    errorNode.replaceChild(textNode, errorNode.firstChild);
  } else {
    errorNode.appendChild(textNode);
  }

少々長くなりましたが,以上で今回の解説は終わりです。

まとめ

初回限定の増量キャンペーンでお送りしましたがいかがでしたでしょうか? 次回からはもう少しライトな内容にシフトする予定です。

なお,後半のjQuery版とjQuery不使用版は細かい動作が異なっています。次回以降,アニメーションなどの細かい動作も詰めてきますので,ご期待ください。

著者プロフィール

太田昌吾(おおたしょうご,ハンドルネーム:os0x)

1983年生まれ。JavaScriptをメインに,HTML/CSSにFlashなどのクライアントサイドを得意とするウェブエンジニア。2009年12月より、Google Chrome ExtensionsのAPI Expertとして活動を開始。

URLhttp://d.hatena.ne.jp/os0x/