HTML 태그는 중첩되어 있다. 따라서 특정한 태그에서 발생하는 이벤트는 중첩되어 있는 태그들 모두가 대상이 될 수 있다. 이런 경우 중첩된 태그들에 이벤트가 등록 되어 있다면 어떻게 처리 될까? (실행)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | < 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 > |
실행결과
1 2 3 4 | INPUT HTML capturing INPUT BODY capturing INPUT FIELDSET capturing INPUT INPUT target |
이벤트가 부모에서부터 발생해서 자식으로 전파되고 있다. 이러한 방식을 capturing이라고 한다. ie 낮은 버전에서는 작동하지 않기 때문에 많이 사용하지는 않는다.
코드를 아래와 같이 변경해보자. (실행)
1 2 3 4 | 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로 변경 되었다.
실행결과
1 2 3 4 | INPUT INPUT target INPUT FIELDSET bubbling INPUT BODY bubbling INPUT HTML bubbling |
이번에는 순서가 반대로 되었다. 자식부터 부모로 이벤트가 전파되는 것을 버블링(bubbling)이라고 한다.
이벤트 전파를 중간에 가로막을 수도 있다.
아래처럼 코드를 변경해보자. (실행)
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 ); |
실행결과
1 2 3 | INPUT INPUT target INPUT FIELDSET bubbling INPUT BODY bubbling |
참고로 ie9 이전의 브라우저에서는 이벤트 전파을 막기 위해서 event.cancelBubble 프로퍼티를 사용해야 한다.