今日は、JavaScriptの話題を書いていこうと思います。タイトル通り、JavaScriptでHTML上の入力項目を矢印キーで上下に移動することが実現できるかを試していきたいと思います。
変なことをするなぁと思われるかもしれませんが、実は最近仕事でこのような要望がありました。矢印キーで手軽に入力項目を移動したいということですね。
また、矢印キーで入力項目を移動したときに移動先のテキストを選択状態にすることも要望されました。
最初は簡単にできそうだなぁと思ったのですが、意外と苦戦したので今回記事にした次第です。
どのように実装するか?
JavaScriptで上下にある入力項目(INPUTタグのTYPE="text")を矢印キーの↑(上)、↓(下)で移動するために以下のイメージで実装します。
※便宜上、上にある入力項目をA入力項目、下にある入力項目をB入力項目とします
①INPUTタグのTYPE="text"の入力項目を上下に2つ用意する
②A入力項目にイベントリスナーを設定する
設定するイベントリスナーは、keydownイベントで矢印キー↓が押されたときを判定しB入力項目にフォーカスするfocus()を呼び出す。フォーカス関数を呼び出した後に、テキストを選択状態にするselect()を呼び出すことで矢印キーによる移動を実現する。
③B入力項目にイベントリスナーを設定する
②と同様にkeydownイベントを登録する。A入力項目と異なるのは矢印キー↑が押下されたことを判定して、A入力項目をフォーカスすること。他の挙動はすべて同じ。
文字で色々と書いていてもよくわからないと思いますので、上記①~③の内容を反映したソースを以下に記載しましたのでご確認ください。
サンプルで使用するHTMLソース
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>sample</title> </head> <body> <input type="text" id="text1" value="text1"><br> <input type="text" id="text2" value="text2"> <script> const text1 = document.getElementById('text1'); const text2 = document.getElementById('text2'); text1.addEventListener('keydown', function(e) { if (e.keyCode === 40) { // 矢印キーの↓を押下した場合 text2.focus(); text2.select(); } }); text2.addEventListener('keydown', function(e) { if (e.keyCode === 38) { // 矢印キーの↑を押下した場合 text1.focus(); text1.select(); } }); </script> </body> </html>
サンプルで使用するHTMLソースをブラウザで確認
動作確認をしました
上記のソースで本当に上手く動作するかを確認しました。矢印キーによる入力項目の上下の移動は実現できました。しかし、テキストを選択するselect()が効いていないのか入力項目を移動した後にテキスト項目が選択されないのです。う~ん、どうしてだろう。
問題点は何か?
うーん、こういうときは便利なGoogle Chromeのデバッグモードだ!ということで確認しました。ステップ実行しながら確認するとselect()を実行した瞬間は画面上を確認すると色が反転しているので選択されているようです!!(以下画面キャプチャ参照)
しかしデバッグモードが終わるとテキスト選択が解除されてしまいます。全然わからない・・・。これは本当に悩みました。
問題点を発見!!
そして、色々と試行錯誤を行って以下のコードをイベントリスナーのコールバック関数の処理に追加することで問題なく動作することを確認しました。
e.preventDefault();
簡単に言うと上記メソッドを使うことで、ブラウザデフォルトの動作を抑制することができるようです。ブラウザデフォルトの動作についてですが、たとえばAタグのhref属性には遷移先のURLを指定すれば、リンクをクリックすることで指定した画面に遷移できると思います。Aタグでは、この画面遷移する作用がブラウザデフォルトの動作のことです。
今回の例では、INPUTタグのTYPE="text"です。入力項目の矢印キー↑を押下すると先頭にカーソルが遷移し、矢印キー↓を押下すると末尾に遷移すると思います。これが入力項目のブラウザのデフォルトの動作です。
ということで、原因は focus()、select()をした後にブラウザのデフォルトの動作が作用することにより、テキストの選択が解除されてしまったようです!!!
今回やりたいことを実現するためには、このブラウザデフォルトの動作を作用させたくなかったので、e.preventDefault()を追加しました。
終わりに
JavaScriptを触り始めてからまだ日が浅いのですが、フロントエンドはVue.jsやReact、Angularなどたくさんのフレームワークも出てきているので
もっといろいろと勉強していきたいと思っています。実は、Vue.jsを個人的に触っているのですがやはりJavaScriptの知識は大事だなぁと思いました。
何故かというと、テキストとか見ても正直あまり理解できていないんですよね。。JavaScriptの文法の理解が薄いとなかなか厳しそうな感じはしています。
今回も最後まで読んでいただきありがとうございました。それでは今回はこの辺で。