Hatena::Groupjavascript

JavaScriptで遊ぶよ

 | 

2011-12-09

CompositionEventの紹介

00:49

JavaScript Advent Calendar 2011オレ標準駅伝10日目です。それにしてもみなさん濃いですね。圧巻はoogattaさんでしょうか。

今日は軽めに、あまり知られてないと思われるDOMのAPIを紹介したいと思います。

DOM3 EventsにはComposition Event Typesというのがあります。

CompositionEventにはcompositionstart, compositionupdate, compositionendの3つのイベントタイプがありまして、これらはIME専用のイベントタイプです。

ChromeとFirefoxとIE9では既に使えました。デモを試してみてください。

f:id:edvakf:20111209062313p:image


こんな感じになるわけです。

IMEを使って最初の一文字を入力しようとするときに出るのがcompositionstartで、キーを打ってるときと変換候補を巡ってるときに出るのがcompositionupdateで、決定のときに出るのがcompositionendです。


何が嬉しいの?

ChromeやIEはIMEで入力中にもkeyupやkeydownが出ますが(昔は違ったような気が…うろ覚え)、FirefoxやOperaなどはCompositionEvent以外には何もイベントを出さないので、compositionupdateが無ければIMEで入力中なのかどうかわかりません。Firefoxではtextというオレ標準イベントが出るらしいです。Operaは東アジア対応が弱いので、CompositionEventが近いうちに入る可能性は低い気がします。

なので、サジェスト系のUIだとタイマーで入力欄のvalueを見てやらないといけません。

CompositionEventがあればもうそんな心配はいりませんね。


それから、↓こういう経験ありますよね。

f:id:edvakf:20111209063950p:image

compositionstartがcancelableになっているのはこれを解決しようとしてのことだと思います。標準IMEをキャンセルしちゃってキー打つごとにサジェスト出したらいいじゃん、って感じです。

しかし、今のところcompositionstartをpreventDefaultできるのはIE9だけでした。MozillaのMDNにはこう書かれています。

Note: This event should handle starting the text composition system, but in Gecko it's the other way around; when the system starts its composition system, Gecko fires this event.

Gecko notes

According to the DOM Level3 specification, compositionstart is cancelable; however, Gecko doesn't currently let you cancel them.

Gecko fires this event when IME starts composition, and some platforms don't have an API for canceling composition once it's begun. In addition, Gecko can't know whether a keyboard event will start composition or not until IME actually starts composition. Because of this, event.preventDefault() doesn't work on compositionstart events in Gecko.

compositionstart - MDN

たぶんChromeも似たような理由でcancelableにしていないんだと思います。

標準のIMEをスタートさせないって、ユーザビリティとしてはどうなのかなとも思いますけどねぇ。


もうOSのIMEなんかに頼らずウェブサイト側がIMEを提供しちゃえばいいんじゃね?みたいなぶっ飛んだ提案をGoogle Chromeチームの人が出してたこともあります。(ウェブサイト側というよりChrome OSやExtensionのことを睨んだものかもしれませんが)

ここから続くスレッドで、こっちに飛んで、最後はここまで続いて、まあ否定的に立ち消えになってます。


CompositionEventの話から逸れました。

Chromeの実装でおかしなところを見つけたのでこれも紹介しておきます。

Some implemenations may populate the data attribute of the compositionstart event with the text currently selected in the document (for editing and replacement); otherwise, the value of the data attribute must be the empty string.

Document Object Model (DOM) Level 3 Events Specification

仕様によると、compositionstartでは.dataが空文字か、またはIMEで入力しようとするときに選択中でこれから置き換えられるはずのテキストにせよと書いてあるんですが、Chromeではcompositionupdateと同じ、つまり最初の文字が入ってます。

その他、他のイベントとの順番や、イベントリスナー中でtextarea.valueを取ったときの値などを見るといろいろ食い違ってるので、やっぱりキーイベントは鬼門だなと思った次第です。


あ、そうそう、DOM3 Eventsのキーイベントでもう一つの大きな目玉といえば、.keyですよね。keyIdentifierを置き換えたあれです。これもIE9ではしっかり実装されてました。ChromeとFirefoxはまだです。あとgetModifierStateというメソッドe.shiftKeyとかの代わりにe.getModifierState('Shfit')とか書けるやつ)もIE9では実装されてました。すごい。

keyIdentifierやkey valueについてはこのブログに昔書いたことがありますので参考までに。


また話が逸れました。

まあそういうことで、今のところはサジェストでタイマー走らせないでいいよってぐらいしか良い所がなさそうなCompositionEventですが、その他の使い道を思いついた人は教えてください。

それでは、Happy Christmas!

nanto_vinanto_vi2011/12/10 01:14> FirefoxやOperaなどはCompositionEvent以外には何もイベントを出さない

一応Mozillaにはtextイベントなるものがあるそうです。
http://tech.kayac.com/archive/firefox-text-event.html

edvakfedvakf2011/12/10 01:26ありがとうございます。デモをアップデートしておきました。

 |