しかしそうも言っていられない。Opera が対応している keypress、keydown、keyup、input イベントでなんとか擬似的に composition events を再現できないか。
ということでそれっぽくできた。一応このエントリも、今まさに wasavi で書いている。しかし問題は山積している:
- 結局のところ、例の暗黙的確定には対応できない。
- 上記のイベントの、Opera 12.12 上での動作にきわめて依存した構成なので、安定してるともいえない。
つまり人様にお出しするにはちょっと……という出来である。どうしよう。
ちなみに擬似 composition events の実現手法だが、Opera で IME の仮入力は、keydown、input、keypress の順でイベントが発生する。このとき、input イベントは場合によっては複数回発生する。仮入力中は、keydown 時の keycode は 229 で固定。keyup 時の keycode は本来押されたキーのコードが入っている。
IME がアクティブな時の様々な動作の特徴は以下の通り:
- 明示的確定: 仮入力後変換候補を出している状態で、enter キー押下により確定する動作。keydown(229)、input が 2 回、keyup(13)
- 暗黙的確定: 仮入力後変換候補を出している状態で、変換に使用しないキーの押下により暗黙的に確定する動作。たとえば「漢字」と変換した状態でそのまま続けて HENKAN と打つと、「漢字」は自動的に確定され、かつ確定に使用した文字「H」が次の仮入力に持ち越される。この動作は composition events でなければ正しく認識できない。keydown(229)、input が 3 回、keyup(暗黙的確定に使用した文字のキーコード)
- 仮入力の取り消し: 取り消しには 2 パターンの方法がある。escape キーを押すか、backspace で仮入力文字を全削除するか。前者は keydown(229)、keyup(最後に入力した文字のキーコード)。つまり input イベントが発生しない。後者は発生する。さらに、IME がアクティブで、かつ仮入力文字列が空かどうかで判断する
- その他の仮入力、変換操作: keydown(229)、input が 1 回、keyup(最後に入力した文字のキーコード)
keydown、input、keyup をリスンし、keydown 時のキーコードおよび input が発生した回数を覚えておく。上記の場合分けはすべて keyup のハンドラで行う。
その他の仮入力、変換操作で、IME がアクティブ(これは実際の IME の状態ではなく、javascript 上のフラグ)でなければ、compositionstart イベントを発火し、IME がアクティブ状態であるとする。それから、compositionupdate イベントを発火する。
2 種の確定動作で確定された文字列を取り出し、compositionend イベントを発火し、IME が非アクティブ状態であるとする。