テキストエリアでリターンキーを押した際に、submitイベントの発生を抑止する方法

テキストエリアでのリターンキーで、submitイベントが発生しないようにする場合、ブラウザ毎にどのような処理を書けばいいのか調べてみました。(submitイベント自体に処理を追加せずに、テキストエリアでのイベントで制御したかったので)

テキストエリアでのリターンを拾えるイベントとしては、下記の3つがあります。

  • keypress
  • keydown
  • keyup

イベントをキャンセルする方法は、IEのJScriptの実装と、DOM 2のEventモデルでの実装である下記の2パターンを試しました。

  • event.preventDefault()
  • event.returnValue=false

そして確認の結果、上記のイベント×キャンセル処理の組み合わせでsubmitイベントがキャンセル出来るのは、下記のパターンとなりました。

  • IE 6
    • keydown - event.returnValue=false
    • keypress - event.returnValue=false
  • FireFox 1.5
    • keydown - event.preventDefault()
    • keypress - event.preventDefault()
  • Opera 8.5
    • keypress - event.returnValue=false
    • keypress - event.preventDefault()

クロスブラウザを考慮する場合、キャンセル処理はどうしてもブラウザの違いを考慮して処理を分けざるをえません。(イベントはkeypressで統一できるが)
そのため、クロスブラウザを考慮した上でのsubmitのキャンセル処理は、下記のようになります。(OperaもOK)

function enterCancel(evt){
  if (evt.keyCode == 13) {
    if (evt.preventDefault) {
      evt.preventDefault();
    } else {
      evt.returnValue = false;
    }
  }
}
<input type="text" name="text" onkeypress="enterCancel(event||window.event);">

これを、prototype.jsのEvent.observeとEvent.stopというクロスブラウザを考慮したメソッドを使って実装しようとした場合、下記のように書くことができます。(これだとOperaダメ)

Event.observe($('hoge'), 'keypress',
              function(event){
                if (event.keyCode == Event.KEY_RETURN) Event.stop(event);
              }, false);
<input type="text" id="hoge" name="text">

コードがシンプルになるので、prototype.js使った方がいい!と思われるかと思いますが、Operaでうまく動きません…
というのも、Event.observeとEvent.stopObservingでkeypressを指定した場合、Operaだとkeydownに変更して扱われてしまうためです。詳しくは、前回のエントリを御参照ください。

今回調べていて、Operaが、event.returnValue=false、event.preventDefault()の両方を実装しているのには驚きました。
Operaでは、element.attachEvent、element.addEventListenerも両方実装されており、IEとFireFoxのどちらとも互換性を保てるようにしようとされているのかもしれません。

それにしても、prototype.jsOperaでkeypressの扱いがおかしい気がしてならないのは、私だけでしょうか…