例えば、DOMノードのイベント操作をする場合、1つのHTMLエレメントに対して1つのイベントリスナーを登録していくことはおすすめできません。アプリケーションの規模によってはイベントの登録がとても多くなります。これによって、ソースコードも膨大な量となり、またイベントの管理も煩雑になるため、イベントリスナー登録は少なくするべきでしょう。
次のようなHTMLエレメントの構造があります。
<div id="colors">
<div id="red" class="primary">Red</div>
<div id="green" class="secondary">Green</div>
<div id="blue" class="primary">Blue</div>
</div>
IDが「red」、「green」、「blue」のDIVタグをクリックしたときのイベントリスナーを登録する場合、まず、それぞれのタグ(3つ)に対してイベントリスナーを登録することを思いつくでしょう。
実際に登録すると、下記のような書き方になります。
Ext.fly( 'red' ).on( 'click', function(){
/*...*/
});
Ext.fly( 'green' ).on( 'click', function(){
/*...*/
});
Ext.fly( 'blue' ).on( 'click', function(){
/*...*/
});
つまり、これらの処理は次の図のような形になります。

しかし、先ほどのことから、イベントリスナー登録は可能であるなら減らすべきでしょう。この場合、red,green,blueのコンテナとなるエレメントに「colors」というIDを持つDIVタグが存在します。今回はこのタグを利用してイベントリスナーを登録してみましょう。
Ext.fly( 'colors' ).on( 'click', function( e, target ) {
alert( target.innerHTML + 'が選択されました!' );
var target = e.getTarget( '.primary' );
if( target ) {
// 「.primary」クラスのみ処理
alert( 'このタグはCSSクラス:primaryが指定されています!' );
}
});
'click'はDOMイベントなので、メソッドシグネチャはeとtargetです。
イベントとしては、ID「colors」のDIVタグがクリックされたときのイベントを記述することになりますが、targetは実際にクリックされたDOMオブジェクトが引き渡されてくるので、このDOMオブジェクトを利用して、処理を分岐させます。
さらに、イベントオブジェクトであるeのgetTargetメソッドを利用して、ターゲットを絞り込むことができます。サンプルコードでは、CSSクラス「.primary」をCSSセレクタとして使用し、ターゲットを取得しています。
これをイベントのデリゲート(委譲)といいます。コンテナエレメントのイベントによるハンドラ内で処理を分岐させることで、イベントリスナー登録をまとめることができます。
イベントデリゲートで使用したサンプルコードでは、コンテナエレメントのイベントのみをイベントリスナー登録しましたが、さらにコンテナエレメントに含まれるエレメントのイベントリスナー登録も同時に行った場合、どのような順番でイベントが発生するのでしょうか?
次の図は、「red」をクリックしたときのclickイベントの発生順です。

先にコンテナ内のエレメント「red」のclickイベントハンドラが実行され、その後にコンテナエレメント「colors」のイベントハンドラが実行されます。このように、ネストしたHTMLのイベントは、内側から外側に向かって順にイベントが発生していきます。図のように下から上に上がっていくイメージから(泡が上っていく様子)からバブリング、またはイベントバブリングと呼ばれます。
イベントリスナーを登録する際、引数によってさらに高度なイベント処理をすることが可能です。第4引数のオブジェクトに以下の項目を設定します。
Panel.on( ' enable', function( e, t ) {
// コールバック内容
}, this, {
// fooクラスに絞り込む
delegate: '.foo'
});
イベントのリレー
Ext.util.ObservableクラスのrelayEventsメソッドを使用すると、別のコンポーネントで発生したイベントを、あたかもそのコンポーネントで発生したイベントのように扱うことができます。これをイベントのリレーといいます。
以下に、その使用例を記述します。relayEventsメソッドの第1引数にイベントが発生するコンポーネントを、第2引数はリレーするイベントの名前を配列にして設定します。
// 'win'で発生したshowイベントとhideイベントをPanelにリレーする
Panel.relayEvents( win, [ 'show', 'hide' ] );
// リレーされるPanelに対してイベントリスナー登録をする
Panel.on( 'show', function( w ) {
console.log( arguments );
}, this );
この場合、winコンポーネントで発生した「show」イベントと「hide」イベントが、Panelコンポーネントで発生したイベントのように使用できます。
上記のようにイベントによって渡される引数をconsole.logを使用して確認すると、winコンポーネントで発生したイベントであることがわかります。しかし、イベントリスナーを登録したコンポーネントはPanelであることから、イベントがリレーされたことを確認できると思います。