jQuery(elem).trigger(eventType)が実行されたとする。このとき発生したイベントをjQueryを利用せずに取得できるだろうか。
jQuery.fn.trigger()の実装の概要
jQuery.fn.trigger()はjQuery.event.trigger()の薄いラッパーになっていて、処理の大半はjQuery.event.trigger()の中で行われる(どちらもsrc/event.jsで定義されている)。
現在のDOMではイベントを生成するAPI(new Event, document.createEvent)と、生成したイベントを発行するAPI(EventTarget.dispatchEvent(event))が提供されているが、jQueryはそれらのAPIを使わず、独自にイベントオブジェクトを作り、イベントのバブリング1なども自前で実装している。
jQuery.fn.trigger()によってイベントが発行される処理を大まかにまとめると次のようになる。
- イベントがバブリングするノードをリストアップして、それぞれに「jQueryから設定されたイベントハンドラを実行して、
node['on' + type]が呼び出せそうならそれも実行する」という処理を行う。
- ここでの
typeはtrigger()の引数として渡されたイベント名からネームスペースを取り除いたもの(jQuery(node).trigger("click.foo.bar")ならclickになる)。 -
typeに:が含まれている場合はnode['on' + type]は実行されない。
- イベントの
preventDefault()が呼ばれていなければ、elem[type]を見て、これが関数であれば実行する2。
- ここでの
elemはイベントの起点になるノード(jQuery(elem).trigger(event))。 -
typeに:が含まれている場合はこの処理は実行されない。
例
-
click:- バブリングの対象になるノードの
onclickプロパティに関数を設定しておくと、1の処理の中で実行される。 - ほとんどのノードにはネイティブの
clickメソッドがあるはずなので、イベント伝播の対象になるノードに標準のイベントリスナーを設定しておけば(伝播中に他のリスナーが伝播を抑止しない限り)イベントを取得できる。
- バブリングの対象になるノードの
-
click.foo.bar:clickと同じ。 -
reset:-
clickの1と同じ。 - イベントの起点になるノードにネイティブの
resetメソッドがあるときにはclickの2と同じ。そうでない場合にはfoobarの2と同じ。
-
-
foobar(非標準のイベント)- バブリングの対象になるノードの
onfoobarプロパティに関数を設定しておくと、1の処理の中で実行される。 - イベントの起点になるノードの
foobarプロパティに関数を設定しておくと、2の処理の中で実行される。
- バブリングの対象になるノードの
-
ajax:success: 取得できない。
テスト: Catching jQuery events by vanilla JS - JSFiddle
参考・関連
- .trigger() | jQuery API Documentation
- 自作オブジェクトのイベントのやりとりにはjQuery.triggerではなくjQuery.triggerHandlerを使うほうがよいと思った - hitode909の日記
-
trigger()メソッド内のイベント伝播のシミュレートでは、capture phaseには対応せず、bubbling phaseのみ実装している。jQuery.fn.bindなどは、IE8以下ではcapture phaseがサポートされていないという理由でcapture phaseに対応していない(参考: Jquery .bind events triggered when event capture or event bubble(Stack Overflow)に対するT.J. Crowderの回答)のと関係があるのかもしれない。 ↩ -
余談だが、一部のブラウザでは
HTMLElement.click()などで発火したイベントも伝播するので、ここでnode['on' + type]がもう一度実行される。 ↩
