HTML 태그는 중첩되어 있다. 따라서 특정한 태그에서 발생하는 이벤트는 중첩되어 있는 태그들 모두가 대상이 될 수 있다. 이런 경우 중첩된 태그들에 이벤트가 등록 되어 있다면 어떻게 처리 될까? (실행)
<html> <head> <style> html{border:5px solid red;padding:30px;} body{border:5px solid green;padding:30px;} fieldset{border:5px solid blue;padding:30px;} input{border:5px solid black;padding:30px;} </style> </head> <body> <fieldset> <legend>event propagation</legend> <input type="button" id="target" value="target"> </fieldset> <script> function handler(event){ var phases = ['capturing', 'target', 'bubbling'] console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]); } document.getElementById('target').addEventListener('click', handler, true); document.querySelector('fieldset').addEventListener('click', handler, true); document.querySelector('body').addEventListener('click', handler, true); document.querySelector('html').addEventListener('click', handler, true); </script> </body> </html>
실행결과
INPUT HTML capturing INPUT BODY capturing INPUT FIELDSET capturing INPUT INPUT target
이벤트가 부모에서부터 발생해서 자식으로 전파되고 있다. 이러한 방식을 capturing이라고 한다. ie 낮은 버전에서는 작동하지 않기 때문에 많이 사용하지는 않는다.
코드를 아래와 같이 변경해보자. (실행)
document.getElementById('target').addEventListener('click', handler, false); document.querySelector('fieldset').addEventListener('click', handler, false); document.querySelector('body').addEventListener('click', handler, false); document.querySelector('html').addEventListener('click', handler, false);
차이점은 addEventListener의 3번째 인자가 false로 변경 되었다.
실행결과
INPUT INPUT target INPUT FIELDSET bubbling INPUT BODY bubbling INPUT HTML bubbling
이번에는 순서가 반대로 되었다. 자식부터 부모로 이벤트가 전파되는 것을 버블링(bubbling)이라고 한다.
이벤트 전파를 중간에 가로막을 수도 있다.
아래처럼 코드를 변경해보자. (실행)
function handler(event){ var phases = ['capturing', 'target', 'bubbling'] console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]); } function stophandler(event){ var phases = ['capturing', 'target', 'bubbling'] console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]); event.stopPropagation(); } document.getElementById('target').addEventListener('click', handler, false); document.querySelector('fieldset').addEventListener('click', handler, false); document.querySelector('body').addEventListener('click', stophandler, false); document.querySelector('html').addEventListener('click', handler, false);
실행결과
INPUT INPUT target INPUT FIELDSET bubbling INPUT BODY bubbling
참고로 ie9 이전의 브라우저에서는 이벤트 전파을 막기 위해서 event.cancelBubble 프로퍼티를 사용해야 한다.