티스토리 뷰

🎈HTML/CSS 설명은 이전 글 참고 : TODO HTML/CSS
HTML Code
더보기
<!DOCTYPE html>
<html lang="ko">
<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>Todo List</title>
<link rel="stylesheet" href="style.css">
<!-- Google Material Icons CDN -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<div class="wrapper">
<!-- HEADER START -->
<header>
<h1>Todo List</h1>
</header>
<!-- HEADER END -->
<!-- SECTION START -->
<section>
<!-- INPUT-CONTAINER START -->
<div class="input-container">
<input type="text" class="input-text">
<button class="add-button">추가</button>
</div>
<!-- INPUT-CONTAINER END -->
<!-- LIST-CONTAINER START -->
<div class="list-container">
<ul class="list">
<li>
<span class="like">
<i class="material-icons favorite">favorite_border</i>
</span>
<span class="item">JS TODO1</span>
<span class="manage">
<i class="material-icons check">done</i>
<i class="material-icons clear">clear</i>
</span>
</li>
<li>
<span class="like">
<i class="material-icons favorite">favorite</i>
</span>
<span class="item">JS TODO1</span>
<span class="manage">
<i class="material-icons check">done</i>
<i class="material-icons clear">clear</i>
</span>
</li>
</ul>
</div>
<!-- LIST-CONTAINER END -->
</section>
<!-- SECTION END -->
</div>
<script src="main.js"></script>
</body>
</html>
CSS Code
더보기
/* Initialize */
* {
margin: 0;
padding: 0;
outline: none;
}
li {
list-style: none;
}
.wrapper {
height: 100vh;
width: 100%;
/* 아이템 세로로 줄 세우기 */
display: flex;
flex-direction: column;
}
header {
color: white;
/* UI_Gradient.com */
background: linear-gradient(20deg, #78ffd6, #a8ff78);
padding: 1rem;
/* 가운데로 위치*/
display: flex;
justify-content: center;
align-items: center;
}
.input-container {
width: 100%;
height: 30px;
/* 위 아래로 꽉차게 stretch 된다. */
display: flex;
border-bottom: 1px solid #ccc;
}
.input-text {
width: 90%;
padding: 0.3rem;
border: none;
}
.add-button {
width: 10%;
background: #ea76a5;
color: #fff;
/* 버튼 클릭 시 사라지지 않는 테두리를 없을 때 */
border: none;
outline: none;
}
.add-button:hover {
cursor: pointer;
background-color: #ff0066;
}
.list li {
display: flex;
border-bottom: 1px solid #ccc;
padding: 1em;
align-items: center;
}
.like {
flex: 1;
}
.item {
flex: 8;
}
.manage {
flex: 1;
display: flex;
justify-content: space-between;
}
.like i {
color: salmon;
}
.check {
color: #38ef7d;
}
.clear {
color: salmon;
}
/* .list li 에 넣을 토글 클래스 설정 */
.done .item {
text-decoration: line-through;
}
.done .check {
visibility: hidden;
}
JS Code
CHECK POINT
1. list 태그에 템플릿 리터럴(아래)을 넣는 대신에 노가다로 태그 생성해서 삽입하는 방법 알아보기
const li = `<li>
<span class="like">
<i class="material-icons favorite">favorite_border</i>
</span>
<span class="item">${inputText.value}</span>
<span class="manage">
<i class="material-icons check">done</i>
<i class="material-icons clear">clear</i>
</span>
</li>`
list.innerHTML += li
2. Event 넣어보기
2-1. like 버튼을 눌렀을 때 e.target.className 과 e.target.innerText로 태그를 인식한다.
그 다음 e.target.innerText 를 원하는 대로 바꿔준다. (Google Material Icon은 innerText만 바꿔도 아이콘이 변함)
2-2. e.target 중에 특정 클래스가 있는지 확인하기 위해서 e.target.classList.contains(태그이름)을 사용한다.
2-3. 태그를 삭제하기 위해서 두 가지 방법이 있다.
① Element.remove() 메서드를 사용한다. ex) e.target.parentNode.remove() | Element는 DOM요소이다.
② Node.removeChild(child) 메서드를 사용한다. (Node는 document.querySelector(태그)한 녀석이다.)
완성코드
const $ = tag => document.querySelector(tag)
const $$ = tag => document.querySelectorAll(tag)
// Input Text와 Button Click 관련
const inputText = $('.input-text')
const addButton = $('.add-button')
const list = $('.list')
function addItem() {
// 인풋 텅비면 종료
if (!inputText.value.trim()) return
// like
const like = document.createElement('span')
const likeIcon = document.createElement('i')
like.classList.add('like')
likeIcon.classList.add('material-icons')
likeIcon.classList.add('favorite')
likeIcon.innerText = 'favorite_border'
like.appendChild(likeIcon)
// item
const item = document.createElement('span')
item.classList.add('item')
item.innerText = inputText.value
// check & clear
const manage = document.createElement('span')
const checkIcon = document.createElement('i')
const clearIcon = document.createElement('i')
manage.classList.add('manage')
checkIcon.classList.add('material-icons', 'check')
checkIcon.innerText = 'done'
clearIcon.classList.add('material-icons', 'clear')
clearIcon.innerText = 'clear'
manage.appendChild(checkIcon)
manage.appendChild(clearIcon)
// like + item + check & clear
const li = document.createElement('li')
li.appendChild(like)
li.appendChild(item)
li.appendChild(manage)
list.appendChild(li)
inputText.value = ''
inputText.focus()
// 편한 방법
// const li = `<li>
// <span class="like">
// <i class="material-icons favorite">favorite_border</i>
// </span>
// <span class="item">${inputText.value}</span>
// <span class="manage">
// <i class="material-icons check">done</i>
// <i class="material-icons clear">clear</i>
// </span>
// </li>`
// list.innerHTML += li
}
// Event - input
addButton.addEventListener('click', e => {
addItem()
})
inputText.addEventListener('keypress', e => {
if (e.key === 'Enter') {
addItem()
}
})
// Event
list.addEventListener('click', e => {
console.log(e)
console.log(e.target)
// Like Btn toggle
if (
e.target.className === 'material-icons favorite' &&
e.target.innerText === 'favorite'
) {
e.target.innerText = 'favorite_border'
} else if (
e.target.className === 'material-icons favorite' &&
e.target.innerText === 'favorite_border'
) {
e.target.innerText = 'favorite'
}
// Check Btn
if (e.target.classList.contains('check')) {
console.log(true)
e.target.parentNode.parentNode.classList.add('done')
}
// Delete Btn
if (e.target.classList.contains('clear')) {
// 방법 1
e.target.parentNode.parentNode.remove()
// 방법 2
// list.removeChild(e.target.parentNode.parentNode)
}
})
참고
이벤트 버블링, 이벤트 캡처 그리고 이벤트 위임까지
(기본) 이벤트 버블링, 이벤트 캡처링, 그리고 이벤트 위임까지 이벤트 전달 방식과 관련된 모든 것을 파헤쳐 봅니다.
joshua1988.github.io
'WEB > JavaScript' 카테고리의 다른 글
| 타자게임 - 데이터상태처리 (setInterval) & API 연동 (0) | 2022.06.16 |
|---|---|
| 타자게임 이벤트 처리 (basic) (0) | 2022.06.15 |
| [JS] HTTP API (0) | 2022.06.13 |
| [JS] DOM, Event (0) | 2022.06.13 |
| [JS] OOP란? (function, class, new) (0) | 2022.06.13 |
댓글