Study Web Development

12월 24일

이전으로

JavaScript

12. 이벤트

12-1 이벤트와 이벤트 속성

onchange
onload
onkeyup
이벤트 이름 설명 발생 순서
keydown 키보드가 눌러질 때 발생 1
keypress 글자가 입력될 때 발생(한글로는 사용할 수 없음) 2
keyup 키보드가 떼어질 때 발생 3

12-3 인라인 이벤트 모델

  1. 새 HTML 파일 s05_onchange.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>onchange</title>
<script type="text/javascript">
	function trans() {
		var x = document.getElementById('name');
		x.value = x.value.toUpperCase(); // 읽어온 데이터를 대문자로 변경해서 저장
	}
</script>
</head>
<body>
영어 단어 : <input type="text" id="name" onchange="trans();"> <!-- 데이터를 서버에 전송하지 않을 것이므로 <form> 태그 생략 -->
<p>입력 필드를 벗어나면 대문자로 변경됩니다.</p>
</body>
</html>
  1. 새 HTML 파일 s06_isNaN.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>isNaN 함수 활용</title>
<script type="text/javascript">
	function checkIt() {
		var age = document.getElementById('age');
		// 공백 처리
		if(age.value.trim()=='') {
			alert('나이를 입력하세요!');
			age.value = '';
			age.focus();
			return;
		}
		// 숫자인지 판별
		if(isNaN(age.value)) {
			alert('숫자만 입력 가능합니다!');
			age.value = '';
			age.focus();
			return;
		}
		// 정상적으로 입력한 경우
		alert('나이는 ' + age.value + '살입니다.');
	}
</script>
</head>
<body>
	<form>
		<input type="text" name="age" id="age" size="20">
		<input type="button" value="나이 확인" onclick="checkIt()">
	</form>
</body>
</html>

12-4 고전 이벤트 모델

  1. 새 HTML 파일 s07_onload.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>스크립트에서 이벤트 연결하기</title>
<script type="text/javascript">
	// 윈도우가 로드되면 onload와 연결된 함수를 실행
	// 이벤트 연결
	window.onload = function() { // 이벤트 속성 = 이벤트 핸들러(함수)
		alert('문서가 로드되었습니다');
		document.body.style.backgroundColor = 'gold';
		var notice = document.getElementById('notice');
		notice.innerHTML = '날씨 흐림!';
	};
</script>
</head>
<body>
	<div id="notice"></div>
</body>
</html>
  1. 새 HTML 파일 s08_onclick.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>스크립트에서 이벤트 연결하기</title>
<style type="text/css">
	div {
		background-color: pink;
	}
</style>
<script type="text/javascript">
	window.onload = function() {
		var header = document.getElementById('header');
		
		// 이벤트 핸들러
		function whenClick() {
			alert('CLICK');
		}
		
		// 이벤트 연결
		header.onclick = whenClick; // 이벤트 속성 = 이벤트 핸들러
		// header.onclick = whenClick(); // 이벤트를 연결하는 것이 아니라 함수가 1회만 호출되고 이벤트 발생시에는 함수가 호출되지 않음
		
		// 익명 함수로 이벤트 연결
		header.onclick = function() {
			header.style.backgroundColor = 'powderblue';
		};
	};
</script>
</head>
<body>
	<div id="header">클릭</div>
</body>
</html>
  1. 임의의 이미지 파일 Koala.jpgC:\javaWork\workspace_jsp\javaScript\src\main\webapp\images로 이동
  2. 새 HTML 파일 s09_onmouseover.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이미지 크기 변경하기</title>
<script type="text/javascript">
	window.onload = function() {
		var alink = document.getElementsByTagName('a');
		var bigImg = document.getElementById('bigImg');
		
		for(let i=0;i<alink.length;i++) {
			// 썸네일 마우스오버시 큰 이미지 보여주기
			alink[i].onmouseover = function() {
				bigImg.style.display = ''; // <img> 태그를 노출시킴
				bigImg.src = this.href; // 이벤트가 발생한 <a> 태그에서  이미지 경로를 읽어옴
				bigImg.width = 500;
				bigImg.height = 350;
			};
			// 썸네일 마우스오버 해제시 큰 이미지 감추기
			alink[i].onmouseout = function() {
				bigImg.style.display = 'none'; // <img> 태그 숨기기
			};
			// 썸네일 클릭시 무반응
			alink[i].onclick = function() {
				return false; // <a> 태그의 기본 이벤트인 링크 기능을 제거
			};
		}
	};
</script>
</head>
<body>
	<div>
		<a href="../images/Penguins.jpg"><img src="../images/Penguins.jpg" width="83" alt="펭귄 이미지"></a> <!-- 썸네일용 작은 크기 이미지를 별도로 준비할 경우 <a> 태그에는 큰 이미지 경로, <img> 태그에는 썸네일 이미지 경로를 사용 -->
		<a href="../images/Koala.jpg"><img src="../images/Koala.jpg" width="83" alt="코알라 이미지"></a>
	</div>
	<div>
		<img id="bigImg" style="display: none;">
	</div>
</body>
</html>
  1. 새 HTML 파일 s10_onclick.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>radio와 이벤트</title>
<script type="text/javascript">
	window.onload = function() {
		var radios = document.getElementsByName('price');
		var fee = document.getElementById('fee');
		
		for(let i=0;i<radios.length;i++) {
			radios[i].onclick = function() {
				if(this.value=='1' && this.checked) { // 유료 radio 버튼 선택시 가입비 안내를 보여주기
					fee.style.display = '';
				}
				else { // 무료 radio 버튼 선택시 가입비 안내를 감추기
					fee.style.display = 'none';
				}
			};
		}
	};
</script>
</head>
<body>
	<form>
		<label><input type="radio" name="price" value="0" checked>무료</label>
		<label><input type="radio" name="price" value="1">유료</label>
	</form>
	<div id="fee" style="display: none;">
		유료 회원 가입비는 10,000원입니다.
	</div>
</body>
</html>
  1. 새 HTML 파일 s11_onkeyup.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>onkeyup</title>
<script type="text/javascript">
/* 
이벤트 이름		설명									발생 순서
keydown		키보드가 눌러질 때 발생					1
keypress	글자가 입력될 때 발생(한글로 사용할 수 없음)	2
keyup		키보드가 떼어질 때 발생					3
*/
	window.onload = function() {
		// textarea
		var content = document.getElementById('content');
		// 이벤트 연결
		content.onkeyup = function() {
			// 입력한 글자 수 구하기
			var inputLength = this.value.length;
			// 남은 글자 수 구하기
			var remain = 150 - inputLength;
			// 문서 객체의 내용 변경
			var letter = document.getElementById('letter');
			letter.textContent = remain;	
		};
	};
</script>
</head>
<body>
	<h4 id="letter">150</h4>
	<textarea rows="5" cols="30" name="content" id="content"></textarea>
</body>
</html>
  1. 새 HTML 파일 s12_onsubmit.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>onsubmit</title>
<script type="text/javascript">
	window.onload = function() {
		var form = document.getElementById('register_form'); // submit 이벤트는 <input> 태그로 만들어진 버튼이 아니라 해당 태그를 포함한 <form> 태그에서 발생함
		// 이벤트 연결
		form.onsubmit = function() {
			var name = document.getElementById('name');
			if(name.value.trim() == '') { // 이름 칸에 아무것도 입력하지 않거나 공백만 입력한 경우
				alert('이름을 입력하세요!');
				name.value = ''; // 공백이 있을 경우 빈 문자열로 대체
				name.focus(); // 이름 칸으로 포커스
				return false; // submit되지 않도록 처리
			}
			var id = document.getElementById('id');
			if(id.value.trim() == '') {
				alert('아이디를 입력하세요!');
				id.value = '';
				id.focus();
				return false;
			}
			var password = document.getElementById('password');
			if(password.value.trim() == '') {
				alert('비밀번호를 입력하세요!');
				password.value = '';
				password.focus();
				return false;
			}
			var phone = document.getElementById('phone');
			if(phone.value.trim() == '') {
				alert('전화번호를 입력하세요!');
				phone.value = '';
				phone.focus();
				return false;
			}
			/*
			let inputs = document.querySelectorAll('li > input');
			let labels = document.querySelectorAll('li > label');
			for(let i=0;i<inputs.length;i++) {
				if(inputs[i].value.trim() == '') {
					alert(labels[i].innerHTML + '을/를 입력하세요!');
					inputs[i].value = '';
					inputs[i].focus();
					return false;
				}
			}
			*/
		};
	};
</script>
</head>
<body>
	<form id="register_form" action="a.jsp" method="post">
		<fieldset>
			<legend>회원 가입</legend>
			<ul>
				<li>
					<label for="name">이름</label>
					<input type="text" name="name" id="name" size="10" maxlength="10"> <!-- 입력받는 값의 최대 길이는 HTML 속성으로 제어할 수도 있고 JavaScript로 제어할 수도 있지만, 한 사이트 내에서는 일관된 방식으로 제어해야 함 -->
				</li>
				<li>
					<label for="id">아이디</label>
					<input type="text" name="id" id="id" size="10" maxlength="10">
				</li>
				<li>
					<label for="password">비밀번호</label>
					<input type="password" name="password" id="password" size="10" maxlength="10">
				</li>
				<li>
					<label for="phone">전화번호</label>
					<input type="text" name="phone" id="phone" size="15" maxlength="13">
				</li>
			</ul>
			<div align="center">
				<input type="submit" value="전송">
			</div>
		</fieldset>
	</form>
</body>
</html>
  1. 임의의 이미지 파일 img1.jpg부터 img7.jpgleft_btn.png, right_btn.pngC:\javaWork\workspace_jsp\javaScript\src\main\webapp\images로 이동
  2. 새 HTML 파일 s13_gallery.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>갤러리</title>
<style type="text/css">
	* {
		margin:0;
		padding:0;
	}
	#galleryWrap {
		width: 520px;
		margin: 0 auto;
		text-align: center;
	}
	#galleryWrap img {
		vertical-align: middle;
	}
	img#prev,img#next {
		cursor: pointer;
	}
</style>
<script type="text/javascript">
	window.onload = function() {
		var num = 1; // 이미지 파일명에 규칙성이 없는 경우, 이미지 경로 혹은 파일명을 문자열로 보관한 배열을 만들어서 처리 가능
		var gallery = document.getElementById('gallery');
		// 이벤트 연결
		document.getElementById('prev').onclick = function() {
			num--;
			if(num<1) num = 7;
			gallery.src = '../images/img' + num + '.jpg';		
			/*
			let currnum = Number(gallery.src.charAt(gallery.src.length-5));
			num = currnum - 1;
			if(num<1) num = 7;
			gallery.src = gallery.src.replace(currnum, num);
			*/
		};
		document.getElementById('next').onclick = function() {
			num++;
			if(num>7) num = 1;
			gallery.src = '../images/img' + num + '.jpg';
		};
	};
</script>
</head>
<body>
	<div id="galleryWrap">
		<h1>이미지 넘기기</h1>
		<p>
			<img src="../images/left_btn.png" alt="이전 그림 보기" id="prev">
			<img src="../images/img1.jpg" alt="갤러리 그림" id="gallery">
			<img src="../images/right_btn.png" alt="다음 그림 보기" id="next">
		</p>
	</div>
</body>
</html>

12-6 기본 이벤트의 의미와 기본 이벤트 제거

  1. 새 HTML 파일 s14_default.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>기본 이벤트</title>
<script type="text/javascript">
	window.onload = function() {
		// <a> 태그에 이벤트 연결
		document.getElementById('alink').onclick = function() { // <a> 태그가 담긴 문서 객체는 이벤트 연결시   번만 사용되므로 굳이 변수를 만들 필요 없음
			alert('이벤트 연결');
		
			// 기본 이벤트 제거
			return false;
		};
		
		// <form> 태그에 이벤트 연결
		document.getElementById('myForm').onsubmit = function() {
			var name = document.getElementById('name');
			alert(name.value);
		
			// 기본 이벤트 제거
			return false;
		};
	};
</script>
</head>
<body>
	<a id="alink" href="https://www.naver.com">이동</a>
	<form id="myForm" action="a.jsp" method="post">
		이름 <input type="text" name="name" id="name">
		<input type="submit" value="전송">
	</form>
</body>
</html>

12-7 이벤트 전달

  1. 새 HTML 파일 s15_propagation.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>이벤트 전달</title>
<script type="text/javascript">
/* 
이벤트 버블링(기본) : 자식 노드에서 부모 노드 순으로 이벤트를 실행하는 것을 의미
이벤트 캡쳐링 : 부모 노드에서 자식 노드 순으로 이벤트를 실행하는 것을 의미

이벤트 버블링
div
|		^
div		|
|		|	자식 노드에서 부모 노드로 이벤트 전파
p		|
|		|
span	이벤트 발생

이벤트 캡쳐링
div	이벤트 발생
|		|
div		|
|		|	부모 노드에서 자식 노드로 이벤트 전파
p		|
|		v
span
*/
	window.onload = function() {
		// <h1> 태그에 이벤트 연결
		document.getElementById('header').onclick = function() {
			alert('header');
			this.style.background = 'pink';
		};
		// <p> 태그에 이벤트 연결
		document.getElementById('paragraph').onclick = function(event) { // 이벤트 객체를 사용하려면 이벤트 핸들러의 매개 변수로 이벤트 객체를 전달받아야 함
			alert('paragraph');
			this.style.backgroundColor = 'gold';
			
			// 이벤트 전달 막기
			event.stopPropagation();
		};
		
	}
</script>
</head>
<body>
	<h1 id="header">Header
		<p id="paragraph">Paragraph</p>
	</h1>
</body>
</html>

12-4 고전 이벤트 모델

  1. 임의의 이미지 파일 shoes.jpg, bag.jpg, jeans.jpg, coat.jpg, giftCard.jpgC:\javaWork\workspace_jsp\javaScript\src\main\webapp\images로 이동
  2. 새 HTML 파일 s16_orderForm.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 구매</title>
<link rel="stylesheet" href="style.css">
<script type="text/javascript">
	// 상품의 가격 정보
	var product = {
		c0:200000,
		c1:100000,
		c2:50000,
		c3:150000,
		c4:100000
	};
	
	window.onload = function() {
		var sum = 0;
		var ship = 0;
		var inputs = document.getElementsByClassName('select');
		for(var i=0;i<inputs.length;i++) {
			inputs[i].onclick = function() {
				if(this.checked) { // 체크박스 선택시
					sum += product[this.id];
				}
				else { // 체크박스 해제시
					sum -= product[this.id];
				}
				
				// sum이 0이면 배송비도 0
				if(sum>0 && sum<300000) {
					ship = 5000;
				}
				else { 
					ship = 0;
				}
				
				var spans = document.getElementsByTagName('span');
				spans[0].innerHTML = sum; // 총 상품 가격
				spans[1].innerHTML = ship; // 배송비
				spans[2].innerHTML = sum + ship; // 총 상품 가격 + 배송비
			};
		}
	};
</script>
</head>
<body>
<!-- 
구매 물건 : 가방(20만원), 코트(10만원), 청바지(5만원), 식사권(15만원), 신발(10만원)
 -->
	<h2>상품 구매</h2>
	<table>
		<caption>상품 목록</caption>
		<tr>
			<td><img src="../images/bag.jpg"></td>
			<td><img src="../images/coat.jpg"></td>
			<td><img src="../images/jeans.jpg"></td>
			<td><img src="../images/giftCard.jpg"></td>
			<td><img src="../images/shoes.jpg"></td>
		</tr>
		<tr>
			<td><input id="c0" class="select" type="checkbox" name="goods" value="bag">bag</td>
			<td><input id="c1" class="select" type="checkbox" name="goods" value="coat">coat</td>
			<td><input id="c2" class="select" type="checkbox" name="goods" value="jeans">jeans</td>
			<td><input id="c3" class="select" type="checkbox" name="goods" value="giftCard">giftCard</td>
			<td><input id="c4" class="select" type="checkbox" name="goods" value="shoes">shoes</td>
		</tr>
		<tr id="price">
			<td>(20만원)</td>
			<td>(10만원)</td>
			<td>(5만원)</td>
			<td>(15만원)</td>
			<td>(10만원)</td>
		</tr>
		<tr height="100">
			<td colspan="5">* <b>30만원 미만 결제</b>시 5,000원의 배송비가 추가됩니다.</td>
		</tr>
		<tr>
			<td id="preview" colspan="5">총 상품 가격 <span>0</span>원 + 배송비 <span>0</span>원 = 총 주문 금액 <span id="total">0</span></td>
		</tr>
	</table>
</body>
</html>
  1. 새 CSS 파일 style.css 생성
@charset "UTF-8";
* {
	margin: 0;
	padding: 0;
}
h2 {
	margin-top: 40px;
	text-align: center;
}
table {
	margin: 40px auto;
	width: 600px;
}
td {
	padding-left: 10px;
}
img {
	width: 100px;	
}
#price {
	text-align: center;
}
#preview {
	border: 3px solid gray;
	margin: 30px auto;
	text-align: center;
	height: 50px;
}
span {
	font-size: 20px;
}
span#total {
	color: red;
}

다음으로