イベントバブル - DOM-Level-2

イベントバブルとは

イベントバブル動作が有効なイベントが発生したとき、始めにイベントが発生した要素に登録されたイベントリスナが実行されます。その後、イベントは上位の要素ノード方向に伝播していき、順番にイベントリスナが実行されます。最上位ノードは document ですので、documentのイベント処理を行えば、もう伝播されません。

サンプル1

HTML

DIV

P バブルスライムはにげだした!

HTMLソース

<div onclick="alert('DIV');">
  DIV
  <p onclick="alert('P');">P
    <span onclick="alert('バブルスライムはにげだした!');">バブルスライムはにげだした!</span>
  </p>
</div>

サンプル1解説

「バブルスライムはにげだした!」をクリックすると、

alert('バブルスライムはにげだした!'); // イベント発生元の要素ノードに登録されたイベント処理を行う
alert('P');                            // 一つ上の親要素にイベントが伝播(イベントバブル)し、onclick属性で定義されたイベント処理を行う
alert('DIV');                          // 更に一つ上の親要素にイベントバブルし、onclick属性で定義されたイベント処理を行う

「P」をクリックすると、

alert('P');    // イベント発生元の要素ノードに登録されたイベント処理を行う
alert('DIV');  // 一つ上の親要素にイベントバブルし、onclick属性で定義されたイベント処理を行う

「DIV」をクリックすると、

alert('DIV');    // イベント発生元の要素ノードに登録されたイベント処理を行う
// 上位要素ノードにイベントバブルするが、実行すべきイベントが登録されていないため、何も起こらない

サンプル2

HTML

DIV

P バブルスライムはにげだした!

HTMLソース

<script type="text/javascript"><!--
document.addEventListener('click', function (event) {
  var target = event.target;       // イベント発生元要素ノード
  if (target.id === 'DIV') {       // イベント発生元要素ノードの id属性値 が DIV なら
    alert ('DIV');
  } else if (target.id === 'P') {  // イベント発生元要素ノードの id属性値 が P なら
    alert ('P');
  } if (target.id === 'SPAN') {    // イベント発生元要素ノードの id属性値 が SPAN なら
    alert ('バブルスライムはにげだした!');
  }
}, false);
//--></script>
</head>
<body>

<div id="DIV">
  DIV
  <p id="P">P
    <span id="SPAN">バブルスライムはにげだした!</span>
  </p>
</div>

サンプル2解説

「バブルスライムはにげだした!」をクリックすると、

// イベント発生元の要素ノードに登録されたイベント処理がないため、上位ノードにイベントバブルする
alert ('バブルスライムはにげだした!'); // 最上位ノードのdocumentで定義されたイベントリスナを処理する

「P」をクリックすると、

// イベント発生元の要素ノードに登録されたイベント処理がないため、上位ノードにイベントバブルする
alert ('P'); // 最上位ノードのdocumentで定義されたイベントリスナを処理する

「DIV」をクリックすると、

// イベント発生元の要素ノードに登録されたイベント処理がないため、上位ノードにイベントバブルする
alert ('DIV'); // 最上位ノードのdocumentで定義されたイベントリスナを処理する

サンプル3

HTMLソース

<script type="text/javascript"><!--
(function () {
  function clickListener (event) {
    var target = event.target || event.srcElement;  // イベント発生元要素ノード (addEventListener || attachEvent)
    if (target.id === 'DIV') {                      // イベント発生元要素ノードの id属性値 が DIV なら
      alert ('DIV');
    } else if (target.id === 'P') {                 // イベント発生元要素ノードの id属性値 が P なら
      alert ('P');
    } if (target.id === 'SPAN') {                   // イベント発生元要素ノードの id属性値 が SPAN なら
      alert ('バブルスライムはにげだした!');
    }
  }

  if (document.addEventListener) {
    document.addEventListener ('click', clickListener, false);
  } else if (document.attachEvent) {
    document.attachEvent ('onclick', clickListener);
  }
})();
//--></script>

サンプル3解説

サンプル2に attachEvent() の処理を加えたコードです。IE8- は addEventListener() に対応していないので、attachEvent() で代用しています。
(IE9 は、addEventListener() に対応します)
実は、サンプル2の実際の処理はこのコードを使用しているので、サンプル2(HTML) は IE8- でも動作します。

参考URL

イベントバブルの参考URL

addEventListener(), attachEvent() の参考URL

eventインターフェース, event.target, event.srcElement の参考URL