개인공부

[기본기 다지기] todo-list만들기_HTML,CSS,JS

chsua 2023. 1. 25. 15:27

todo list를 만들어 보았다.

바닐라 자바스크립트로 했는데

앞서 만든 심플한 게임은 하나의 요소를 변형시키는 정도였다면,

이번에는 하나의 요소가 변형되면 다른 요소도 같이 영향을 주는 것을 연습해보았다.

 


1. 실행화면

 

2. 내 코드 분석

  1) HTML

 

  2) CSS

 

  3) JS : 첫 번째 사진은 큰 개괄 정리

 

3. 실제 코드

  1) HTLM

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="./practice.css"/>
        <meta name="viewport" content="width=device-width">
        <title>practice</title>
    </head>

    <body>
        <header>
            <h1 class="title">To Do List</h1>
        </header>
        
        <main>

            <label class="input"> 할 일: 
                <input class="inputWork">
                <input class="submit" type="submit">
            </label>
            <div class="notYet">
                <h3>NOT YET</h3>
                <ul class="notYetList">
                    
                </ul>
            </div>

            <div class="complete">
                <H3>COMPLETE</H3>
                <ul class="completeList">

                </ul>
            </div>

        <main>
        <script src="practice.js"></script>
    </body>
</html>

 

2) CSS

body {
  width: 70%;
  margin: 0% auto;
  padding: 5%;
}

header {
  border-bottom: 3px solid black ;
  border-bottom-style: double;
  text-align: center;
}

main {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.input{
  margin: 3%;
  grid-column:1/3;
  text-align: center;
}

.notYet, .complete {
  background-color: rgb(243, 243, 243);
  width: 90%;
  margin: 3% auto;
  padding: 3%;
  padding-top: 1%;
  height: 400px;
}

.notYetList, .completeList {
  overflow:scroll;
  max-height: 80%;
}

h3 {
  position: relative;
  left: 8%;
}

.todo-item {
  display: flex;
  padding: 1%;
  align-items: center;
  font-size: smaller;
  position: relative;
  right: 8%;
}

.work {
  width: 90%;
  padding-left: 3%;

}

.complete .todo-item p{
  text-decoration: line-through;
  color: gray;
}

.amendInput{
  width: 90%;
  background-color: unset;
  border: 1px solid gray;
}

 

3) JS

const inputWork = document.querySelector(".inputWork");
const notYetList = document.querySelector(".notYetList");
const completeList = document.querySelector(".completeList");
const submit = document.querySelector(".submit");
const body = document.querySelector("body");


class Todo {

    constructor() {
        this.id = 0;
    }

    init() {
        submit.addEventListener("click", () => {
            this.makeTodoItem(notYetList, inputWork.value)
            inputWork.value = "";
        });

        inputWork.addEventListener("keypress", (event) => {
            if (event.key === "Enter") {
                this.makeTodoItem(notYetList, inputWork.value)
                inputWork.value = "";
            }
        })
    }

    makeTodoItem(place, inputText) {  //input 클릭시 발생
        const todoItemElem = document.createElement('li');
        todoItemElem.classList.add("todo-item");
        todoItemElem.setAttribute("id", this.id);
        place.appendChild(todoItemElem);
        this.id++;

        this.makeTodoItemChild(todoItemElem, inputText);
    }

    makeTodoItemChild(elem, text) {
        const checkboxElem = document.createElement('input');
        checkboxElem.setAttribute("type", "checkbox");   //set!!!!!
        elem.appendChild(checkboxElem);
        if (elem.parentElement.className === "completeList") checkboxElem.checked = true;
        checkboxElem.addEventListener('click', (e) => {
            const targetTodoItem = e.target.parentElement;
            const place = targetTodoItem.parentElement
            this.completeTodoItem(place.className, targetTodoItem.id);
        })

        const todoTextElem = document.createElement("P");
        todoTextElem.classList.add("work");
        todoTextElem.innerHTML = text;
        elem.appendChild(todoTextElem);
        todoTextElem.addEventListener('dblclick', (e) => {
            const target = e.target.parentElement;
            this.requestAmendTodoItem(target.id)
        })

        const buttonElem = document.createElement("button");
        buttonElem.classList.add("delBtn");
        buttonElem.innerText = "x";
        elem.appendChild(buttonElem);
        buttonElem.addEventListener('click', (e) => {
            const target = e.target.parentElement;
            this.deleteTodoItem(target.id);
        })
    }

    deleteTodoItem(id) {    //삭제 버튼 클릭시 발생
        const deleteElem = document.getElementById(id);
        deleteElem.remove();
    }

    completeTodoItem(place, id) {      //완료 체크박스 클릭시 발생
        const moveElem = document.getElementById(id);
        moveElem.remove();

        if (place === "notYetList") {
            completeList.appendChild(moveElem);
        } else {
            notYetList.appendChild(moveElem);
        }
    }

    requestAmendTodoItem(id) {         //더블클릭 p 누르면 발생
        const amendElem = document.getElementById(id);
        const amendWork = amendElem.getElementsByClassName("work");

        const inputElem = document.createElement('input');
        inputElem.classList.add("amendInput");
        inputElem.value = amendWork[0].textContent;

        //기존 내용 없애고 input 생성
        amendElem.innerHTML = "";
        amendElem.appendChild(inputElem);
        inputElem.focus();

        //input click/그 외 화면 터치 event 시
        inputElem.addEventListener("keypress", (event) => {
            if (event.key === "Enter") {
                this.makeTodoItemChild(amendElem, inputElem.value);
                inputElem.remove();
                body.removeEventListener("click", bodyClick);
            }
        })

        const bodyClick = (event) => {
            if (event.target !== inputElem) {
                this.makeTodoItemChild(amendElem, inputElem.value);
                inputElem.remove();
                body.removeEventListener("click", bodyClick);
            }
        };

        body.addEventListener("click", bodyClick);
    }



}

const todo = new Todo();
todo.init();