ふだんなんとなく使っているけれど詳しいことは知らない,そんなものの代表格であるこいつらについて,一度きちんと勉強しなくてはならないと薄々考えていたので補習することにした. 学習のまとめがこの文書である.
CAVEAT: 以下の内容は基本的な挙動であり,ブラウザによって挙動が変化することがある.これは公式ドキュメントではなく,誤記が含まれているおそれがあり,その他いかなる内容も保証しない.
keydown,keypressed,keyup
これらは全てイベント(KeyboardEvent)である.
overview
attribute: char,key
いずれのイベントでもchar(string)そしてkey(string)を読むことができる.
押下されたキーが印字可能な文字に対応するとき,charはその文字を含むunicode文字列であり,keyもこれと等しい文字列である.キーに印字表現がないときは,charは空文字列であり,キーを表現する文字列が定義されているときはkeyはその文字列であり,さもなくばkeyは"Unidentified"である.keyがとりうる値はMDNのドキュメントで確認できる.
charとkeyはいずれもreadonlyである.
deprecated attribute: charCode,keyCode
いずれのイベントでもcharCode,keyCodeを読むことができるが,これらはdeprecatedになっており,可能な限りcharかkeyを使わなければならない.複数文字を入力するマクロとしてキーが使われた場合,charは最初の1文字ではなく入力文字列全てになる.
modifiers
いずれのイベントでも,ctrlKey,shiftKey,altKey,metaKey(いずれもboolean)を読むことで,イベント発火時に押下されていた修飾キーを識別できる.
auto-repeat
オートリピート時には,基本的にkeydown,keypressが繰り返し発火され,キーを離したタイミングでkeyupが発火する.ただし環境によってはkeydown, keypress,keyupが繰り返し発火される(実際に連打しているように見える)ため注意する.
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属性があり,音声認識中や漢字変換を行っているかどうかを判別することができる.
まとめ
charCode,keyCodeは新規プロダクトでは避け,charまたはkeyを使わなければならない.- アクセシビリティ確保の観点から,
keypressよりもinputを積極的に使いたい. - 単純なショートカットの実装には
keydownを使うべきである.- submitショートカットとして使う場合は
keyupを使い,変換完了を待つ必要がある.
- submitショートカットとして使う場合は
- ラジオボタンとチェックボックスについては,
inputではなくchangeを使わなければならない. - 入力支援のために
inputを使うときは,入力検知が際限なくループするのを防ぐために適切な状態管理が必要である.
参考文献
https://www.w3.org/TR/DOM-Level-3-Events/#keys
*1:つまり変化が変化を発生させうるため,停止しない状態を作り出せてしまうことに留意すべき