IMEのInputEventでの入力検知について
Input要素におけるInputEventの入力検知
概要
とある実装で入力された項目を自動でカタカナに変換するという件がありました。 例えば、ある項目Aに"富士山"といったワードを打ち込んだ時に、カタカナの項目Bを"フジサン"にするのような実装です。
これを実現するために二通りの実現方法があるかと思います。
- 入力時のキーボード入力をトラッキングする。
- 入力された何かしらの文字列から形態素解析などを用いて適切なフリガナをふる。
今回は入力項目がただの単語なので1の方法で十分でした。 1の場合、このくらいの実装ならば何かしら良いOSSがあるのではないかと思い調べましたが、特にいい感じのものが見当たらなかったので自身で実装することにしました。
その時に調べたことをまとめようと思います。 なお、PCはMacのChromeのみしか検証していませんのでPC = IOSのChromeということで解釈お願いします。
実際の実装・結論
注意!2020/05時点の環境になります
-
PC(chrome)の場合
-
KeyBoardEvent
のkey
プロパティを使用してトラックする。
KeyBoardEvent.key // "[a-z|A-Z]もしくは記号
PCの場合は単純にこのプロパティをトラック用のChar[]なスタックとみなした配列に突っ込めば要件を満たせます。EnterやBackspaceもこのプロパティで追えます。
-
-
OSX(safari & chrome)の場合
-
4つのInputEvent.inputTypeを分岐させて入力内容をトラックする
変換可能である文字が1文字入力された: "insertCompositionText", IMEの変換が実行された: "insertFromComposition", 変換可能である文字が1文字削除された: "deleteCompositionText", 確定状態の文字が1文字削除された: "deleteContentBackward"
トラック用のChar[]な配列をスタックとして初期化し、上記の項目で分岐させ、追加、削除のたびにその配列を操作します。 例えば、
insertCompositionText
なイベントの場合はchars.push(e.data)
し、deleteCompositionText
の場合はchars.pop()
します。 また、IMEの変換が実行されたタイミングではdeleteCompositionText
insertCompositionText
という風にイベントが走るので、注意します。 変換対象の文字列を一旦削除するようになっている実装みたいです。
-
-
Android(chrome)の場合
- 手元にないので、実際に実機で動くか不明ですがブラウザのUAを変更して動きを見るとPCと同じようでした。
上記以外の場合はこちらのDemoで実際にお試しください。
InputEvent
IOSの場合はInputEventで捉えられるということが調べてわかりました。
- 日本語入力IMEでもアルファベットIMEでも
InputEvent.data
で変換対象状態の文字列が返って来るので、それを単純に追えば良い。 - 変換中の文字が削除されたときは
InputEvent.inputType
が"deleteCompositionText"
になるので削除も補足できる
しかし、一度変換されてしまうと漢字の読みまでは予測できないので今回の実装は不可逆です。 私の要件としては問題なかったのでこれで完了しましたが、上手いこと手軽にできる手段があれば知りたい。。
KeyBoardEvent
Android, PCの場合はKeyBoardEvent.key
をスタックにつめつめしていけば追えます。
削除の場合もBackspaceやら特殊な入力を検知するだけです。こちらも今回の実装では一度カタカナにすると不可逆なので他に手段があれば知りたいです。
ん?じゃあこれからどうやってカタカナにするの?
めちゃくちゃ簡潔で素晴らしいコードが記載されていました。こちらをご確認ください。
って、これIOSしかできんやんけ!
はい、ローマ字から日本語に落としましょう。こちらが大変参考になります。正規表現って恐ろしいですね。
所感
挙動確認するのしんどいし面倒な作業なので誰かの一助になれば幸いです。
参考
W3の仕様の草案 https://rawgit.com/w3c/input-events/v1/index.html#interface-InputEvent-Attributes