반응형

앞에서 사용했던 일반적인 이벤트처리는 동일한 요소/동일한 이벤트에 대해 복수의 이벤트 핸들러를 정의할 없다.

 

여러 라이브러리를 조합하여 이용하고 있는 경우에는 어떤 라이브러리가 어떤 요소의 특정 이벤트를 사용해버리면 다른 라이브러리에서 동일한 요소에 다른 이벤트를 등록할 수가 없다.

 

이와 같은 경우에 사용할 있는 방법이 이벤트리스너이다.

이벤트 리스너는 이벤트 핸들러와 같이 발생된 이벤트에 대응하는 처리를 정의하는 것은 같지만 다음과 같은 부분이 다르다.

  • 동일 요소의 동일 이벤트에 대해서 복수의 이벤트 리스너를 등록할 있다.
  • 먼저 설정한 이벤트 리스너를 삭제할 있다.

 

단점으로는 브라우저를 의식하고 작성해야 한다.

  • IE - attachEvent메서드 사용
  • - addEventListener 메서드 사용

 

이벤트 등록

1
2
3
addEventListener/attachEvent 메소드
요소노드.attachEvent(이벤트명, 이벤트 핸들러)
요소노드.addEventListener(이벤트명, 이벤트 핸들러, 이벤트의 전달 방향)
cs

이벤트 삭제

1
2
3
detachEvent/removeEventListener 메소드
요소노드.detachEvent(이벤트명, 이벤트 핸들러명)
요소노드.removeEventListene(이벤트 명,이벤트 핸들러 명, 이벤트의 전달 방향)
cs

 

1. 이벤트 리스너 등록하기

addListenertest.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
27
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>이벤트 리스너의 등록</title>
<script type="text/javascript">
function addListener(elem, ev, listener) {
    if(elem.addEventListener) {
        elem.addEventListener(ev, listener, false);
    } else if(elem.attachEvent) {
        elem.attachEvent('on' + ev, listener);
    } else {
        throw new Error('이벤트 리스너에 미대응입니다.');
    }
}
addListener(window'load', init);
 
function init() {
    addListener(document.getElementById('btn'), 'click'function() {
        window.alert('버튼이 클릭되었습니다.');
    });
}
</script>
</head>
<body>
<input type="button" id='btn' value="다이얼로그표시" />
</body>
</html>
cs

 

2. 이벤트 리스너 삭제하기

removeListenertest.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>이벤트 리스너의 삭제</title>
<script type="text/javascript">
function addListener(elem, ev, listener) {
    if(elem.addEventListener) {
        elem.addEventListener(ev, listener, false);
    } else if(elem.attachEvent) {
        elem.attachEvent('on' + ev, listener);
    } else {
        throw new Error('이벤트 리스너에 미대응입니다.');
    }
}
 
function removeListener(elem, ev, listener) {
    if(elem.removeEventListener) {
        elem.removeEventListener(ev, listener, false);
    } else if(elem.detachEvent) {
        elem.detachEvent('on' + ev, listener);
    } else {
        throw new Error('이벤트 리스너에 미대응입니다.');
    }
}
 
addListener(window'load', init);
 
function init() {
    addListener(document.getElementById('btn'), 'click', btn_click);
    addListener(document.getElementById('btnRemove'), 'click', btnRemove_click);
}
 
function btn_click() {
    window.alert('버튼이 클릭되었습니다.');
}
 
function btnRemove_click() {
    removeListener(document.getElementById('btn'), 'click', btn_click);
}
</script>
</head>
<body>
<input type="button" id='btn' value="다이얼로그 표시" />
<input type="button" id='btnRemove' value="이벤트 리스너 삭제" />
</body>
</html>
cs

 

3., 이벤트 관련 정보 취득하기

Event객체는 이벤트를 발생시킨 객체에 대한 정보를 참조하고 있다.

eventtest.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Event객체</title>
<script type="text/javascript" src="listener.js"></script>
<script type="text/javascript">
addListener(window'load', init);
 
function init(){
    addListener(document.getElementById('title'), 'mousedown',
        function(e) {
            var result = [];
            result.push('발생원:' + getSource(e).id);
            result.push('이벤트:' + e.type);
            result.push('버튼:' + getButtonType(e));
            result.push('X좌표:' + e.clientX);
            result.push('Y좌표:' + e.clientY);
            window.alert(result.join('\n'));
        }
    );
}
 
function getSource(e) {
    if(e.target) {
        return e.target;
    } else if(window.event) {
        return window.event.srcElement;
    }
}
 
 
function getButtonType(e) {
    if(e.target) {
        switch(e.button) {
            case 0 : return 'left';
            case 1 : return 'center';
            case 2 : return 'right';
        }
    } else if(window.event) {
        switch(window.event.button) {
            case 1 : return 'left';
            case 2 : return 'right';
            case 4 : return 'center';
        }
    }
}
</script></head>
<body>
<h1 id="title">[마우스로 클릭해보세요]</h1>
</body>
</html>
cs

 

동작 확인 Event객체를 취급하는 경우의 주의사항을 보자.

Event객체를 얻으려면 브라우저들 간의 동작 차이를 알고 있어야 한다.

기본적으로 대부분의 브라우저에서 이벤트 발생 이벤트 핸들러 함수가 등록되어 있다면

발생된 이벤트 객체를 이벤트리스너 함수의 번째 인수로 전달받는다.

주의해야 하는 것은 이렇게 이벤트를 전달받은 핸들러 내에서 Event객체를 이용하려는 경우이다.

역시 대부분의 브라우저에서 이벤트 핸들러 안에서 핸들러를 정의하는 경우 이벤트 객체를 번째 인자로 전달받지만 Internet Explorer 이벤트 객체를 전달하지 않는다.

그래서 이런 경우 window.event 프로퍼티를 경유하여 명시적으로 Event객체를 취할 필요가 있다.

일반적인 상황에서는 고려하지 않겠지만 만약 이벤트핸들러에서 이벤트 객체를 취급하려는 경우에는 크로스 브라우징을 고려해야할 필요가 있으며 다음과 같은 형태의 코드가 필요하다.

1
2
3
4
5
6
window.onload = function(){ 
   document.getElementById('btn').onmousedown = function(e){
        if(!e) { e = window.event; }       
        //event 객체에 의해 읽어들인 코드
    }
}
cs

코드와 같이 이벤트가 전달되지 않은 경우 window.event 프로퍼티로부터 이벤트 객체를 명시하여 가져온다. 이를 활용하면 어떤 브라우저든 변수 e 이용하여 이벤트 객체에 접근할 있다.

 

Event객체에서 사용 가능한 프로퍼티

분류

프로퍼티

설명

일반

srcElement

이벤트를 발생시킨 요소(IE 브라우저)

 

target

이벤트를 발생시킨 요소(IE 이외 브라우저)

 

type

이벤트 종류(click ,mouseover )

좌표

clientX

이벤트 발생 좌표(브라우저에서의 좌표)

 

clientY

이벤트 발생 좌표(브라우저에서의 좌표)

 

screenX

이벤트 발생 좌표(화면에서의 좌표)

 

screenY

이벤트 발생 좌표(화면에서의 좌표)

키보드/마우스

button

마우스 버튼 구분(//중앙)

 

keyCode

키보드 입력 코드

 

altKey

알트키 눌림 상태

 

ctrlKey

컨트롤키 눌림 상태

 

shiftKey

시프트키 눌림 상태

 

4. 이벤트 객체 프로퍼티에 대한 주요 사항

 

- 이벤트를 발생시킨 요소를 취득하는 것은 srcElement/target 프로퍼티이다.

     IE -> srcElement 프로퍼티

     그 -> target 프로퍼티

앞에 예제에서 크로스브라우저에 대응하기 위해 이벤트 발생 요소를 얻기 위해서 함수를 사용하였다.

getSource() 함수에서 다음과 같은 처리를 확인할 있다.

Event.target 프로퍼티 존재 확인
성공 여부에 따라 srcElement/target 프로퍼티 하나를 호출

- button 프로퍼티의 값은 브라우저에 따라 다름

종류

IE

마우스 왼쪽 버튼

1

0

마우스 오른쪽 버튼

2

2

중앙 버튼

4

1

 

추가적으로 사항으로 IE에서는 클릭 되고 있는 버튼의 조합을 인식할 있음. (/ 동시 클릭 1+2=3 값을 반환)

 앞의 예제에서 getButtonType()함수를 보면 Event.target 프로퍼티 존재 여부에 따라 브라우저의 종류를 식별하여 반환 값에 대응되는 문자열을 반환하고 있다.

 

5. 상위 요소로 이벤트 전달 막기

기본적으로 페이지상에서 발생한 이벤트는 상위 요소에도 전달된다.

bubbletest.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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Event객체</title>
<script type="text/javascript" src="listener.js"></script>
<script type="text/javascript">
addListener(window'load', init);
 
function init(){
    addListener(document.getElementById('outer'), 'click'function(e) {
        window.alert("상위 요소의 이벤트리스너입니다.");
    });
    addListener(document.getElementById('inner'), 'click'function(e) {
        window.alert("하위 요소의 이벤트리스너입니다.");
    });
}
</script>
</head>
<body>
<div id="outer">
    <div id="inner">
        클릭해 봅시다.
    </div>
</div>
</body>
</html>
cs

 

상위요소로의 이벤트 전달을 확인할 있다. 이러한 동작의 개념을 거품이 올라가는 것에 빗대어 버블링이라 한다. 버블링이 경우에 따라서 막아야 필요가 있는데 이런 경우 명시적으로 억제가 가능하다.

 

stopPropageationtest.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
27
28
29
30
31
32
33
34
35
36
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Event객체</title>
<script type="text/javascript" src="listener.js"></script>
<script type="text/javascript">
function cancelBubbling(e) {
  if (e.stopPropagation) {
    e.stopPropagation();
  } else if (window.event) {
    window.event.cancelBubble = true;
  }
}
 
addListener(window'load', init);
 
function init() {
    addListener(document.getElementById('outer'), 'click'function(e) {
        window.alert("상위 요소의 이벤트리스너입니다.");
    });
    addListener(document.getElementById('inner'), 'click'function(e) {
        window.alert("하위 요소의 이벤트리스너입니다.");
        cancelBubbling(e);
    });
}
</script>
</head>
<body>
<div id="outer">
    <div id="inner">
        클릭해 봅시다.
    </div>
</div>
</body>
</html>
 
cs

 

위와 같은 방식 또한 브라우저에 따라 다를 있다.

     IE -> cancelBubble 프로퍼티 사용

     그 -> stopPropagation 메서드 사용

 

    동작 과정은 다음과 같다.

        (1) Event.stopPropagation 프로퍼티가 존재하는지 확인

        (2) 위 확인 결과에 따라 stopPropagation메서드 또는 cancelBubble프로퍼티를 사용

 

6. 이벤트 디폴트의 동작 막기

 개발을 하다 보면 submit 같은 버튼의 기본 이벤트 동작을 제거해야 경우도 있다.

 submit뿐만 아니라 a태그와 같이 기본적인 동작이 있는 요소에 대해 이벤트를 제거하는 방법이 있다.

 이벤트 핸들러는 기본적으로 반환값으로 false 반환하지만 기본 동작은 취소되지 않는다.

 

 이를 해결하기 위해 다음과 같은 작업이 필요하다.

      IE -> returnValue 프로퍼티

      그 -> PreventDefault 메서드

 

cancelEvent.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
27
28
29
30
31
32
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Event객체</title>
<script type="text/javascript" src="listener.js"></script>
<script type="text/javascript">
function cancelEvent(e) {
  if (e.preventDefault) {
    e.preventDefault();
  } else if (window.event) {
    window.event.returnValue = false;
  }
}
 
addListener(window'load', init);
 
function init() {
    addListener(document.getElementById('fm'), 'submit'function(e) {
        if(!window.confirm('송신해도 좋겠습니까?')){
            cancelEvent(e);
        }
    });
}
</script>
</head>
<body>
<form id="fm">
<input type="text" id="name" size="10" />
<input type="submit" value="송신" />
</form>
</body>
</html>
cs

 

위와 같이 크로스브라우저에 대응하기 위한 함수를 정의하여 이벤트 취소 처리를 외부에 정의하였다.

 

처리 설명

    (1) Event.preventDefault 프로퍼티 존재여부 확인

    (2) 위 성공여부에 따라 preventDefault메서드 호출 또는 returnValue 프로퍼티 사용하여 처리

반응형

'교육자료 > Javascript' 카테고리의 다른 글

18-4. 스타일시트 조작하기  (0) 2019.05.13
18-3. 노드 치환하기  (0) 2019.05.13
18-2. 속성 값 가져오기  (0) 2019.05.13
18-2. DOM특정 노드 참조하기  (0) 2019.05.13
18-1. DOM(Document Object Model)  (0) 2019.05.13

+ Recent posts