
|
1. JavaScript 이벤트 2. 이벤트 관련 용어 3. 이벤트 전달 4. 표준 이벤트 모델 5. 기본 이벤트 |
1. JavaScript 이벤트
1) 이벤트(Event)
- 웹 페이지에서는 어떤 종류의 상호작용이 발생할 때 이벤트 발생
- 사용자에 의한 상호작용 : 클릭하거나 특정 요소 위로 마우스를 가져가거나 특정한 키를 누르는 것 등
- 브라우저에 의한 상호작용 : 웹 페이지의 로딩이 끝났다거나, 사용자가 페이지를 스크롤 하거나, 브라우저 창의 크기를 조절하는 것 등
- JavaScript를 통해 특정 객체에 이벤트가 일어나는 것을 감지할 수 있으며 그러한 이벤트들에 대응해서 어떤 일을 할 지 설정할 수 있다.
2) 이벤트 객체(event object)
- 이벤트가 발생했을 때 이벤트에 대한 정보와 기능을 담고 있는 객체
- 이벤트 객체는 이벤트가 발생할 때마다 자동으로 생성된다.
- 이렇게 생성된 이벤트 객체를 참조하고 싶다면 이벤트 핸들러의 매개변수로 받아 와서 활용할 수 있다.
2. 이벤트 관련 용어
⊙ 이벤트 이름(Event name), 이벤트 타입(Event type)
⊙ 이벤트 속성(Event attribute)
- 객체의 이벤트 속성. 이벤트가 발생하면 이벤트 속성과 연결된 이벤트 핸들러 확인
⊙ 이벤트 핸들러(Event handler)
- 이벤트가 발생했을 때 처리할 기능
<script>
window.onload = function () {...};
// onload → 이벤트 속성
// function () {} → 이벤트 핸들러
document.getElementById("header").onclick = function () {
// onclick → 이벤트 속성
// function () {} → 이벤트 핸들러(익명 함수)
alert("Hello World!");
};
</script>
예제) 이벤트 강제 발생
<script>
var hello = document.getElementById("hello");
var button = document.getElementsByTagName("button")[0];
// → 객체의 배열 반환
hello.onclick = function () {
alert("Hello World!");
button.onclick();
// → 이벤트 속성에는 이벤트 핸들러가 연결되어 있기 때문에
// 이벤트 속성을 함수로써 실행시킨다는 것은 이벤트를 강제 발생시키는 것과 같다!
};
button.onclick = sayHello;
function sayHello() {
alert("Hello JavaScript!");
}
</script>
연습문제 1)
: h1 요소를 클릭하면 그 요소가 1초에 걸쳐 점차 흐릿해지면서 화면에서 사라지는 프로그램과 button 요소를 클릭하면 h1의 배경 색상과 글자 색상을 바꾸는 프로그램을 작성하라.
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta charset="utf-8">
<title>demo</title>
<link rel="stylesheet" href="reset.css">
<style>
body {
background-color: black;
}
#hello {
width: 360px; height: 100px;
line-height: 100px;
margin: 50px auto 0;
color: white;
font-size: 35px;
font-weight: 900;
text-align: center;
cursor: pointer;
}
p {
width: 360px;
margin: 25px auto;
}
button {
height: 50px;
}
</style>
</head>
<body>
<h1 id="hello">Hello World!</h1>
<p>
<button id="bg">bacground-color: yellowgreen</button>
<button id="color">color: navy</button>
<button id="reset">RESET</button>
</p>
<script>
var hello = document.getElementById("hello");
hello.onclick = function () {
// 이벤트 핸들러: #hello 요소에 click 이벤트가 발생하면 실행할 기능
// this 키워드: 메서드에서 객체를 나타내는 키워드
// → 따라서 이벤트 핸들러에서는 this 키워드가 "이벤트가 발생한 객체"를 나타낸다.
// 여기에서는 #hello 요소를 표현하는 Element 객체가 된다.
//#hello 요소가 1초에 걸쳐 흐릿하게 사라지도록 한다.
this.style.transition = "1s ease-in";
this.style.opacity = "0";
this.style.visibility = "hidden";
};
document.getElementById("bg").onclick = bg_color;
// 익명 함수가 아닌 선언적 함수를 식별자를 통해 대입하는 것도 가능하다.
// document.getElementById("bg").onclick = sample_1();
// → sample_();는 함수를 호출하는 표현식이므로 이 문장은 틀린 문장이다.
// 함수 자체를 대입해야 한다.
document.getElementById("color").onclick = font_color;
document.getElementById("reset").onclick = function () {
// 이벤트 핸들러 : #reset 요소에 click 이벤트가 발생하면 실행할 기능
// #hello 요소에 적용했던 스타일 속성 제거
// hello.style.backgroundColor = "";
// hello.style.color = "";
hello.removeAttribute("style");
};
// 이벤트 핸들러 (선언적 함수 1) : #bg 요소에 click 이벤트가 발생하면 실행할 기능
function bg_color() {
// #hello 요소의 배경색 변경
hello.style.backgroundColor = "yellowgreen";
};
// 이벤트 핸들러 (선언적 함수 2) : #color 요소에 click 이벤트가 발생하면 실행할 기능
function font_color() {
// #hello 요소의 글자색 변경
hello.style.color = "navy";
};
</script>
</body>
</html>


연습문제 2)
: button 요소를 클릭하면 h1 요소의 글자 색상을 red로 바꾸거나 본래 상태로 되돌리는 프로그램을 작성하라.
이때 button의 요소의 내부 문자는 버튼의 기능에 따라 바뀌도록 한다.
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta charset="utf-8">
<title>demo</title>
<link rel="stylesheet" href="reset.css">
<style>
body {
background-color: black;
color: white;
}
#container {
width: 350px;
margin: 100px auto;
}
#hello {
display: block;
font-size: 50px;
font-weight: 900;
letter-spacing: -1px;
text-align: center;
line-height: 80px;
background-color: #444;
border-radius: 10px;
}
#color {
width: 80px;
line-height: 2;
margin: 25px 135px;
}
</style>
</head>
<body>
<div id="container">
<h1 id="hello">Hello World!</h1>
<button id="color">COLOR</button>
</div>
<script>
//---------------------------------------------------------------------------
// 1. #color 요소를 클릭하면
// 2-1. #color 요소의 내부 문자가 "COLOR"이면
// 2-2 = (#hello 요소의 color 스타일 속성의 값이 없으면)
// 3. #hello 요소의 글자 색상을 빨간색으로 바꾸고
// 4. #color 요소의 내부 문자를 "RESET"으로 바꾼다.
// 5. 그렇지 않으면
// 6. #hello 요소의 글자 색상을 본래 색상으로 되돌리고
// 7. #color 요소의 내부 문자를 "COLOR"으로 바꾼다
//----------------------------------------------------------------------------
// 1. #color 요소를 클릭하면
// → #color 요소에 click 이벤트 핸들러를 연결해서 구현
document.getElementById("color").onclick = function () {
// 이벤트 핸들러: #color 요소에 click 이벤트가 발생하면 실행할 기능
// JavaScript에서 거짓을 의미하는 값
// 1. number - 0
// 2. string - ""
// 3. boolean - false
// 4. function - function () {}
// 5. object - {}, []
// 6. undefined
// 2-1. #color 요소의 내부 문자가 "COLOR"이면
// 2-2. #hello 요소의 color 스타일 속성의 값이 없으면
// → if (!hello.style.color)
if (this.innerHTML == "COLOR") {
// 3. #hello 요소의 글자 색상을 빨간색으로 바꾸고
hello.style.color = "red";
// 4. #color 요소의 내부 문자를 "RESET"으로 바꾼다.
this.innerHTML = "RESET";
}
// 5. 그렇지 않으면
else {
// 6. #hello 요소의 글자 색상을 본래 색상으로 되돌리고
hello.style.color = "";
// 7. #color 요소의 내부 문자를 "COLOR"으로 바꾼다
this.innerHTML = "COLOR";
}
};
</script>
</body>
</html>

3. 이벤트 전달

⊙ 이벤트 전달(event propagation)
- 하위 요소에서 발생한 이벤트는 상위 요소들에게 순차적으로 전달된다.
- 하위 요소에서 발생한 이벤트가 상위 요소에게 전달되지 않도록 막는 것을 "이벤트 전달을 제거한다"라고 표현한다.
- 이벤트 전달을 제거하는 방법 : 이벤트 객체의 stopPropagation 메서드를 호출
- 다른 요소에서 발생한 이벤트가 중첩된 다른 요소로 전달된다.
- JavaScript에서는 "이벤트 버블링" 방식에 따라 이벤트가 전달된다.
- 이벤트 버블링 : 하위 요소에서 상위 요소로 이벤트가 전달되는 방식
- 이벤트 캡처링 : 상위 요소에서 하위 요소로 이벤트가 전달되는 방식


4. 표준 이벤트 모델
⊙ 표준 이벤트 모델
- W3C에서 지정한 DOM Level 2 이벤트 모델
- 하나의 요소에 여러 이벤트 핸들러 추가 기능
- 이벤트 캡처링 지원
- IE8 이전 버전에서는 지원하지 않음
|
element.addEventListener( eventName, handler, useCapure ); element.addEventListener( eventName, handler );
eventName은 이벤트 속성이 아니라 이벤트 이름을 나타낸다. 여기서 useCapure는 이벤트 캡처링 사용 여부(boolean)를 나타내고 생략 가능하다(생략 시 false). |
5. 기본 이벤트(default event)
- 몇몇 HTML 요소들은 이벤트 핸들러를 연결하지 않아도 기본적으로 가지고 있는 기능들이 있다.
이를 "기본 이벤트"라고 한다.
- 대표적으로 a 요소, input 요소, form 요소 등이 있다.
- 상황에 따라서는 이러한 기본 이벤트가 동작하지 않도록 제거해야 한다.
이를 "기본 이벤트를 제거한다"라고 표현한다.
- 기본 이벤트를 제거하는 2가지 방법
- 이벤트 객체의 preventDefault 메서드 호출 (주로 이 방법을 많이 쓴다.)
- 이벤트 핸들러에서 false 반환
예제)
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta charset="utf-8">
<title>demo</title>
<link rel="stylesheet" href="reset.css">
<style>
body {
background-color: black;
}
#container {
width: 200px;
padding: 20px 40px;
margin: 30px auto;
background-color: #555;
border-radius: 10px;
}
#google {
display: block;
text-align: center;
}
</style>
</head>
<body>
<div id="container">
<a href="http://www.google.com" id="google">Google</a>
</div>
<script>
document.querySelector("#google").onclick = function (event) {
// 이벤트 핸들러: #google 요소에 click 이벤트가 발생하면 실행할 기능
// #google 요소는 a 요소이므로 click 이벤트가 발생하면 href 속성에 지정해 놓은
// URL로 이동하는 것이 기본 이벤트이다.
// 필요에 따라 이 기본 이벤트를 제거할 수 있고 제거하게 되면 url로 이동하지 않고
// 인라인 스타일 속성에 지정되어 있는 스타일 속성만 적용된다.
// 기본 이벤트를 제거하는 첫 번째 방법
// → 이벤트 객체의 preventDefault 메서드 호출
event.preventDefault();
// 이벤트 전달 제거
// → #google에 발생한 이벤트를 상위 요소들(#container, body, html)
// 에게 전달되는 것을 막기 위해
event.stopPropagation();
this.style.color = "hotpink";
// 기본 이벤트를 제거하는 두 번째 방법
// return false;
// 이 방법은 스타일 속성이 적용된 후에 작성되어야 한다.(순서 중요)
};
document.querySelector("#container").onclick = function () {
// 이벤트 핸들러: #container 요소에 click 이벤트가 발생하면 실행할 기능
this.style.backgroundColor = "navy";
// 하위 요소(#google)에 발생한 이벤트는 상위 요소들(#container, body, html)
// 에게 순차적으로 전달되므로 하위 요소에 이벤트 전달 제거를 해주지 않으면
// #google을 클릭(onclick)하게 되면 상위 요소에 적용했던 스타일 속성까지 동시에 나타난다.
// 그러므로 하위 요소(#google)에 "이벤트 전달을 제거"해야 한다
};
</script>
</body>

몇 백줄이 지난 후, #google 요소의 이벤트 핸들러를 이미 작성했다는 사실을 잊어버려 다시 작성했다고 가정해보면
<script>
document.querySelector("#google").onclick = function (event) {
event.preventDefault();
event.stopPropagation();
this.style.color = "hotpink";
};
document.querySelector("#container").onclick = function () {
this.style.backgroundColor = "navy";
};
//...
//...
document.querySelector("#google").onclick = function (event) {
// 이벤트 핸들러(#google 요소에 click 이벤트가 발생하면 실행할 기능)를 통해
// 스타일 속성을 "추가"할 목적으로 작성
event.preventDefault();
this.innerHTML = "Go Google!";
};
</script>

위와 같이 이벤트 핸들러를 통해 스타일 속성을 추가할 목적으로 작성했지만 추가되지 않고
기존에 적용되었던 스타일 속성을 덮어쓰게 된다.
변수에 또 다른 값을 대입하면 초기화되는 것과 같이 이와 같은 경우에도
여기서 작성된 스타일 속성이 앞에서 작성된 핸들러를 통해 실행할 스타일 속성을 덮어쓰게 된다.
이러한 문제점을 addEventListener를 통해 해결해야 한다.
<script>
document.querySelector("#google").onclick = function (event) {
event.preventDefault();
event.stopPropagation();
this.style.color = "hotpink";
};
document.querySelector("#container").onclick = function () {
this.style.backgroundColor = "navy";
};
//...
//...
document.querySelector("#google").addEventListener("click", function () {
// 기본 이벤트 제거
event.preventDefault();
// 스타일 속성 설정
this.innerHTML = "Go Google!";
});
// 이벤트 핸들러와 객체를 다룰 때는 되도록 addEventListener으로 작성하는 것이 좋다.
};
</script>
