티스토리 뷰

WEB/JavaScript

TODO Dom & Event

Harimad 2022. 6. 14. 22:24

🎈실습자료: https://blog.kakaocdn.net/dna/84fqL/btrENHtVyVd/AAAAAAAAAAAAAAAAAAAAAHZwXkTDuKdwThuuxMSeJc51_4HMc3S0Gw1cGKdTqi0B/tfile.html?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=M9m96w%2FDvgb9T%2BucoKxFFU%2BgSns%3D


🎈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
댓글
다크모드
Document description javascript psychology
더보기 ,제목1 태그 호버