본문 바로가기
Programming/Project

Todo list 프로젝트 만들기 #2

by akter 2022. 2. 23.

저번에 만들었던 Todo list 프로젝트에 제가 원하는 기능을 더 추가하여 수정하고 Netlify라는 사이트를 통해 배포까지 해보았습니다.

 

https://hs-todo-list.netlify.app

 

To Do List

 

hs-todo-list.netlify.app

이렇게 Todo list 프로젝트를 만들어봤는데 어떤지 한 번씩 봐주시고, 댓글 같은 거 남겨주시면 감사하겠습니다.

우선 제가 원하는 추가 기능

1. enter키를 누를 시 input값을 list에 추가하기

2. input 값이 없을 시 alert로 "할 일을 입력해주십시오."라는 문구가 뜨게 구현하기

3. 모바일 환경에 맞게 구현하기

이렇게 세 가지의 추가 기능을 원해서 수정해봤습니다.

<!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>To Do List</title>
        <script src="https://kit.fontawesome.com/98f8ca3915.js" crossorigin="anonymous"></script>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div id = "todolist">   <!--전체적인 id-->
            <div class = "main_title">  <!--대제목-->
                <h1>To DO List</h1>
            </div>

            <div class = "input__section"> <!--할 일 적은 것을 받을 인풋 클래스-->
                <form onsubmit="return false;"> <!--엔터 누를 시 새로고침 방지-->
                    <div>
                        <input type="text" class="item" autofocus="true">
                    </div>
                    <div>
                        <button type="button" class="input__button"><i class="fas fa-plus-circle"></i></button>
                    </div>
                </form>
            </div>

            <div class="item__list"></div> <!--인풋 받은 할 일들을 리스트로 표시해줄 클래스-->

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

<!--autofocus = 웹 접속 시 해당 부분으로 포커싱한다-->

 

우선 전체적인 html입니다. 전에 게시물에 비해 달라진 점은 form 부분에 추가가 되었는데요. 좀 이따가 다시 설명드리겠습니다.

'use strict';   // strict 모드 사용

let itemList = [];                                          // itemList라는 배열 선언
let inputbutton = document.querySelector(".input__button"); // input__button 클래스 불러오기
let input = document.querySelector(".item")                 // item 클래스 불러오기
inputbutton.addEventListener("click", addItem);             // Click 이벤트 발생 시, addItem 함수 실행
input.addEventListener("keypress", (e) => {                 // enter키가 눌리는 이벤트 발생 시, addItem 함수 실행
    if (e.key === 'Enter') {
        addItem();
    }
});

/*  strict = JavaScript의 함정을 발견하여 오류로 통지해주는 구조
    let = 변수 선언
    const = 상수 선언
    document.querySelector = id나 class, 여러가지 선택자를 불러오는 기능
    addEventLIstener(이벤트이름, 콜백함수) = 어떠한 이벤트가 발생하였을 때, 함수를 불러오는 기능*/

 

이제 자바스크립트 부분인데요. 자바스크립트에는 좀 많은 부분이 추가가 되었습니다.

우선 기존에는 button을 눌러야만 input 값이 리스트에 추가가 되었었는데요. 저는 엔터키를 누를 때에도 input값이 리스트에 추가가 되었으면 좋겠어서

let input = document.querySelector(".item")					// item 클래스 불러오기

input.addEventListener("keypress", (e) => {                 // enter키가 눌리는 이벤트 발생 시, addItem 함수 실행
    if (e.key === 'Enter') {
        addItem();
    }

 

우선 input이라는 input 값을 적는 클래스인 item 클래스를 불러오는 함수를 선언하고, 이 함수는 'Enter' 키가 keypress 눌러지면 addItem() 클래스가 실행되도록 addEventListener을 통해 구현했습니다.

그리고 웹으로 실행을 해보니 input 값을 리스트에 추가는 되지만 그와 동시에 웹이 리프레쉬 되면서 웹이 초기화면으로 돌아가는 현상이 생겼습니다. 이것을 방지하기 위해 아래 같은 코드를 넣어주었습니다.

<form onsubmit="return false;"> <!--엔터 누를 시 새로고침 방지-->

 

위와 같이 onsubmit 값을 false를 주어 리프레쉬가 되는 것을 막아주었습니다.

그리고 input 값을 아무것도 주지 않고, 실행 시킬 경우 " " 값으로 리스트에 추가가 되었었는데, input에 아무 것도 주지 않으면 alert를 통해 "할 일을 입력해주십시오."라는 문구가 뜨면 좋을 거 같다는 생각이 들어 수정을 해줬습니다.

function addItem() {                                        // addItem이라는 콜백함수 선언
    const item = document.querySelector(".item").value;     // item 클래스에 입력된 값을 불러오기
    if (item === "") {                                      // item이 ""이면
        alert("할 일을 입력해주십시오.");                    // alert 실행
        return;
    }

    itemList.push(item);                            // itemList에 push
    document.querySelector(".item").value = "";     // push 후 item 클래스의 값을 제거
    document.querySelector(".item").focus();        // 제거 후 item 클래스에 포커싱
    showList();                                     // showList() 실행
}


/*  function = 함수를 선언
    value = 값
    push = 보내는 기능
 */

 

이와 같이 수정을 해주었는데요. item의 input 값이 ""일 시 alert를 통해 "할 일을 입력해주십시오."가 출력되도록 해주었고, input 값이 있으면 밑에 코딩처럼 itemList에 push하고 input값을 초기화하고 input에 포커싱이 되도록 해주었습니다. 

저는 이 과정이 너무 어려웠었는데요. 

function addItem() {                                    // addItem이라는 콜백함수 선언
    let item = document.querySelector(".item").value;   // item 클래스에 입력된 값을 불러오기
    if (item != null) {                                 // item이 null이 아닐 때
        itemList.push(item);                            // itemList에 push
        document.querySelector(".item").value = " ";    // push 후 item 클래스의 값을 제거
        document.querySelector(".item").focus();        // 제거 후 item 클래스에 포커싱
    }

    showList();                                         // showList() 실행

}

 

처음 한 코딩을 보시면 if로 item이 null이 아니면 이라고 처음에 주어서 item 값이 없으면 null이 나오겠다고 생각하게되어서

function addItem() {                                    // addItem이라는 콜백함수 선언
    let item = document.querySelector(".item").value;   // item 클래스에 입력된 값을 불러오기
    if (item != null) {                                 // item이 null이 아닐 때
        itemList.push(item);                            // itemList에 push
        document.querySelector(".item").value = " ";    // push 후 item 클래스의 값을 제거
        document.querySelector(".item").focus();        // 제거 후 item 클래스에 포커싱
    } else {
    	alert("할 일을 입력해주십시오.");
	}
    showList();                                         // showList() 실행

}

 

이렇게 수정을 해주었는데, 아무리 value 없이 실행해도 else문은 실행이 되지 않는 겁니다. 그래서 item 값을 알아보기 위해 console.log를 찍어봤습니다. 그러니 값이 없는 빈 값이 출력이 되었습니다.

그래서 저는 if에 item === "" 으로 일 때 alert("할 일을 입력해주십시오.")가 출력되도록 수정해주었고, 값이 있으면 그 값을 원래 했던 대로 리스트에 추가되도록 해주었습니다.

그 다음 리스트를 보여주는 showList()는 잘 실행되어서 그대로 두었습니다.

function showList() {       // showList() 함수 선언
    let list = "<ul>"   
    for (let i = 0; i <itemList.length; i++) {
        list += "<li>" + itemList[i] + "<span class='close' id=" + i + ">" + "\u00D7" + "</span></li>";
    }                       // close 클래스에 <li> 형태의 요소 생성과 x표 생성
    list += "</ul>";        // for문을 통해 배열에 들어오는 요소 <ul>형태로 list 변수에 담기
    document.querySelector(".item__list").innerHTML = list;     // innerHTML 속성으로 item__list 클래스에 list 변수 담기

    let deleteButtons = document.querySelectorAll(".close");    // querySelectorAll로 클래스가 close인 모든 element를 가져오기                                                                
    for (let i = 0; i < deleteButtons.length; i++) {
        deleteButtons[i].addEventListener("click", deleteItem); // click시 deleteItem 함수 실행
    }
}

/*  \u00D7 = X를 뜻하는 유니코드
    innerHTML = element에 포함된 HTML 또는 XML 마크업을 가져오거나 설정
 */

 

그리고 리스트 값을 삭제해주는 deleteItem()는 리스트 값을 삭제한 후 input에 포커싱이 되도록

document.querySelector(".item").focus();
 
 
을 추가해주었습니다.
 
function deleteItem() {                         // deleteItem() 함수 선언
    let id = this.getAttribute("id");           // id 속성 부여 및 가져오기
    itemList.splice(id, 1);                     // itemList에서 부여된 id부터 1까지 제거
    document.querySelector(".item").focus();    // input에 포커싱
    showList();                                 // showList() 실행
}

/*  Attribute = 속성
    getAttribute = 속성을 가져오는, 접근하는 함수
    splice = 배열에서 특정항목을 제거
 */
 
 

그리고 리스트 값을 체크 표시 할 수 있도록

let checkList = document.querySelector('.item__list');  // item__list 클래스 불러오기
checkList.addEventListener('click', event => {          
  if (event.target.tagName === 'LI') {
    event.target.classList.toggle('checked');
  }                                                     // click 시 checked가 존재한다면 제거, 존재하지 않다면 추가
});
 
 
checkList 함수를 위와 같이 주었습니다.
 
그리고 css를 통해 모바일 환경일 때를 생각해
 
@media screen and (max-width: 768px)

 

를 주어서 css를 추가해주었습니다. css의 전체적인 코드입니다.

@import url('https://fonts.googleapis.com/css2?family=Hi+Melody&display=swap');

body {
    background: linear-gradient(90deg, #02aab0, #00cdac);
    font-family: 'Hi Melody', cursive;
    margin-left: 0px;
    margin-right: 0px;
    caret-color: #02aab0;
}

#todolist {
    text-align: center;
}

.main_title {
    color: white;
    margin: 30px;
}

.input__section form {
    display: inline-flex;
    align-items: center;
}

.item {
    width: 300px;
    height: 30px;
    border-radius: 15px;
    border: 1px solid #fbe7c6;
    padding: 0 30px;
}

*:focus {
    outline: none;
}

.input__button {
    background-color: transparent;
    font-size: 30px;
    line-height: 60px;
    margin-left: 10px;
    color: white;
    border: 0;
    padding-top: 5px;
}

ul {
    margin: 0px;
    padding: 0px;
    list-style: none;
}

ul li {
    cursor: pointer;
    position: relative;
    padding: 12px 8px 12px 8px;
    background: #eee;
    font-size: 18px;
    transition: 0.3s;
}

ul li:hover {
    background: #ddd;
}

.close {
    position: absolute;
    right: 20px;
    top: 0px;
    align-items: center;
    text-align: center;
    margin: 8px 60px;
    padding: 4px 10px;
    border: none;
}

.close:hover {
    background: linear-gradient(90deg, #02aab0, #00cdac);
    border-radius: 100%;
    color: white;
}

ul li.checked {
    background: #ddd;
    color: #272341;
    text-decoration: line-through;
}

ul li.checked::before {
    content: "";
    position: absolute;
    border-color: #272341;
    border-style: solid;
    border-width: 0 2px 2px 0;
    top: 13px;
    left: 90px;
    transform: rotate(45deg);
    height: 15px;
    width: 7px;
}

@media screen and (max-width: 768px) {
    body {
        margin: 0;
    }

    #todolist {
        max-width: 100%;
    }

    .input__section form {
        display: inline-flex;
        align-items: center;
    }

    .item {
        width: 200px;
        height: 30px;
        border-radius: 15px;
        border: 1px solid #fbe7c6;
        padding: 0px 30px;
    }

    .close {
        position: absolute;
        right: 20px;
        top: 0px;
        align-items: center;
        text-align: center;
        margin: 8px 15px;
        padding: 4px 8px;
        border: none;
    }
}

 

여기까지 저의 to do list 프로젝트를 마치겠습니다. 읽어주셔서 감사합니다.

'Programming > Project' 카테고리의 다른 글

파이썬 tkiter로 간단한 GUI 계산기 만들기  (0) 2022.03.09
Todo list 프로젝트 만들기 #1  (0) 2022.02.19

댓글