본문 바로가기
제가 쓴 책/HTML5, CSS3 and JavaScript

7.2 Event Method를 이용한 이벤트 처리

by edupicker(체르니) 2013. 8. 6.

7.2 Event Method를 이용한 이벤트 처리


방금 전 이벤트 속성을 이용한 이벤트 처리 방법은 요소에 이벤트 속성을 이용하여 이벤트를 처리하는 형태에 대해서 알아보았습니다. 이 방법은 HTML 요소 태그 내에 JavaScript 코드가 혼용되어 사용되는 조금은 HTML 코드와 JavaScript를 코드 분리와 같은 원칙이 조금은 아쉬운 이벤트 처리 방법이었습니다.
이번에는 편리하게 addEventListener(), removeEventListener() 메서드를 이용하여 이벤트를 처리하는 방법에 대해서 알아봅니다.



7.2.1 addEventListener() 메서드를 이용한 이벤트, 이벤트 핸들러 추가

addEventListener()
메서드는 img, p 등과 같은 HTML DOM 요소에 특정 이벤트와 이에 대한 이벤트 처리를 위한 함수를 연결할 수 있도록 지원하는 메서드로 다음과 같은 형식을 사용합니다.


addEventListener(eventType, handler, capture);


위에서 eventType click, submit과 같은 이벤트 이름을 나타냅니다. 다음으로 handler는 이벤트가 발생했을 때 처리해 줄 함수를 나타내며 마지막으로 capture true 혹은 false 중 하나의 값을 가지게 되며 일반적으로 대부분의 경우 false가 사용됩니다.
예를 들어 웹페이지에 이미지를 더블클릭하면 발생하는 dblclick 이벤트와 이벤트 발생시 처리해줄 함수를 dblclkHandler라고 하면 다음과 같은 형태로 사용할 수 있습니다.


addEventListener("dblclick", dblclkHandler, false);


이제 이에 대한 예제를 해볼까요? 메모장을 열어서 다음과 같이 코드를 작성합니다.

<!DOCTYPE HTML>
<html>
<head>
  <title>addEventListener
예제</title>
  <script type=”text/javascript”>
    //
추가할 코드 부분
  </script>
</head>
<body>
  <p>
이미지 위에서 마우스 더블클릭(dblclick)</p>
  <img id="flowerid" src="flower2.jpg" width="100" height="70">
</body>
</html>

위와 같이 “flower2.jpg” 이미지를 화면에 나타내는데 있어서 “flowered” id 속성값으로 설정한 후 “addEventListenerEx.html”로 저장하고 IE9를 통해 보면 화면에 “flower2.jpg” 이미지가 나타나고 아직까지는 마우스로 더블 클릭해도 아무런 이벤트가 발생하지 않습니다.
이제 실제 마우스로 이미지를 더블 클릭하면 이에 대해서 반응하도록 위 코드에서 “//추가할 코드 부분에 다음과 같이 코드를 작성합니다.


    window.onload = function() {
      var vimg = document.getElementById("flowerid");
      vimg.addEventListener("dblclick",dblclkHandler,false);
      function dblclkHandler() {
        alert("flower2.jpg
이미지를 더블클릭함");
      }
    }

위에서 페이지 로딩(Loading)이 끝나면 발생하는 load 이벤트 핸들러 안에 getElementById() 메서드를 이용하여 img 요소 객체를 참조하는 객체를 선언하고 이 객체에 addEventListener() 메서드를 이용하여 dblclick 이벤트와 이벤트를 처리해 줄 함수를 dblclkHandler로 설정합니다. 마지막으로 실제 dblclkHandler() 함수를 정의해주면 됩니다. 저장하고 IE9로 다시 연 후 이미지를 더블 클릭하면 조금 전과는 달리 다음과 같이 알림창이 나타나게 됩니다.




조금만 더 나가볼까요? 알림창에 HTML 요소이름과 이벤트 이름이 나타내기 위해서 다음과 같이 해당 코드를 수정합니다.


      function dblclkHandler(event) {
        alert(this.nodeName + "
요소의 flower2.jpg 이미지를 더블클릭하여" +
        event.type + "
이벤트 발생");
      }

위에서 입력 파라미터로 사용된 event는 이벤트(event) 객체(object)를 나타내어 이 event 객체의 type 속성을 이용하면 어떤 이벤트가 발생했는지를 파악할 수 있습니다. 저장하고 다시 IE9를 통해 열어보면 다음과 같이 원하는 정보를 나타내줍니다.





7.2.2 removeEventListener() 메서드를 이용한 이벤트, 이벤트 핸들러 삭제
removeEventListener()
메서드는 addEventListener() 메서드와 반대 기능을 하는 메서드로 img, p 등과 같은 HTML DOM 요소에 연결된 특정 이벤트와 이에 대한 이벤트 처리를 위한 함수를 삭제하는데 사용되는 메서드로 다음과 같은 형식을 사용합니다.


removeEventListener(eventType, handler, capture);


위에서 사용된 eventType, handler, captureaddEventListener() 메서드에서와 동일합니다.
이제 방금 전 예제를 조금 변형해서 이벤트를 삭제하는 방법을 알아봅니다.
메모장으로 “addEventListenerEx.html” 파일을 열어서 <script> … </script> 블록 안을 다음과 같이 수정합니다.


  <script type="text/javascript">
    window.onload = function() {
      var vimg = document.getElementById("flowerid");
      var count =1;
      vimg.addEventListener("dblclick",dblclkHandler,false);
     
      function dblclkHandler(event) {
        if(count != 1) {     
          vimg.removeEventListener("dblclick",dblclkHandler,false);
          alert("dblclick
이벤트가 삭제되었습니다.");
        }
        else {
          alert(this.nodeName+ "
요소의 flower2.jpg 이미지를 더블클릭하여"+
          event.type +"
이벤트 발생");
        }
        count++;

      }     
    }
  </script>

위에서 더블 클릭수를 계산하기 위한 변수 count를 선언하고 그 값을 1로 초기화한 후 dblclick 이벤트가 발생하면 처리해주는 함수인 dblclkHandler() 내에서 count 값이 1일 경우에 dblclick 이벤트 처리를 하고 1이 아닐 경우는 id 속성값이 “flowered” img 요소로부터 dblclick 이벤트를 삭제하도록 합니다. 메모장에서 다른 이름으로 저장을 선택하고 “removeEventListenerEx.html”로 저장한 후 IE9를 통해 열고 이미지를 처음 클릭하면 방금 전 “addEventListenerEx.html” 예제의 결과와 같이 나타나지만 다시 더블 클릭하면 다음과 같이 “dblclick 이벤트가 삭제되었습니다."라는 알림창이 나타나게 됩니다.





7.2.3
동일한 이벤트 타입 처리 - Event capturing, Event bubbling

이제 지금까지 설명하지 않았던 addEventListener(), removeEventListener() 메서드의 입력 파라미터들 중 3 번째 caputure의 값에 대해서 자세히 볼까요?
HTML
요소(Element)들은 동일한 이벤트 타입을 가질 수 있습니다. 예를 들어 div 요소 안에 p, button, img 등 다양한 요소들이 포함되어 있다고 가정하면 div 요소 안의 img를 마우스로 클릭(click) 할 경우 div 요소의 click 이벤트가 발생해야 할까요? 아니면 img 요소의 click 이벤트가 발생해야 할까요? 이에 대한 이벤트 발생 순서는 다음과 같이 2 가지 형태로 나눌 수 있습니다.


Event capturing
밖에서 안으로 접근하는 형태로 방금 전 가정을 생각해보면 먼저 div 요소의 click 이벤트가 발생하고 img 요소의 click 이벤트 발생하는 순서로 동작합니다.

Event bubbling

안으로 밖으로 접근하는 형태로 Event capturing 접근방법과 반대로 먼저 img 요소의 click 이벤트 발생하고 div 요소의 click 이벤트가 발생하는 순서로 동작합니다.

위와 같인 동일한 이벤트 타입 처리에 대한 2 가지 접근 방법은 브라우저별로 그 적용이 다르며
현재 W3C에서 2가지 접근 방법을 모두 지원하며 앞서
addEventListener(), removeEventListener() 메서드의 입력 파라미터들 중 3 번째 caputure의 값을 true로 설정하면 Event capturing 접근방법을 적용하는 것이고 caputure의 값을 false로 설정하면 Event bubbling 접근방법을 적용하는 것이라고 이해하면 편합니다.
이제 예제를 통해 차이점을 알아보기 위해서 메모장을 열어서 다음과 같이 코드를 작성합니다.


<!DOCTYPE HTML>
<html>
<head>
  <title>event capturing,bubbling
예제</title>
  <style type="text/css">
    div.color {
      border-width:3px;
      border-style:solid;
      border-color:#ff9900;
    }
  </style>
  <script type=”text/javascript”
    //
이벤트를 처리할 코드 부분
  </script>
</head>
<body >
  <div id="outer_div" class="color">
    <img id="flowerid" src="flower2.jpg" width="100" height="70">
  </div>
</body>
</html>


div 요소 안에 앞 예제들에서 사용한 “flower2.jpg” 이미지를 img 요소를 이용하여 포함된 형태로 body 요소를 구성합니다. 그리고 div img 요소를 구분하기 위해서 상단의 <style> … </style> 블록의 코드와 같이 경계선의 두께(너비), 스타일 및 색상을 설정합니다.
“eventcapturingandbubbling.html”
로 저장하고 IE9를 통해 보면 다음과 같이 나타납니다.




div, img 요소에 click 이벤트, 이벤트 핸들러를 addEventListener() 메서드를 이용하여 caputure의 값을 false로 설정하여 Event bubbling 접근방법을 적용되는지 보기 위해서 위 코드에서 “//이벤트를 처리할 코드 부분부분에 다음과 같이 코드를 작성합니다.

  <script type="text/javascript">
    window.onload = function() {
      var vdiv = document.getElementById("outer_div");
      vdiv.addEventListener("click", divclkHandler, false);  
      var vimg = document.getElementById("flowerid");
      vimg.addEventListener("click", imgclkHandler, false);
     
      function divclkHandler(event) {
        alert(this.nodeName+ "
요소를 클릭하여"+event.type +"이벤트 발생");
      }

      function imgclkHandler(event) {
        alert(this.nodeName + "
요소의 flower2.jpg 이미지를 클릭하여" +
        event.type + "
이벤트 발생");
      }     
    }
  </script>

위 코드에서 “vdiv.addEventListener("click", divclkHandler, false);”와 같이 caputure의 값을 false 형태로 설정해서 먼저 img 요소의 click 이벤트 발생하고 div 요소의 click 이벤트가 발생하는 순서로 동작하는 Event bubbling 접근방법으로 코드를 작성합니다. 저장하고 IE9로 연 후 이미지를 클릭하면 다음과 같이 먼저 img 요소의 click 이벤트 발생하여 해당 알림창을 먼저 알리고 그 다음 div 요소의 click 이벤트가 발생하여 관련 알림창에 메시지를 표시하게 됩니다.




이제 밖에서 안으로 접근하는 형태인 Event capturing 방법을 알아보기 위해서 위 코드에서 2개의 addEventListener() 메서드 부분을 다음과 같이 코드를 수정합니다.

    vdiv.addEventListener("click", divclkHandler, true);
    vimg.addEventListener("click", imgclkHandler, true);


위와 같이 caputure의 값을 true 형태로 설정하여 Event capturing 접근 방법으로 적용되도록 하고 저장한 후 IE9로 열고 이미지를 클릭하면 Event bubbling 접근방법에서와는 반대로 먼저 div 요소의 click 이벤트가 발생하여 관련 알림창에 메시지를 나타내고 뒤이어 img 요소의 click 이벤트 발생하여 해당 알림창을 나타냅니다.

끝으로 IE9 이전 버전의 경우
addEventListener(), removeEventListener() 메서드가 지원되지 않으며 addEventListener() 메서드와 유사한 기능을 하는 attachEvent(), removeEventListener() 메서드와 비슷한 기능을 하는 detachEvent() 메서드를 이용하여 이벤트 처리를 할 수 있습니다. 이에 대한 부분은 웹사이트나 관련 자료들을 참고하시기 바랍니다.





- 본 저작물은 본인이 2011년 상반기부터 2012년 여름 즈음까지 도서 출판을 목적으로 약 470 페이지(A4, 폰트 10)으로 작성한 원본 중 JavaScript에 대한 부분을 그대로를 공개하는 것으로 본 저작물에 대한 모든 권리는 본인(원철연)에서 있음을 알립니다.
개인적인 학습 목적으로 사용을 허용하며 온오프라인의 베포나 펌상업적인 용도의 사용은 삼가해주시기 바랍니다. 끝으로 학교나 비영리 단체에서의 경우 본 저작물을 비상업적인 용도로 활용하고자 할 경우 연락처를 비밀댓글로 남겨주시면 연락드리겠습니다.