Post

(Front-end) DOM 이벤트 모델

https://stackoverflow.com/questions/12627443/jquery-click-vs-onclick

eventuality

이벤트 핸들러 추가, 실행, 관리 객체 https://github.com/umbum/Web/blob/master/JS/goodparts/eventuality.html

이벤트

흔히 사용하는 window.onload가 바로 이벤트다.

1
2
3
4
window.onload = function(){};
load : 이벤트 이름 또는 이벤트 타입( event type )
onload : 이벤트 속성
function(){}; : 이벤트 리스터 또는 이벤트 핸들러

문서 객체에 이벤트를 연결하는 방법을 이벤트 모델이라 한다. 이벤트 모델은 다음과 같이 DOM Level에 따라 두 가지로 분류되며 각 레벨에서도 다시 두 가지로 분류된다.

  • DOM Level 0
    • 고전(기본) 이벤트 모델
    • 인라인 이벤트 모델
  • DOM Level 2
    • MS IE 이벤트 모델
    • 표준 이벤트 모델
  • DOM Level 3

추가로 jQuery event method도 이벤트를 연결하는 데 사용할 수 있다.

Level2 처럼 여러 개의 이벤트 리스너를 연결할 수 있다.

DOM Level 0

고전(기본) 이벤트 모델 : 비추

요즘도 많이 사용한다. 문서 객체의 이벤트 속성으로 이벤트를 연결하는 방법이다. getElementById()를 이용해 JS로 HTML element를 불러와 이벤트를 연결한다.

1
2
3
4
5
6
7
8
9
10
11
window.onload = function(){
var header = document.getElementById('header');


//function whenClick() { alert("CLICK"); }
//header.onclick = whenClick();
header.onclick = function(){
alert("cl");
header.onclick = null; //이벤트 제거
};
}

주석처리한 문장처럼 함수를 연결하면 제대로 동작하지 않는다. 이벤트를 제거하려면 null을 할당하면 된다.

고전 이벤트 모델은 이벤트 하나에 이벤트 리스너 하나만 연결 가능하다. (그래서 다른 방법을 쓰는게 좋다.)

이벤트 발생 객체 및 이벤트 정보 ( this )

이벤트 핸들러 안에서 this 키워드를 사용하면 이벤트가 발생한 객체를 알아낼 수 있다.

this 를 사용해서 이벤트가 발생한 객체의 속성을 변경할 수 있다.

1
2
3
header.onclick = function(){
this.style.color = 'orange'
};

이벤트 발생에 대한 정보는 이벤트 객체 안에 들어있다. alt 등의 키를 함께 눌렀는지, 좌표는 어디인지 등의 정보가 출력된다.

1
2
3
4
5
6
7
8
9
10
11
window.onload = function(){
var header = document.getElementById('header');
header.onclick = function(e){
this.innerHTML += '</br>'
var event = e || window.event;
for (var key in event){
this.innerHTML +=
'<p>' + key + ': ' + event[key] + '</p>';
}
};
}

IE 8 이하는 이벤트 발생 시 이벤트를 window.event 속성으로 전달하지만, 다른 브라우저는 매개변수로 전달하기 때문에 다음과 같이 처리한다.

1
var event = e || window.event;

header.onclick() 이런 식으로 이벤트를 강제로 실행할 수 있다.

인라인 이벤트 모델 : 비추

인라인 이벤트 모델은 HTML attribute를 직접 작성하면서 value에 JS 코드를 적어 이벤트를 연결하는 방식이다.

onclick, onchange, onload 등 이벤트 모델의 “value” 는 자동으로 JS 코드로 해석된다.

1
2
3
4
5
6
7
8
<script>
function whenClick(e){
alert('CLICK EVENT');
}
</script>
</head>
<body>
<h1 onclick="whenClick(event)">click</h1>

this 를 사용해 이벤트가 발생한 DOM에 접근할 수 있다.

1
2
3
4
<select onchange="alert(this.value)">
<option value="1">first</option>
<option value="2">second</option>
</select>

디폴트 이벤트 제거

일부 HTML 태그는 자체적인 이벤트 리스너를 가지고 있다. 이 것을 디폴트 이벤트라고 한다. 예를 들어 입력 양식의 submit 버튼을 누르면 자동으로 입력 양식을 제출하고 페이지를 새로고침 하는 것이 디폴트 이벤트다. 디폴트 이벤트를 제거하는 것은 이 같은 입력 양식에서 입력값 검증을 위해 많이 사용한다. 바로 양식을 제출하도록 하지 않고, 적절히 검증한 다음 제출하도록 이벤트를 수정하는 것이다.

고전 이벤트 모델은 역시 HTML element들을 불러와서 검사하게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
window.onload = function (){
document.getElementById('my-form').onsubmit = function(){
var pass = document.getElementById('pass').value;
var passCheck = document.getElementById('passCheck').value;

  

if(pass != passCheck){
alert("pass and passCheck are diffrent")
return false;
}
}
}

인라인 이벤트 모델은 HTML attribute에 JS 함수를 직접 연결한다. 이 때 return fucntion()형태로 적어줘야 한다.

1
2
3
4
5
6
7
8
9
10
function whenSubmit(e){
var eventinfo="";
for (var key in e){
eventinfo += key + " : " + e[key] + "\n";
}
alert(eventinfo);
return false;
}
...
<form id="my-form" onsubmit="return whenSubmit(event)">

이벤트 전달 ( 이벤트 버블링 )

이벤트 버블링은 자식 노드에서 부모 노드 순으로 이벤트를 실행하는 것을 말하고, 이벤트 캡쳐링은 부모 노드에서 자식 노드 순으로 이벤트를 실행하는 것을 말한다.

IE와 JQuery에서 이벤트 캡쳐링을 지원하지 않기 때문에, 이벤트 캡쳐링 방식은 사용하지 않는다. 그래서 브라우저에서 이벤트를 전달하는 방식은 이벤트 버블링이다.

p태그를 클릭하면 자식 노드 paragraph에 연결된 팝업이 먼저 뜨고, header 팝업이 뜬다. 이벤트 전달을 막으면 paragraph에 연결된 팝업만 출력하도록 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
window.onload = function () {
document.getElementById('header').onclick = function (){
alert("header");
}
document.getElementById('paragraph').onclick = function (){
alert("paragraph");
}
}
</script>
...
<h1 id="header">
<p id="paragraph">paragraph</p>
</h1>

이벤트 전달을 막는 방법은 다음과 같다.

  • IE : 이벤트 객체의 cancelBubble속성을 js true로 변경한다.
  • 그 외 : 이벤트 객체의 stopPropagation() 메서드를 사용한다. 보통은 이렇게 한꺼번에 처리한다
1
2
3
4
5
6
7
document.getElementById('paragraph').onclick = function (e){
var event = e || window.event;
event.cancleBubble = true;
if(event.stopPropagation){
event.stopPropagation();
}
}

DOM Level 2

Level 0 이벤트 모델은 하나의 이벤트 리스너만 연결할 수 있지만, Level 2 이벤트 모델을 사용하면 이벤트를 여러개 연결할 수 있다.

IE 이벤트 모델

다음 두가지 메서드로 이벤트를 연결하거나 제거한다.

1
2
attachEvent(eventProperty, eventListener);
detachEvent(eventProperty, eventListener);

eventProperty : onload, onclick 등 eventListener : 이벤트 함수 이는 IE에만 존재하는 메소드라서 다른 브라우저에서 사용하면 에러난다. 다음과 같이 사용하면 페이지가 로드되면서 IE event 알람창이 두번 뜬다. 이런 식으로 이벤트를 중첩 연결할 수 있다. 바깥의 window.onloadwindow.attachEvent로 변경하면 안된다.

1
2
3
4
window.onload = function () {
window.attachEvent('onload', function () { alert("IE event"); });
window.attachEvent('onload', function () { alert("IE event"); });
}

익명 함수를 이벤트 리스너로 사용했을 경우 제거할 수 없다. 어떤 이벤트를 제거할지 파라미터로 지정해 넘겨야 하기 때문이다.

표준 이벤트 모델

W3C에서 공식적으로 지정한 이벤트 모델이다. (DOM Level 3도 W3C에서 지정)

1
2
addEventListener(eventName, eventListener[, useCapture]);
removeEventListener(eventName, eventListener);

useCapture를 사용하면 이벤트 캡쳐링 방식으로 동작하는데, 사실상 안쓴다.

1
2
3
4
5
6
window.onload = function() {
var header = document.getElementById('header');
header.addEventListener('click', function () {
this.innerHTML += '+';
});
}
This post is licensed under CC BY 4.0 by the author.