6.10 キー入力イベント,changeイベント

(1/1)
パソコンのキーボードを打っているイラスト
イベントハンドラ - 5.2 プロパティ、メソッド、イベントハンドラ」で、JavaScriptでよく使うイベントハンドラを紹介した。
今回は、addEventListener メソッドを使って、キー入力イベントが発生したときにユーザー関数を実行するサンプルプログラムとタイピング練習プログラムを紹介する。また、changeイベントを使って年月日セレクタを作る。

目次

サンプル・プログラム

圧縮ファイルの内容
eventkey.htmlサンプル・プログラム(1) - キー入力イベントをみる
typing.htmlサンプル・プログラム(2) - タイピング練習プログラム
selectDate.htmlサンプル・プログラム(3) - 年月日セレクタ
eventkey.html 更新履歴
バージョン 更新日 内容
1.0.0 2023/05/01 初版
typing.html 更新履歴
バージョン 更新日 内容
1.0.0 2023/05/01 初版
selectDate.html 更新履歴
バージョン 更新日 内容
1.0.0 2023/12/29 初版

キー入力イベントをみる

イベントハンドラ - 5.2 プロパティ、メソッド、イベントハンドラ」で紹介したイベントハンドラと、今回紹介するイベントの種類の対応表を掲げる。
上述のサンプルプログラムは、3種類のキー入力イベントに対し、取得するタイミングと、取得できる2つの値(keycode)を表示するものである。
イベントハンドラ イベントの種類 イベント発生タイミング
onKeyDown keydown キーを押した時に発生
onKeyUp keyup 押していたキーをあげた時に発生
onKeyPress keypress キーを押してる時に発生
キー入力イベントをみる
たとえば A キーを押すと、keydownkeypress の列に値が入ってくる。そして、A キーを離すと、keyup に値が入る。これが、3種類のイベントが発生するタイミングの違いである。
キー入力イベントをみる
次に ShiftCtrl といった特殊キーを押してみてほしい。上図のように、keydownkeyup には値が入るが、keypress には入らないことが確認できる。ESCEnter も同様である。
これらのキー入力をキャッチしたいときは、keydownkeyup を使う。

取得できる2つの値 keycode だが、code は左右の特殊キーの違いまで取得できるが、key はそこまで識別ができないという違いがある。

キー入力イベントをみるプログラム

では、プログラムをみていくことにしよう。

  99: <table id="result">
 100: <tr>
 101: <th>イベント</th>
 102: <th>keydown</th>
 103: <th>keyup</th>
 104: <th>keypress</th>
 105: </tr>
 106: <tr>
 107: <th>key</th>
 108: <td id="keydown_key"></td>
 109: <td id="keyup_key"></td>
 110: <td id="keypress_key"></td>
 111: </tr>
 112: <tr>
 113: <th>code</th>
 114: <td id="keydown_code"></td>
 115: <td id="keyup_code"></td>
 116: <td id="keypress_code"></td>
 117: </tr>
 118: </table>

まず、取得した値を表示するTABLEを用意する。

  36: /**
  37:  * keydownイベントが発生したとき,keyとcodeの値を表示する.
  38:  * @param   Object e イベント
  39:  * @return  なし
  40: */
  41: function eventKeydown(e) {
  42:     document.getElementById('keydown_key').innerHTML  = e.key;
  43:     document.getElementById('keydown_code').innerHTML = e.code;
  44: }

  46: /**
  47:  * keyupイベントが発生したとき,keyとcodeの値を表示する.
  48:  * @param   Object e イベント
  49:  * @return  なし
  50: */
  51: function eventKeyup(e) {
  52:     document.getElementById('keyup_key').innerHTML  = e.key;
  53:     document.getElementById('keyup_code').innerHTML = e.code;
  54: }

  56: /**
  57:  * keypressイベントが発生したとき,keyとcodeの値を表示する.
  58:  * @param   Object e イベント
  59:  * @return  なし
  60: */
  61: function eventKeypress(e) {
  62:     document.getElementById('keypress_key').innerHTML  = e.key;
  63:     document.getElementById('keypress_code').innerHTML = e.code;
  64: }

次に、3つのイベント各々に対応するユーザー関数を用意する。引数 e は KeyboardEventオブジェクトである。このオブジェクトに keycode というプロパティが格納されており、それらをTABLEの指定した場所に書き込む。

  79:     //キー入力イベントをセットする.
  80:     document.addEventListener('keydown',  eventKeydown);
  81:     document.addEventListener('keyup',    eventKeyup);
  82:     document.addEventListener('keypress', eventKeypress);
  83: }

メインプログラムでは addEventListener を使い、先ほど定義した3つのイベント keyupkeydownkeypress に対応するユーザー関数を指定してやる。こうすることで、イベント発生時に指定したユーザー関数が自動的に呼ばれるようになる。
なお、keypress は非推奨となっており、いずれ言語仕様から外されることになっているが、ここでは説明のためにあえて残してある。後述するタイピング練習プログラムでは、keypress は使用しない。

タイピング練習プログラム

キー入力イベントを使って、タイピング練習プログラムを作ってみる。
画面に表示された問題文字列(英数字)と同じキーを入力し、両者が合致するかどうか、入力開始から終了までに要した時間(ミリ秒)を表示するプログラムである。
タイピング練習プログラム
コアになるのは、keydownイベント発生時に呼び出すユーザー関数 eventKeydown と、問題と入力文字列を比較して結果を表示するユーザー関数 evaluateString の2つだ。
タイピング練習プログラム

  73: /**
  74:  * 入力したキーを表示する.
  75:  * @param   Object e イベント
  76:  * @return  なし
  77: */
  78: function eventKeydown(e) {
  79:     //入力キーがCHARACTERSに含まれていれば処理する.
  80:     if (CHARACTERS.includes(e.key)) {
  81:         let str = document.getElementById('input').innerHTML;
  82:         str +e.key;
  83:         document.getElementById('input').innerHTML = str;
  84:         //問題と入力文字列を比較し,結果を表示する.
  85:         evaluateString();
  86:     //ESCキーが押下されたら初期化する.
  87:     } else if (e.key == 'Escape') {
  88:         initialize();
  89:     }
  90: }

ユーザー関数 eventKeydownは、引数で渡されたプロパティ e.key が、あらかじめ定義した定数 CHARACTERS に含まれているかどうか includesメソッドを使って調べる。定数 CHARACTERS は、このプログラムの冒頭の方で英数字の羅列となっている。
含まれていれば問題文字列にある文字として、HTMLのオブジェクト #input に、すでに表示してある入力文字列の末尾に1文字追加する形で表示する。
含まれていなければ、入力キーがESCキーかどうかを調べる。ESCキーだったら、表示を初期化するユーザー関数 initialize を呼び出す。

  73: /**
  74:  * 入力したキーを表示する.
  75:  * @param   Object e イベント
  76:  * @return  なし
  77: */
  78: function eventKeydown(e) {
  79:     //入力キーがCHARACTERSに含まれていれば処理する.
  80:     if (CHARACTERS.includes(e.key)) {
  81:         let str = document.getElementById('input').innerHTML;
  82:         str +e.key;
  83:         document.getElementById('input').innerHTML = str;
  84:         //問題と入力文字列を比較し,結果を表示する.
  85:         evaluateString();
  86:     //ESCキーが押下されたら初期化する.
  87:     } else if (e.key == 'Escape') {
  88:         initialize();
  89:     }
  90: }

ユーザー関数 evaluateStringは、まず、問題文字列と入力文字列の長さが一致するかどうかを調べる。一致しなければ入力中と判断し、何もせずに終了する。
一致していたら、現在時刻と計測開始時刻の差分(ミリ秒)を計算し、変数 diff に代入する。これがタイピング入力に要した時間である。
次に、問題文字列と入力文字列が一致するかどうかを調べる。一致していたらHTMLのオブジェクト #result に、OKと差分時間を表示する。一致しなければNGと差分時間を表示する。

年月日セレクタをつくる

ここでは、日付入力で使う年月日セレクタを作る。
セレクタはHTMLのselectタグを利用し、年や月の選択に応じて、うるう年や月の大小で、日数を自動的に変更し、矛盾した年月日が入力されないようにする。
年月日セレクタをつくる
プログラムの流れは上図の通りで、コアになるのは、年・月・日の3つのセレクタを生成する setSelector 関数である。
年は、引数で与えた year を含む前後5年分を。月は、1から12を。日は、月の大小とうるう年を判定して、適切な選択肢(最大値は 29, 30, 31のいずれか)をセットする。

メイン・プログラムでは、 addEventListenerメソッドを使い、年や月のセレクタでchangeイベントが発生したとき、setSelector 関数を走らせ、連動して日のセレクタが変化するようにする。
changeイベントは、input, select, textareaタグで、ユーザーが要素の値を変更したときに発生する。

参考サイト

(この項おわり)
header