728x90
반응형
1) Event
1-1) DOMContentLoaded
1-2) Form 태그 이벤트 예제
1-3) Element 생성
1-4) 정리
2) 코드 실습 - Lotto 번호 뽑기(중복값, 정렬 이슈 해결)
1) Event
+) <script> 태그의 위치에 따른 출력값 변화( 코드 실행 예측을 통한 자바스크립트 동작 순서 파악 목적 )
<!-- HTML -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="./public/js/index.js" type="text/javascript"></script>
</head>
<body>
<div class="box"></div>
</body>
</html>
// JS
const box = document.querySelector(".box");
console.log(box); // null
/*
null 값이 출력된 이유
>> 바로 위의 html 문서 상 head 태그 내부에 있는 script 태그를 먼저 읽고, 자바스크립트 코드를 실행시키기 때문에 밑에 body 태그 내부의 div 태그가 읽히지 못해 해당 코드를 실행하면 결과값이 'null'이 반환됨!!
>> 즉, HTML 문서의 load가 완료되지 않은 상태에서 "querySelector"를 사용했기 때문에 "null"이 반환됨
>> "querySelector"를 실행하면 결과값으로 element를 가져오거나 null을 반환함!!
*/
// 만일 바로 위의 자바스크립트 코드는 고정한 채 html 문서 상 script 태그의 위치를 기존의 head 태그 내부에서 body 태그 내부 맨 아래에 위치시키면 위의 코드는 해당 element를 정상적으로 출력함!!
1-1) DOMContentLoaded
// DOMContentLoaded
// 브라우저가 load가 완료되면 DOMContentLoaded 이벤트를 한 번만 발동시킴
function init() {
console.log("hello world!");
const box = document.querySelector(".box");
console.log(box);
}
document.addEventListener("DOMContentLoaded", init);
1-2) Form 태그 이벤트 예제
<!-- HTML -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#error {
color: red;
font-size: 20px;
display: none;
}
</style>
</head>
<body>
<div class="box"></div>
<form method="get" id="loginForm" action="./">
<!-- form 태그의 action 속성은 페이지를 해당 값(주소)으로 이동시켜줌(여기서는 "./"을 통해 현재 페이지로 이동하도록 설정함) -->
<input type="text" id="uid" name="userid" value="" />
<!-- query string 형태(객체는 아니지만 객체 같은 형태 >> 여기서 key: name 속성의 값 / value: value 속성의 값)로 데이터를 전달함 -->
<input type="password" id="upw" name="userpw" value="" />
<button type="submit">로그인</button>
</form>
<div id="error">아이디나 패스워드가 비어있음!</div>
<ul id="userList"></ul>
<h3>비밀번호</h3>
<input type="password" id="pw" />
<h3>비밀번호 확인</h3>
<input type="password" id="repw" />
<div id="pwError"></div>
<script src="./public/js/index.js" type="text/javascript"></script>
</body>
</html>
// JS version1
function submitHandler() {
alert("!!!");
}
function init() {
const form = document.querySelector("#loginForm");
// console.log(form); // 코드 동작 확인용
form.addEventListener("submit", submitHandler);
// "submit" 이벤트는 form element에서만 이벤트 등록 가능.
}
document.addEventListener("DOMContentLoaded", init); // DOMContentLoaded: 호출시간이 언제이다를 명확히 정하는 것
// document.addEventListener("click", init); // 이벤트는 기본적으로 html 문서의 load가 완료된 이후 동작 가능함!!
// 이벤트의 경우, 최종적으로 html 파일이 로드가 완료된 이후에 수행될 수 있으므로 위의 querySelector 구문이 정상적으로 동작함!!
※ 여기서 "addEventListener"의 경우, 첫 번째 인자값에 정의된 event를 등록한 뒤 해당 event가 발생하면 두 번째 인자값에 정의된 callback 함수를 호출하여 실행시켜주는 역할을 함!!
// JS version2
/*
아이디랑 패스워드가 비어있지 않을 때
해당 정보를 가져와서
list를 만듦
1. 어디에 element를 추가할 것인지
2. 어떤 element를 추가할 것인지
3. 추가했던 element의 내용을 어떻게 만들지
4. 만들었던 element를 어떻게 추가할 것인지
*/
function submitHandler(e) {
// 여기서 submitHandler 함수는 이벤트 객체(e)를 받는다!!
e.preventDefault(); // preventDefault(): 기본적으로 해당 element가 가지고 있는 기능(ex. a 태그의 링크 이동 기능)을 막는 메서드
const uid = document.querySelector("#uid");
const upw = document.querySelector("#upw");
const error = document.querySelector("#error");
console.log(uid);
console.log("아이디는 : ", uid.value !== "");
console.log("패스워드는 : ", upw.value !== "");
if (uid.value !== "" && upw.value !== "") {
// e.target.submit();
const userList = document.querySelector("#userList");
const li = document.createElement("li");
li.innerHTML = uid.value + " " + upw.value;
userList.append(li);
// console.log(uid.value, upw.value); // 코드 내용 확인용
uid.value = "";
upw.value = "";
error.style = "display: none";
} else {
alert("아이디나 패스워드를 입력해주세요!");
error.style = "display: block;";
}
uid.focus(); // 아이디와 비밀번호 입력 후 혹은 아이디와 비밀번호를 입력하지 않은 경우, 자동적으로 "uid" id를 가진 input 태그에 커서가 가도록 하기 위한 용도!!
}
function init() {
const form = document.querySelector("#loginForm");
// console.log(form); // 코드 동작 확인용
form.addEventListener("submit", submitHandler);
// "submit" 이벤트는 form element에서만 이벤트 등록 가능.
}
document.addEventListener("DOMContentLoaded", init); // DOMContentLoaded: 웹 페이지 load가 완료되면 addEventListener에 지정된 콜백함수를 호출하여 실행하는 역할(호출시간이 언제이다를 명확히 정하는 역할)
// document.addEventListener("click", init);
// 이벤트의 경우, 최종적으로 html 파일이 로드가 완료된 이후에 수행할 수 있으므로 위의 querySelector 구문이 정상적으로 동작함!!
/*
submit 이벤트가 없을 경우
1. 브라우저에서 "submit" 버튼을 누르면
2. 내용(queryString: 객체처럼 'key:value'의 형태를 가지지만 객체는 아니다!!)을 만들어서 Action 값에 있는 URL로 이동함
*/
/*
submit 이벤트가 있을 경우
1. 브라우저에서 "submit" 버튼을 누르면
2. "submit" 이벤트를 발동시킴. 이후 submitHandler 함수가 호출되고 호출이 끝나면.
3. 내용(queryString: 객체처럼 'key:value'의 형태를 가지지만 객체는 아니다!!)을 만들어서 Action 값에 있는 URL로 이동함
Action 값에 있는 URL 이동을 막고 싶다면
submitHandler 함수 안에서 이벤트 객체를 받아서
"e.preventDefault()"
e.preventDefault()
>> 내용(queryString: 객체처럼 'key:value'의 형태를 가지지만 객체는 아니다!!)을 만들어서 Action 값에 있는 URL로 이동함
>> 위의 내용이 작동 안 됨!
이후 내가 원하는 시점에서 submit을 날리고 싶다면
e.target.submit()
*/
/*
1. 만약에 input이 비어 있다면. submit 안 날리고.
2. 비어 있다면 input 색깔을 바꾸기!
3. input이 채워져 있다면 submit 날리기!
1) 만약에 input이 비어있다면 submit 안 날리고
inptu 내용이 비어있다라는 것을 어떻게 알 수 있을까?
id="uid"인 input 박스를 가져오기
value 값도 가져오기
*/
※ preventDefault(): 기본적으로 해당 element가 가지고 있는 기능(ex. a 태그의 링크 이동 기능)을 막는 메서드
1-3) Element 생성
/*
js로 element 만들기
uid : web7722
upw : 1234
아이디: web7722 패스워드 : 1234
>> 로그인 버튼을 누르면 위와 같이 아이디와 패스워드 폼의 입력값이 계속 화면 영역에 쌓이도록 할 계획
* element 만들기
document.createElement(element 이름);
document.createElement('li'); // li element가 만들어짐!
* element 넣기
<ul id="userList"></ul>
// const userList = document.querySelector("#userList");
// console.dir(userList);
// append(); >> 자식 element를 추가하겠다는 의미!!
const userList = document.querySelector("#userList");
const liElement = document.createElement("li");
liElement.innerHTML = "hello world!";
userList.append(liElement);
*/
// JS(비밀번호/비밀번호 확인 form 비교 구문)
const pw = document.querySelector("#pw"); // 객체
const repw = document.querySelector("#repw");
const error = document.querySelector("#pwError");
function changeHandler(e) {
if (pw.value === "") {
error.style = "color: red;";
error.innerHTML = "비밀번호를 먼저 입력해주시기 바랍니다!";
pw.focus();
e.target.value = "";
return;
}
if (e.target.value === pw.value) {
error.style = "color: green;";
error.innerHTML = "패스워드가 일치합니다!";
} else {
error.style = "color: red;";
error.innerHTML = "패스워드가 일치하지 않습니다!";
}
}
/*
keyup : 키보드를 누르고 땠을 때 실행됨
keydown : 키보드를 누르고 있을 때마다 실행됨
keypress : 키보드를 누르고 있을 때 실행됨(한글 인식 안 됨)
*/
repw.addEventListener("keyup", changeHandler);
1-4) 정리
/*
1) Event
1-1) Element 생성
function submitHandler() {
alert("!!!");
}
function init() {
const form = document.querySelector("#loginForm");
// console.log(form); // 코드 동작 확인용
form.addEventListener("submit", submitHandler);
}
document.addEventListener("DOMContentLoaded", init); // 여기서 "DOMContentLoaded" 이벤트 등록이 완료됨
1-2) Event
click
keyup
DOMContentLoaded
<초점>
document // window(전역객체) 객체에 포함되어 있음
window
this // this를 써서 window를 가리킬 수 있음!!
1-3) DOM
DataType : Object - 참조 데이터
Method
- document.getElementById()
- document.getElementsClassName()
- document.getElementsTagName()
querySelector 방식이 좋아서 주로 이 방식을 사용함!!
- document.querySelector()
- document.querySelectorAll()
* HTML에서 직접 값을 주는 방식 >> onClick="alert('hello!')"
* Element.onClick = function(){}
- 1개의 element에 2개의 이벤트를 등록할 수 없음!
- 삭제하기 편하다!
* Element.addEventListener(이벤트, 콜백함수)
- 복수의 이벤트를 넣을 수 있음!
- 삭제하기 불편하다!
- 코드 형태가 너무 어렵다!(콜백함수의 개념을 사전에 알고 있어야 코드를 이해하고 사용할 수 있음)
Element.addEventListener(이벤트, callback)
// 위의 코드는 Element에 이벤트를 등록하겠다는 의미이며, 위의 이벤트가 발생할 시 callback 함수를 실행하라는 코드임!!
function listener(event, callback) {
// 자바스크립트가 "click"이라는 event가 올 때까지 멈췄다가 "click" event가 발생할 시 아래 코드를 실행시켜줌!!
if (event === ""click) {
callback()
}
}
listener('click', function(){})
Event Object...
function handler(e) {
console.log(e)
// 이벤트 객체에서 가장 자주 쓰이는 속성 3가지
e.target
e.type
e.preventDefault()
}
div.addEventListener('click', handler)
// 지금까지 배운 이벤트들(이외 이벤트는 따로 필요 시 추가로 알아볼 계획!!)
- submit
- click
- mouseover
- mouseout
- keyup
- keydown
- keypress
Property
+) CRUD
Create
Read
Update
Delete
- ToDoList
- Comment
- Board
>> CRUD 안에 ToDoList, Comment, Board가 포함됨!!
*/
2) 코드 실습 - Lotto 번호 뽑기(중복값, 정렬 이슈 해결)
/*
lotto 코드 구현 이슈
- 코드를 줄이는 refactoring 작업
- 중복값 제거
- 정렬
*/
lotto.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#lotto > li {
display: inline-block;
font-size: 40px;
width: 80px;
height: 80px;
border-radius: 40px;
text-align: center;
line-height: 80px;
margin: 30px;
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.3);
}
#lotto.none {
display: none;
}
/* 1 ~ 10 */
#lotto > li.a {
background: yellow;
}
/* 11 ~ 20 */
#lotto > li.b {
background: blue;
}
/* 21 ~ 30 */
#lotto > li.c {
background: red;
}
/* 31 ~ 40 */
#lotto > li.d {
background: gray;
}
/* 41 ~ 45 */
#lotto > li.e {
background: green;
}
</style>
</head>
<body>
<h1>로또번호 생성기</h1>
<ul id="lotto" class="none">
<li class="a"></li>
<li class="b"></li>
<li class="c"></li>
<li class="d"></li>
<li class="e"></li>
<li class="e"></li>
</ul>
<button id="btn">번호 생성</button>
<script src="./public/js/lotto.js" type="text/javascript"></script>
</body>
</html>
lotto.js
// 쉬운 것부터 하나하나 구현하는 것이 좋음!!
// 1. 번호생성 버튼을 누르면 #lotto element를 보이게 하고 싶음
// 1.1 번호생성 버튼에다가 이벤트(click)를 넣자
// 1.1.1 번호생성 element를 선택해서 가져올 수 있어야 함 = querySelector를 사용할 수 있어야 한다는 의미
// 1.1.2 #lotto 선택해서 가져오기
// 2. 랜덤 숫자를 뽑아서 부여하는 것
// 2.1 랜덤 숫자(1 ~ 45)를 뽑는 것
// 2.2 랜덤 숫자를 부여
// 2.2.1 클릭할 때 랜덤 값 생성해보기
// 2.2.2 랜덤 값 6개 만들기
// 2.2.3 element 선택 >> querySelectorAll() 사용
// 2.2.4 각각 순서에 맞게 내용을 넣어주기
// 문제 확인하기!
// 1. 색깔이 안 바뀜
// 1.1 내가 랜덤으로 뽑은 숫자의 범위가 어디에 해당되는지를 알아야 함
// (1~10, 11~20, 21~30, 31~40, 41~45)
// 1.1.1 12라는 숫자가 있을 때 1 ~ 10
// 9라는 숫자가 있을 때 1 ~ 10
// 1.2 input 1 ~ 45 >> 1 ~ 10 = a, 11 ~ 20 = b, 21 ~ 30 = c ...
// className을 활용해서 처리하자
// 2. 로또는 중복값이 없어야 함
// 배열에서 추출 값 제거(splice 활용) >> if 문을 통해 이미 추출한 값이 나오면 다시 랜덤으로 숫자를 돌려 추출하도록 함
// 이 경우 전체 횟수는 기존의 6번만 돌리려던 것에서 다시 숫자를 추출한 만큼 전체 수행 횟수가 늘어남!
// 현재는 코드로서 문제가 있다!!
const btn = document.querySelector("#btn");
const lottoDisplay = document.querySelector("#lotto");
const lottoBox = document.querySelectorAll("#lotto > li");
let lottoNum = [];
for (let i = 1; i < 46; i++) {
lottoNum.push(i);
}
function randomLotto() {
const random = Math.floor(Math.random() * 45) + 1;
// Math.floor(Math.random() * 45)는 0 ~ 44까지의 숫자를 랜덤하게 반환하는데
// 우리가 뽑으려는 숫자의 범위는 1 ~ 45이므로 1을 위의 코드에 더해준다!!
return random;
}
function randomFinal() {
let temp = [];
for (let i = 0; i < 6; i++) {
let randomNum = randomLotto();
// temp.push(randomLotto());
if (temp.length !== 0) {
for (let j = 0; j < temp.length; j++) {
if (temp[j] === randomNum) {
temp.splice(j, 1);
i--;
}
}
}
temp.push(randomNum);
}
// 랜덤 숫자 배열 오름차순 정렬 함수
function randomNumAsc(arr) {
let tempAsc;
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] - arr[j] > 0) {
tempAsc = arr[i];
arr[i] = arr[j];
arr[j] = tempAsc;
}
}
}
return arr;
}
return randomNumAsc(temp);
}
function between(num, min, max) {
if (min <= num && num <= max) {
return true;
}
return false;
}
// input 1 ~ 45
// 문제 1 ~ 10 = a, 11 ~ 20 = b, 21 ~ 30 = c ...
// output : a || b || c || d || e
function getClassName(num) {
if (between(num, 41, 45)) {
return "e";
}
if (between(num, 31, 40)) {
return "d";
}
if (between(num, 21, 30)) {
return "c";
}
if (between(num, 11, 20)) {
return "b";
}
if (between(num, 1, 10)) {
return "a";
}
}
function lottoHandler(e) {
/*
const num1 = randomLotto();
const num2 = randomLotto();
const num3 = randomLotto();
const num4 = randomLotto();
const num5 = randomLotto();
const num6 = randomLotto();
console.log(num1);
console.log(num2);
console.log(num3);
console.log(num4);
console.log(num5);
console.log(num6);
const num1ClassName = getClassName(num1);
const num2ClassName = getClassName(num2);
const num3ClassName = getClassName(num3);
const num4ClassName = getClassName(num4);
const num5ClassName = getClassName(num5);
const num6ClassName = getClassName(num6);
lottoBox[0].innerHTML = num1;
lottoBox[0].className = num1ClassName;
lottoBox[1].innerHTML = num2;
lottoBox[1].className = num2ClassName;
lottoBox[2].innerHTML = num3;
lottoBox[2].className = num3ClassName;
lottoBox[3].innerHTML = num4;
lottoBox[3].className = num4ClassName;
lottoBox[4].innerHTML = num5;
lottoBox[4].className = num5ClassName;
lottoBox[5].innerHTML = num6;
lottoBox[5].className = num6ClassName;
*/
// function linearSearch(array, target) {
// const length = array.length;
// for (let i = 0; i < length; i++) {
// if (array[i] === target) {
// return i;
// }
// }
// return -1;
// }
/*
for (let i = 0; i < 6; i++) {
num[i] = randomLotto();
lottoBox[i].innerHTML = num[i];
lottoBox[i].className = getClassName(num[i]);
}
*/
let num = randomFinal();
for (let i = 0; i < 6; i++) {
lottoBox[i].innerHTML = num[i];
lottoBox[i].className = getClassName(num[i]);
}
lottoDisplay.classList.remove("none");
}
btn.addEventListener("click", lottoHandler);
'DOM' 카테고리의 다른 글
DOM 기초(6) - 메뉴 / 서브메뉴, 이미지 슬라이드, 로또 (0) | 2022.11.14 |
---|---|
DOM 기초(5) - 이미지 슬라이드, preview / next 버튼 구현 (0) | 2022.11.11 |
DOM 기초(4) - setTimeout, setInterval, single thread, event loop (0) | 2022.11.10 |
DOM 기초(2) - Event, 코드 실습(Lotto) (0) | 2022.11.08 |
DOM 기초 - DOM, Window, Array (0) | 2022.11.07 |