EventTarget - イベントの対象
EventTargetは、イベントを設定するための機能を備えたインターフェイスです。NodeやElement、Document、Windowなど、イベントを設定できるインターフェイスがこれを継承しています。
概要
- 名前
- EventTarget
- IDL
[Constructor, Exposed=(Window,Worker,AudioWorklet)] interface EventTarget { void addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options); void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); boolean dispatchEvent(Event event); }; dictionary AddEventListenerOptions : EventListenerOptions { boolean passive = false; boolean once = false; }; callback interface EventListener { void handleEvent(Event event); }; dictionary EventListenerOptions { boolean capture = false; };
- 仕様書
- https://dom.spec.whatwg.org/#eventtarget
チュートリアル
イベントの設定
ある要素をクリックした時のイベントを設定する例です。
<button id="hoge">SYNCER</button>
// 要素の取得
var element = document.getElementById( "hoge" ) ;
// コールバック関数
var listener = function ( event ) {
console.log( "クリックしました!!" ) ;
}
// 要素にイベントを追加
element.addEventListener( "click", listener ) ;
// 要素のイベントを削除
element.removeEventListener( "click", listener ) ;
イベント発生の仕組み
イベントが発生すると、子孫から先祖の順番にコールバック関数が呼び出されます。例えば、下記は、それぞれの要素にクリックイベントが設定されている状況で、div#event4をクリックした時の例です。すると、div#event4、div#event3、div#event2、div#event1の順番にコールバック関数が呼び出されます。
<!-- 子孫から先祖(event4 → event3 → event2 → event1)の順番にコールバック関数が呼び出される -->
<div id="event1">
<div id="event2">
<div id="event3">
<!-- ここがイベントの発生元 -->
<div id="event4">
</div>
</div>
</div>
</div>
もちろん、これは基本であって、イベントの設定によってはこの順番が変わることもあります。その仕組みを後述します。
立場
さて、疑問に思わなければいけないのは「なんでクリックしてないdiv#event1、div#event2、div#event3のコールバック関数が呼び出されてしまうのか?」です。これは、それらがdiv#event4の先祖だからです。レイアウトで重なっていたか、重なっていないかは一切関係ありません。レイアウトは捨てて下さい。ツリー構造上の先祖と子孫の関係だけを考えて下さい。
要素 | 立場 | 説明 |
---|---|---|
div#event1 | 先祖 | ついでに、コールバック関数が呼び出される。 |
div#event2 | 先祖 | ついでに、コールバック関数が呼び出される。 |
div#event3 | 先祖 | ついでに、コールバック関数が呼び出される。 |
div#event4 | 発生元 | イベントの発生元だから、コールバック関数が呼び出される。 |
何故、イベントが発生した時、発生元の先祖に設定してあるコールバック関数が呼び出されてしまうのか。これは、イベントフェイズという概念を知れば理解できます。
イベントフェイズと伝播
イベントが発生すると「伝播」が起こります。伝播とは「伝わる」という意味です。リンゴでもなんでもいいのですが、たった1つの「何か」を次から次へ渡していく、という画をイメージすると分かりやすいと思います。伝播を受け取ると、設定されているコールバック関数が呼び出されます。伝播の現在位置によって、3つの段階(フェイズ)に分けることができます。これらをまとめて、イベントフェイズといいます。
順番 | 名前 | 説明 | 伝播の順番 |
---|---|---|---|
1 | キャプチャリングフェイズ | 伝播がイベントの発生元に辿り着く前の段階。先祖から子孫の方向に伝播する。 | div#event1 → div#event2 → div#event3 |
2 | ターゲットフェイズ | 伝播がイベントの発生元に辿り着いた段階。 | div#event4 |
3 | バブリングフェイズ | 伝播がイベントの発生元に辿り着いた後の段階。子孫から先祖の方向に伝播する。 | div#event3 → div#event2 → div#event1 |
先にまとめてしまうと、立場が「先祖」の場合、キャプチャリングフェイズ、または、バブリングフェイズでコールバック関数が実行されます。立場が「発生元」の場合、ターゲットフェイズでコールバック関数が実行されます。
キャプチャリングフェイズ
イベントが発生すると、一番最初に、先祖から子孫の方向に伝播します。伝播がイベントの発生元に辿り着く前までの段階を、キャプチャリングフェイズといいます。例では、一番の先祖であるWindowから始まり、Documentを経て、、
// div#event4に辿り着く前までがキャプチャリングフェイズ
(省略) → div#event1 → div#event2 → div#event3 → div#event4(イベントの発生元)
キャプチャリングフェイズでは、伝播を受けてもコールバック関数は呼び出されません。つまり、この段階ではdiv#event1、div#event2、div#event3のコールバック関数が呼び出されません。
これはデフォルトの話です。「キャプチャリングフェイズの段階でコールバック関数を実行する」と、イベントの登録時に設定することができます。
ターゲットフェイズ
キャプチャリングフェイズを経て、伝播がイベントの発生元に辿り着いた段階を、ターゲットフェイズといいます。ターゲットフェイズでは、イベントの発生元のコールバック関数が呼び出されます。例では、div#event4のコールバック関数が呼び出されます。イベントの発生元は、伝播の行き止まりです。つまり、これ以上、子孫の方向には伝播しません。
// div#event4に辿り着いた時点がターゲットフェイズ
(省略) ← div#event1 ← div#event2 ← div#event3 ← div#event4(イベントの発生元)
バブリングフェイズ
行き止まり(イベントの発生元)まで辿り着いた伝播は、今度は逆方向、すなわち、子孫から先祖の方向に進みます。この段階を、バブリングフェイズと言います。バブリングフェイズは、イベントの発生元(div#event4)を含みません。
// div#event4に辿り着いた時点がターゲットフェイズ
(省略) ← div#event1 ← div#event2 ← div#event3 ← div#event4(イベントの発生元)
バブリングフェイズでは、伝播を受けてコールバック関数が呼び出されます。つまり、例では、div#event3、div#event2、div#event1と、伝播を受けた順番に、それぞれに設定してあるコールバック関数が呼び出されるというわけです。
これはデフォルトの話です。「バブリングフェイズの段階ではコールバック関数を実行しない」と、イベントの登録時に設定することができます。
コンストラクタ
コンストラクタはありません。
プロパティ
固有のプロパティはありません。
メソッド
addEventListener()
1つのターゲット(要素など)に対して、1つのリスナー(コールバック関数)を追加登録します。
dispatchEvent()
ターゲットに対して、任意のイベントを発生させます。
removeEventListener()
ターゲットに設定してあるイベントを削除します。
定数
固有の定数はありません。
イベント
固有のイベントハンドラはありません。
サポート状況
クリックすると、バージョンごとの対応状況を確認できます。
Features | Chrome | Firefox | Safari | Edge | IE | Opera | iOS Safari | Android |
---|---|---|---|---|---|---|---|---|
EventTarget | ● | ● | ● | ● | ● 9+ | ● | ● | ● |
addEventListener() | ● | ● | ● | ● | ● 9+ | ● | ● | ● |
dispatchEvent() | ● | ● | ● | ● | ● 9+ | ● | ● | ● |
removeEventListener() | ● | ● | ● | ● | ● 9+ | ● | ● | ● |
関連記事
- CaretPosition.getClientRect()
- getClientRect()は、CaretPositionのメソッドです。キャレット位置を表すDOMRectを返します。
- CaretPosition.offset
- offsetは、CaretPositionのプロパティです。キャレット位置を表す、ノードの先頭からのオフセットを返します。
- Selection.deleteFromDocument()
- deleteFromDocument()は、Selectionのメソッドです。選択範囲のコンテンツを削除します。
- Selection.removeAllRanges()
- removeAllRanges()は、Selectionのメソッドです。全ての選択範囲を解除します。