JavaScript入門 | イベント | イベントリスナーの呼び出し

イベントリスナーの呼び出し

イベントリスナーが登録され、対象のオブジェクトや要素で指定されたタイプのイベントが発生すると、ブラウザは登録されたイベントリスナーを自動的に呼び出す。 このときイベントリスナーは引数としてイベントオブジェクトを受け取り、識別子を通じて渡されたイベントオブジェクトを参照する。

イベントオブジェクト

イベントオブジェクトとは、特定のタイプのイベントに関連するオブジェクトである。

イベントオブジェクトは、そのタイプのイベントに関する詳細情報を保存している。 すべてのイベントオブジェクトは、イベントのタイプを表すtypeプロパティと、イベントの対象を表すtargetプロパティを持つ。 このようなイベントオブジェクトは、イベントリスナーが呼び出されるときに引数として渡される。

var btn = document.getElementById("btn"); // IDが"btn"の要素を選択する。
btn.addEventListener("click", clickBtn);  // 選択した要素にclickイベントリスナーを登録する。
function clickBtn(event) {
    document.getElementById("text").innerHTML =
    "このイベントのタイプは " + event.type + " で、イベントの対象は " + event.target + " です。";
}

イベントの呼び出し順序

addEventListener()メソッドを使用すると、1つのイベントタイプに複数のイベントリスナーを登録できる。 このとき特定のタイプのイベントが発生すると、ブラウザは次の順序でイベントを呼び出す。

  1. イベントの対象となるオブジェクトや要素にプロパティとして登録したイベントリスナーを最初に呼び出す。
  2. その後、addEventListener()メソッドを使用して登録したイベントリスナーを、登録した順序で呼び出す。

イベント伝播

イベント伝播とは、イベントが発生したときに、ブラウザがイベントリスナーを実行する対象要素を決定する過程を意味する。

イベントの対象がWindowオブジェクトのような単一のオブジェクトであれば、イベントの伝播は起こらない。 しかし、DocumentオブジェクトやHTML文書の要素でイベントが発生すると、対象要素を決定するためにイベントの伝播が起こる。

イベントの伝播方式は、大きく次の2つに分けられる。

  1. バブリング方式
  2. キャプチャリング方式

バブリング方式

バブリング方式は、イベントが発生した要素から始まり、DOMツリーに沿って上方向へ伝播する方式である。

この伝播方式では、その要素のリスナーが実行された後、親要素に登録されたリスナーが実行され、さらにその親要素に登録されたリスナーが実行される。 このイベントの伝播は、Documentオブジェクトだけでなく、最終的にはWindowオブジェクトまで続く。

バブリング方式には、多数の要素に共通して適用されるイベントリスナーを各要素ごとに個別登録しなくても、共通の祖先要素に一度だけ登録すれば処理できるという利点がある。

// 各要素にバブリング方式でclickイベントリスナーを登録する。
document.getElementById("divBox").addEventListener("click", clickDiv);
document.getElementById("paraBox").addEventListener("click", clickPara);
document.getElementById("spanBox").addEventListener("click", clickSpan);
function clickDiv(event)  { document.getElementById("text").innerHTML += "div要素をクリックしました!<br>"; }
function clickPara(event) { document.getElementById("text").innerHTML += "p要素をクリックしました!<br>"; }
function clickSpan(event) { document.getElementById("text").innerHTML += "span要素をクリックしました!<br>"; }

キャプチャリング方式

キャプチャリング方式は、DOMツリーの最上位からイベントが発生した要素まで下方向へ伝播する方式である。

この伝播方式では、最初にWindowオブジェクトのリスナーが実行され、その後Documentオブジェクトに登録されたリスナーが実行され、さらにその子要素に登録されたリスナーが実行される。 このイベントの伝播は、イベントが発生した要素まで続く。 この伝播方式を使用するには、addEventListener()メソッドの3番目の引数にtrueを渡せばよい。

キャプチャリング方式では、実際にイベントの対象となる要素へイベントが渡される前に、上位要素に登録されたイベントリスナーがそれを横取りしたり捕捉したりできる。 このようにイベントを選別して該当するイベントリスナーが呼び出されないようにする技法を、イベントキャンセル技法という。

// 各要素にキャプチャリング方式でclickイベントリスナーを登録する。
document.getElementById("divBox").addEventListener("click", clickDiv, true);
document.getElementById("paraBox").addEventListener("click", clickPara, true);
document.getElementById("spanBox").addEventListener("click", clickSpan, true);

キャプチャリング方式は、addEventListener()メソッドをサポートしないInternet Explorer 8以前、Opera 6以前では使用できない。

イベントの既定動作のキャンセル

HTMLの<a>要素でクリックイベントが発生すると、ブラウザは指定されたアドレスをたどって新しいWebページを開く。 このように、特定のイベントにはあらかじめ指定された既定動作がある。 しかし、preventDefault()メソッドやreturnValueプロパティを利用すると、このような既定動作の実行をキャンセルできる。

// 各要素にバブリング方式でclickイベントリスナーを登録する。
document.getElementById("divBox").addEventListener("click", clickDiv);
document.getElementById("paraBox").addEventListener("click", clickPara);
document.getElementById("linkBox").addEventListener("click", clickLink);
function clickDiv(event) { document.getElementById("text").innerHTML += "div要素をクリックしました!<br>"; }
function clickPara(event) { document.getElementById("text").innerHTML += "p要素をクリックしました!<br>"; }
function clickLink(event) {
    event.preventDefault(); // リンクの既定動作をキャンセルする。
    document.getElementById("text").innerHTML += "リンクの既定動作を止めました!<br>";
    document.getElementById("text").innerHTML += "a要素をクリックしました!<br>";
}

イベント伝播のキャンセル

先ほど見たイベントの既定動作だけでなく、イベントの伝播もキャンセルできる。 stopPropagation()メソッドやcancelBubbleプロパティを利用すると、このようなイベントの伝播をキャンセルできる。

function clickLink(event) {
    event.preventDefault();  // リンクの既定動作をキャンセルする。
    document.getElementById("text").innerHTML += "リンクの既定動作を止めました!<br>";
    event.stopPropagation(); // イベントの伝播をキャンセルする。
    document.getElementById("text").innerHTML += "イベントの伝播を止めました!<br>";
}