본문 바로가기

Language & Framework/실습

자바스크립트로 간단한 투두리스트 만들기.

자바스크립트 초보들이 모두 거쳐간다는 투두리스트.

사실 만든 지 좀 됐는데 요즘 블로그에 글 올릴 시간은 커녕 코딩할 시간도 없어서 허덕이던 터라 미루고 미루다 이제야 올린다..

작성하고, 지우고, 남은 할 일 개수를 카운트하는 아주 기본적인 기능만 가진 투두리스트다.

 

 

 

HTML / CSS

    <section class="todoList">
        <header class="todoList__title"><span>To Do List</span></header>
        <form class="inputContianer">
            <input type="text" name="textbox" id="todoInput">
            <label class="input__icon">+</label>
            <input type="text" name="emptyBox" id="" style="display:none">
        </form>
        <div class="todoList__main">
        </div>

        <footer class="todoList__foot">
            <p class="todoList__foot__task">You have 4 pending tasks</p><button class="todoList__foot__clearbtn">Clear
                All</button>
        </footer>
    </section>
* {
  box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */
  font-family: "Noto Sans KR", sans-serif;

  &::-webkit-scrollbar {
    display: none; /* Chrome, Safari, Opera*/
  }
}

button {
  outline: none;
  border: none;
}

body {
  margin: 0px;
  height: 100vh;
  background-image: linear-gradient(62deg, #8ec5fc 0%, #e0c3fc 100%);
  background-size: cover;
}

.todoList {
  display: flex;
  flex-direction: column;
  margin: 100px auto;
  width: 80%;
  max-width: 450px;
  height: 50%;
  text-align: center;
  background-color: white;
  padding: 20px;
  border: none;
  -webkit-box-shadow: 10px 11px 15px -2px #418d8e;
  box-shadow: 10px 11px 15px -2px #418d8e;
}

.todoList__title {
  width: 100%;
  height: 50px;
}

.todoList__title span {
  font-size: 25px;
  display: block;
  margin-top: 10px;
}

.inputContianer {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 30px;
  flex-wrap: nowrap;
  margin: 10px 0px;
}

#todoInput {
  width: 90%;
  border: 1px solid rgba(0, 0, 0, 0.2);
  height: 30px;
  font-size: 16px;
}

.input__icon {
  font-size: 23px;
  height: 100%;
  line-height: 27px;
  margin-left: 10px;
  cursor: pointer;
  background-color: blueviolet;
  color: white;
  font-weight: bold;
  width: 10%;

  &:hover {
    background-color: lightskyblue;
    transition: 300ms ease-in;
  }
}

.todoList__main {
  height: 300px;
  background-color: white;
  overflow-y: scroll;
}

.todoList__main__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-left: 20px;
  background-color: whitesmoke;
  margin: 10px 0px;
}

.trash {
  padding: 20px;
  cursor: pointer;

  &:hover {
    background-color: red;
    color: white;

    transition: 300ms ease-in;
  }
}

.todoList__foot {
  width: 100%;
  height: 50px;
  display: flex;
  font-size: 14px;
  align-items: center;
  padding-top: 20px;
  justify-content: space-between;
}

.todoList__foot__task {
  font-size: 13px;
}

.todoList__foot__clearbtn {
  width: 90px;
  height: 30px;
  background-color: blueviolet;
  outline: none;
  line-height: 10px;
  border: none;
  color: white;
  cursor: pointer;

  &:hover {
    background-color: lightskyblue;
    transition: 300ms ease-in;
  }
}

 

 

 

JavaScript

 

const textInput = document.querySelector("#todoInput");
const todoList = document.querySelector(".todoList__main");
const todoTask = document.querySelector(".todoList__foot__task");
todoTask.innerHTML = `You have ${todoList.childElementCount} pending tasks`;

const addBtn = document.querySelector(".input__icon");
const clearAllBtn = document.querySelector(".todoList__foot__clearBtn");

let idCount = 0;

textInput.addEventListener("change", handleInput);
todoList.addEventListener("click", deleteBtn);
clearAllBtn.addEventListener("click", clickClearAll);

function addToDo(text) {
  const todoItem = document.createElement("div");
  todoItem.className = "todoList__main__item";
  todoItem.dataset.id = `${idCount}`;
  todoItem.innerHTML = `<p class="todoList__main__item--text">${text}</p>
  <button class="trash deleteBtn" data-id=${idCount}>
      <i class="trash fa-solid fa-trash-can" data-id=${idCount}></i>
  </button>`;
  todoList.append(todoItem);
  idCount++;
  todoList.scrollTo(0, todoList.lastChild.getBoundingClientRect().y);
}

function ChangeTaskNum() {
  todoTask.innerHTML = `You have ${todoList.childElementCount} pending tasks`;
}

function handleInput(e) {
  if (textInput.value == undefined) {
    return;
  }
  addToDo(textInput.value);
  ChangeTaskNum();
  textInput.value = " ";
}

function deleteBtn(event) {
  let tagName = event.target.tagName;
  let targetCount = event.target.dataset.id;

  if (tagName !== "BUTTON" && tagName !== "I") {
    return;
  } else {
    let todoItem = document.querySelector(
      `.todoList__main__item[data-id="${targetCount}"]`
    );
    todoItem.remove();
  }
}

function clickClearAll() {
  while (todoList.hasChildNodes()) {
    todoList.removeChild(todoList.firstChild);
  }
  ChangeTaskNum();
}



별다른 특이사항은 없으나 당시에 나는 동적으로 HTML을 생성할 때 안에서 addEventListener를 만들어줄 수 있다는 사실을 모르고 일일히 dataset을 부여하고 삭제할 때마다 dataset을 대조하는 굉장히 비효율적인 방식으로 만들었다..