IMEのInputEventでの入力検知について

IMEのInputEventでの入力検知について

Input要素におけるInputEventの入力検知

デモページ

概要

とある実装で入力された項目を自動でカタカナに変換するという件がありました。 例えば、ある項目Aに"富士山"といったワードを打ち込んだ時に、カタカナの項目Bを"フジサン"にするのような実装です。

これを実現するために二通りの実現方法があるかと思います。

  1. 入力時のキーボード入力をトラッキングする。
  2. 入力された何かしらの文字列から形態素解析などを用いて適切なフリガナをふる。

今回は入力項目がただの単語なので1の方法で十分でした。 1の場合、このくらいの実装ならば何かしら良いOSSがあるのではないかと思い調べましたが、特にいい感じのものが見当たらなかったので自身で実装することにしました。

その時に調べたことをまとめようと思います。 なお、PCはMacのChromeのみしか検証していませんのでPC = IOSのChromeということで解釈お願いします。

実際の実装・結論

注意!2020/05時点の環境になります

  • PC(chrome)の場合

    • KeyBoardEventkeyプロパティを使用してトラックする。

      KeyBoardEvent doc

    KeyBoardEvent.key // "[a-z|A-Z]もしくは記号
    

    PCの場合は単純にこのプロパティをトラック用のChar[]なスタックとみなした配列に突っ込めば要件を満たせます。EnterやBackspaceもこのプロパティで追えます。

  • OSX(safari & chrome)の場合

    • 4つのInputEvent.inputTypeを分岐させて入力内容をトラックする

      InputEvent doc

    変換可能である文字が1文字入力された: "insertCompositionText",
    IMEの変換が実行された: "insertFromComposition",
    変換可能である文字が1文字削除された: "deleteCompositionText",
    確定状態の文字が1文字削除された: "deleteContentBackward"
    

    トラック用のChar[]な配列をスタックとして初期化し、上記の項目で分岐させ、追加、削除のたびにその配列を操作します。 例えば、insertCompositionTextなイベントの場合はchars.push(e.data)し、deleteCompositionTextの場合はchars.pop()します。 また、IMEの変換が実行されたタイミングでは

    1. deleteCompositionText
    2. 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