Lambdaカクテル

ウェブアプリケーションエンジニアです.玉石混淆です.

keydown,keypress,keyup,inputについての補習

ふだんなんとなく使っているけれど詳しいことは知らない,そんなものの代表格であるこいつらについて,一度きちんと勉強しなくてはならないと薄々考えていたので補習することにした. 学習のまとめがこの文書である.

CAVEAT: 以下の内容は基本的な挙動であり,ブラウザによって挙動が変化することがある.これは公式ドキュメントではなく,誤記が含まれているおそれがあり,その他いかなる内容も保証しない.

keydown,keypressed,keyup

これらは全てイベント(KeyboardEvent)である.

overview

attribute: charkey

いずれのイベントでもchar(string)そしてkey(string)を読むことができる. 押下されたキーが印字可能な文字に対応するとき,charはその文字を含むunicode文字列であり,keyもこれと等しい文字列である.キーに印字表現がないときは,charは空文字列であり,キーを表現する文字列が定義されているときはkeyはその文字列であり,さもなくばkey"Unidentified"である.keyがとりうる値はMDNのドキュメントで確認できる. charkeyはいずれもreadonlyである.

deprecated attribute: charCodekeyCode

いずれのイベントでもcharCodekeyCodeを読むことができるが,これらはdeprecatedになっており,可能な限りcharkeyを使わなければならない.複数文字を入力するマクロとしてキーが使われた場合,charは最初の1文字ではなく入力文字列全てになる.

modifiers

いずれのイベントでも,ctrlKeyshiftKeyaltKeymetaKey(いずれもboolean)を読むことで,イベント発火時に押下されていた修飾キーを識別できる.

auto-repeat

オートリピート時には,基本的にkeydownkeypressが繰り返し発火され,キーを離したタイミングでkeyupが発火する.ただし環境によってはkeydown, keypresskeyupが繰り返し発火される(実際に連打しているように見える)ため注意する.

keydown

キーが押し込まれたときに発火する.

keypress

キーが押し込まれ,そのキーが文字を生成するときに限って発火する.DOM L3仕様により順序はkeydownの後である.

DOM L3でdeprecatedになっており,代替として(よりアクセシビリティの面でも優れる)HTML5 inputを使うことが推奨される. Chromeは,一定のショートカットにおいてこのイベントを発火しない.ショートカットを実装したい場合はkeydownを使う.

keyup

キーが離されたときに発火する.

input

<input>または<select><textarea>の値(value属性)が変化したときに発火する.つまり,直接変化させた場合でなくとも発火するので,入力支援のために使用するときは注意して扱うべき*1イベントである.さらに(名称からすると非直感的ではあるが)<input>のうちtype=checkboxまたはtype=radioはユーザがクリックしたときvalue属性が変化しないため,このイベントを発火しない.

キーボードではない手段(音声入力など)によって値が変化したときにも発火するため,アクセシビリティの面で優れている.

InputEventを継承しているため,data属性を通じて挿入された文字列を取り出すことができる.また,文字列の挿入を伴わない変化(文字の削除など)によって発生したイベントによるものであるときは,dataは空文字列である. したがって,このイベントはあらゆるキーの検出には向かない.

またInputEventにはisComposing属性があり,音声認識中や漢字変換を行っているかどうかを判別することができる.

まとめ

  • charCodekeyCodeは新規プロダクトでは避け,charまたはkeyを使わなければならない.
  • アクセシビリティ確保の観点から,keypressよりもinputを積極的に使いたい.
  • 単純なショートカットの実装にはkeydownを使うべきである.
    • submitショートカットとして使う場合はkeyupを使い,変換完了を待つ必要がある.
  • ラジオボタンチェックボックスについては,inputではなくchangeを使わなければならない.
  • 入力支援のためにinputを使うときは,入力検知が際限なくループするのを防ぐために適切な状態管理が必要である.

参考文献

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

https://www.w3.org/TR/DOM-Level-3-Events/#keys

*1:つまり変化が変化を発生させうるため,停止しない状態を作り出せてしまうことに留意すべき