Webページでのテキストフィールド移動

同じことで何度も悩んでしまったので、ちゃんとまとめて書いておこう。タイトルだけでは何の意味かわからないですが、具体的には、ログインパネルのユーザ名とパスワードと思ってください。通常、ユーザ名を入力してEnterキーを押すと、パスワードのフィールドに自動的に移動したいですよね。ということで、ユーザ名のテキストフィールドをuserBox、パスワードのテキストフィールドをpasswordBoxで参照しているとして、まあ、例えば、こんなプログラムを組みます。イベント設定はいろんな方法があるのでそこは置いといて、keydownイベントが来て、押されたキーがEnterあるいはNumpadEnterなら、パスワードボックスに飛びます。

userBox.onkeydown = function (event) {
  if (event.code === 'Enter' || event.code === 'NumpadEnter') {
    passwordBox.focus()
  }
}

しかし、これだと、Macではおかしな動作が発生します。かな漢字変換途中の文字列でEnterを押すと、確定した文字列がユーザ名だけでなく、パスワード側にも入るのです。つまり、Enterによる確定でユーザ名に確定した文字列が入るのですが、同時に変換途中の状態でパスワード側にフォーカスが移動して、そこでもやっぱり確定されて、両方のフィールドに文字が入ってしまうようなのです。Windowsでは、どうなっているのかというのはちょっと説明しづらいですが、あまりいい感じではありません。

そこで、いろいろ調べると、EventクラスにisComposingというプロパティがあって、変換途中ならtrueになることがわかりました。ということで、結論としてはこのようにisComposingを考慮すればいいということになります。つまり、Enterキーを押しても、変換途中ならばパスワードフィールドへの自動移動をしないということです。

userBox.onkeydown = function (event) {
  if ((event.code === 'Enter' || event.code === 'NumpadEnter')
      && !event.isComposing) {
    passwordBox.focus()
  }
}

ちなみに、caniuse.comによると、isComposingはモダンなブラウザならどれもサポートしているので安心して使えます。