자바스크립트 이벤트 - EVENT Bubbling or Capture




1. 이벤트 버블링이란?


해당 엘리먼트의 이벤트 발생 시 브라우저가 시행하는 특정 이벤트 처리 절차를 가리킵니다.


- 이벤트 처리 절차는 아래와 같습니다.

1. 해당 엘리먼트의 이벤트 속성에 할당된 핸들러를 호출합니다.

2. 최초 이벤트가 발생한 엘리먼트의 위치부터 루트 엘리먼트(#document)까지의 모든 부모 엘리먼트들을 검사하여 최초 발생한 이벤트 타입과 동일한 이벤트 타입에 핸들러가 할당되어 있다면 이를 실행시킵니다.






- 아래는 버블링 전파에 대한 내용을 도식화한 그림입니다.






또한, 아래 작성된 코드로 이벤트 전파 테스트가 가능합니다.


  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <HTML onclick="msg(this, 'test');">
  3. <HEAD>
  4. <TITLE> New Document </TITLE>
  5. <META NAME="Generator" CONTENT="EditPlus">
  6. <META NAME="Author" CONTENT="">
  7. <META NAME="Keywords" CONTENT="">
  8. <META NAME="Description" CONTENT="">
  9. <script>
  10.  
  11. function msg(obj, msg, e){
  12.    
  13.     e = window.event || e;
  14.     alert(obj.nodeName);
  15. };
  16.  
  17.  
  18. </script>
  19.  
  20.  
  21. </HEAD>
  22. <BODY onclick="msg(this, 'test');">
  23. <div id="test_object1" onclick="msg(this, 'test');">
  24.     <div id="test_object2" onclick="msg(this, 'test');"></div>
  25.     <!-- 방법 2: HTML 어트리뷰트에 할당하는 방법 -->
  26.     <div id="test_object3" onclick="msg(this, 'test');">CLICK!!!</div>
  27. </div>
  28. </BODY>
  29. </HTML>


위 코드의 실행 결과는 아래와 같습니다.

[test_object3] onclick handler --> [test_object1] onclick handler --> [body] onclick handler --> [html] onclick handler --> [#document] onclick handler




추가코드: 이벤트 버블링 방지하기

 function stopPropagation(e) {
    //IE or 표준 브라우저
    if (e.cancelBubble) e.cancelBubble = true;
    else if (e.stopPropagation) e.stopPropagation();
}



2. 이벤트 캡처란? 

DOM LEVEL 2 이벤트 모델부터 지원하기 시작했으며, IE 브라우저를 제외(IE 브라우저는 버블링 처리만 지원)한 표준 브라우저에서만 지원하고 버블링과는 반대되는 이벤트 처리 절차를 가집니다.

즉, 버블링 처리 절차 와는 반대로 루트 엘리먼트 부터 이벤트가 발생한 엘리먼트의 위치로 이벤트를 전파시킵니다.



아래는 버블링과 마찬가지로 캡처 시 전파에 관한 내용을 도식화한 그림입니다.



또한, 아래 작성된 코드로 이벤트 전파 테스트가 가능합니다.


  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <HTML>
  3. <HEAD>
  4. <TITLE> New Document </TITLE>
  5. <META NAME="Generator" CONTENT="EditPlus">
  6. <META NAME="Author" CONTENT="">
  7. <META NAME="Keywords" CONTENT="">
  8. <META NAME="Description" CONTENT="">
  9. <script>
  10.  
  11.  
  12. // DOM LEVEL 2 Event Model 처리 함수
  13. function bind(elem, type, handler, capture)
  14. {
  15.  
  16.     type = typeof type === 'string' && type || '';
  17.     handler = handler || function(){ ; };
  18.    
  19.     if (elem.addEventListener){
  20.         elem.addEventListener(type, handler, capture);
  21.     }
  22.     else if (elem.attachEvent){
  23.         elem.attachEvent('on' + type, handler);
  24.     }
  25.  
  26.     return elem;
  27. };
  28.  
  29. // 이벤트 할당
  30. bind(window, 'load', function(){
  31.  
  32.     bind(document, 'click', function(e){
  33.        
  34.             var e = window.event || e
  35.               , target = e.srcElement || e.target;
  36.            
  37.             alert(document.nodeName);
  38.  
  39.     }, true);
  40.  
  41.     bind(document.documentElement, 'click', function(e){
  42.        
  43.             var e = window.event || e
  44.               , target = e.srcElement || e.target;
  45.            
  46.             alert(document.documentElement.nodeName);
  47.  
  48.     }, true);
  49.  
  50.     bind(document.body, 'click', function(e){
  51.        
  52.             var e = window.event || e
  53.               , target = e.srcElement || e.target;
  54.            
  55.             alert(document.body.nodeName);
  56.  
  57.     }, true);
  58.  
  59.     bind(document.getElementById('test_object1'), 'click', function(e){
  60.        
  61.             var e = window.event || e
  62.               , target = e.srcElement || e.target;
  63.            
  64.             alert(document.getElementById('test_object1').nodeName);
  65.  
  66.     }, true);
  67.  
  68.     bind(document.getElementById('test_object2'), 'click', function(e){
  69.        
  70.             var e = window.event || e
  71.               , target = e.srcElement || e.target;
  72.            
  73.             alert(document.getElementById('test_object2').nodeName);
  74.  
  75.     }, true);
  76.  
  77.  
  78. }, false);
  79.  
  80. </script>
  81.  
  82.  
  83. </HEAD>
  84. <BODY>
  85. <div id="test_object1">
  86.     <div id="test_object2">CLICK!!!</div>
  87. </div>
  88. </BODY>
  89. </HTML>


마지막으로 앞서 말씀드린바와 같이 이벤트 캡처는 IE 브라우저를 제외한 표준 브라우저에서만 지원하므로 실행 결과는 아래와 같습니다.


IE 브라우저: 

위 소스중 bind(, , , true) 함수 호출 시 캡처 상태를 나타내는 매개변수에 true를 넘겨도 캡처를 지원하지 않으므로 이벤트 호출 시 버블링 방식으로 처리됩니다):


[test_object2] onclick handler --> [test_object1] onclick handler --> [body] onclick handler --> [html] onclick handler --> [#document] onclick handler

표준 브라우저:


[ #document ] onclick handler --> [ html ] onclick handler --> [body] onclick handler --> [ test_object1] onclick handler --> [ test_object2] onclick handler