나만의 To do list 만들기

1. html 구성하기

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="styles.css">
    <title>ToDoList</title>
</head>
<body>
    <div class="container-box">
        <div class="contents">
            <h1>To Do List</h1>
            <ul>
                <li>테스트</li>
            </ul>
        </div>
    </div>
</body>

먼저, HTML 부분입니다. 박스를 만들 container-box를 만들고 내용이 들어갈 contents를 위한 div를 만듭니다.

그리고 <h1> 태그를 이용해 제목을 쓰고 <ul>로 리스트를 만듭니다.

 

2. CSS로 꾸며주기

 

body {
    margin: 0;
    color: #ffffff;
    background-color: #0f0f0f
}

다음으로 CSS부분입니다. 기본적으로 body에 마진이 들어가 있으니 margin을 0으로 설정해 줍니다.

개인적으로 검은배경을 좋아해서 background-color를 검은색으로 설정하고 글자색을 하얀색으로 설정해줍니다.

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

body {
    margin: 0;
    color: #ffffff;
    background-color: #0f0f0f;
    font-family: 'Hi Melody', cursive;
}
.container-box {
    width: 800px;
    height: 500px;
    border: solid 5px #fff;
    margin-top: 100px;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
}
.contents h1 {
    margin-top: 30px;
    margin-bottom: 0px;
}
.contents ul {
    margin-top: 50px;
    
}
.contents li {
    width: 100%;
    border-bottom: solid 1px #fff;
}

fonts.google.com 사이트를 들어가서 글씨체를 고릅니다. 그리고 거기에 해당하는 url을 import 해줍니다.

container-box에 border를 넣어 박스를 만들어 줍니다.

박스를 가로 가운데 정렬 하기 위해 margin-left와 margin-right에 auto를 넣어줍니다.

마진을 이용해서 리스트 부분에 적당한 간격을 넣어주고 border-bottom을 이용해 밑줄도 넣어줍니다.

    <div class="inputlist">
        <h2>아래 입력칸에 오늘 할일을 입력해주세요</h2>
        <form>
            <input type="text" placeholder="해야할 일을 입력하세요">
        </form>
    </div>

이번에는 리스트를 입력받을 input칸을 만듭니다.

.inputlist {
    text-align: center;
    margin-top: 50px;
}
.inputlist h2 {
    margin-top: 0;
    margin-bottom: 10px;
}
input {
    text-align: center;
    font-family: 'Hi Melody', cursive;
    font-weight: bold;
    font-size: 18px;
    width: 500px;
    height: 30px;
}

input의 크기를 적당하게 넓히고 글씨체도 동일한 글씨체를 적용해 줍니다.

근데 이렇게 하면 input안에 글자를 입력할때도 바뀐 글씨체가 적용됩니다.

사용자가 입력하는 글씨체는 바꾸지 않고 placeholder에 있는 글씨체만 바꾸고 싶으면 input::placeholder 를 이용하면 됩니다.

 

이제 리스트를 입력하면 리스트가 만들어지게 자바스크립트를 입력해보겠습니다.

const containerBox = document.querySelector("#containerBox"),
    contents = containerBox.querySelector("#contents"),
    list = contents.querySelector("#list"),
    inputList = document.querySelector(".inputlist"),
    listForm = inputList.querySelector("#listForm"),
    input = listForm.querySelector("input");
const list_LS = "toDos";

let toDos = [];

먼저, 앞으로 사용할 list와 관련된 선택자들을 querySelector를 이용해 선택합니다.

그리고 localstorage를 이용해 웹에 정보를 저장하기 위해 빈object를 만들어줍니다.

 

function saveList(){
    localStorage.setItem(list_LS, JSON.stringify(toDos));
}

웹의 localStorage에 리스트를 저장하는 함수입니다.

localStorage.setItem(키이름, 키값): localStorage에 정보를 저장합니다.

JSON.stringify(): 객체를 JSON 문자열로 변환합니다.

 

function showingList(text){
    const li = document.createElement("li");
    const delbtn = document.createElement("button");
    const span = document.createElement("span");
    const listNum = toDos.length+1;
    delbtn.innerText = "(지우기)";
    delbtn.addEventListener("click", deleteList);
    span.innerText = text;
    list.appendChild(li);
    li.appendChild(span);
    li.appendChild(delbtn);
    li.id = listNum;
    const toDoObj = {
        text: text,
        id: listNum
    };
    toDos.push(toDoObj);
    saveList();
}

웹에 입력한 리스트를 보여주기 위한 함수입니다.

document.createElement(): 괄호 안에 있는 요소를 생성합니다.

리스트를 지울 수 있게 삭제버튼도 만듭니다.

입력한 텍스트와 번호를 짝지어주는 객체를 생성합니다.

입력된 리스트를 저장하는 saveList()함수를 실행합니다.

 

function deleteList(event){
    const btn = event.target;
    const li = btn.parentNode;
    list.removeChild(li);
    const cleanList = toDos.filter(function(toDo){
        return toDo.id !== parseInt(li.id);
    });
    toDos = cleanList;
    saveList();
}

삭제버튼을 누르면 해당되는 리스트를 지우는 함수입니다.

filter(): 주어진 함수를 통과하는 모든 요소를 모아 재배열 합니다.

parseInt(): 문자열 인자의 구문을 분석해 특정 진수의 정수를 반환합니다.

 

function handleSubmit(event){
    event.preventDefault();
    const currentValue = input.value;
    showingList(currentValue);
    input.value = "";
}

input에 입력한 값을 다루는 함수입니다.

event.preventDefault(): 이벤트를 취소할 수 있는 경우, 이벤트의 전파를 막지않고 그 이벤트를 취소합니다.

event.preventDefault()를 사용하지 않아도 정상적인 작동은 되는것으로 보이지만 매번 새로고침이 됩니다. 이와 관련되어서는 다른 포스팅을 참고해주시길 바랍니다.

https://porimp.tistory.com/19

 

(자바스크립트/JavaScript)이벤트 버블링, 캡쳐, 이벤트 취소하기(preventDefault, stopPropagation)

이벤트 버블링(Event Bubbling) 웹에서 이벤트를 감지하는 방식 중 하나입니다. 이벤트의 버블링은 이벤트가 감지되었을 때, 해당 요소를 포함하고 있는 최상위요소까지 이벤트가 전파 되는 것을 의미합니다. 아래..

porimp.tistory.com

 

function loadList(){
    const loadedList = localStorage.getItem(list_LS);
    if(loadedList !== null){
        const parsedData = JSON.parse(loadedList);
        parsedData.forEach(function(toDo){
            showingList(toDo.text);
        });
    }
}

리스트를 불러오는 함수입니다.

localstorage에 저장한 리스트를 불러옵니다.

JSON.parse(): JSON 문자열의 구문을 분석하고 자바스크립트 값이나 객체를 생성합니다.

불러온 리스트를 보여주는 showingList 함수를 실행합니다.

 

function init(){
    loadList();
    listForm.addEventListener("submit", handleSubmit);
}

init();

loadList함수를 실행합니다.

input 부분에서 submit 하는 이벤트가 발생하면 handleSubmit 함수를 실행합니다.

자바스크립트까지 구성해서 실행한 모습입니다.

리스트를 입력하면 리스트에 추가가 되며, 지우기버튼이 생깁니다.

 

이제 마지막으로 버튼과 전체적인 스타일을 다듬어줍니다.

button {
    font-family: 'Hi Melody', cursive;
    font-weight: bold;
    position: absolute;
    right: 50px;
    text-align: center;
    background-color: #fff;
    border-color: rgb(61, 61, 61);
    border-style: solid;
    border-radius: 5px;
}

완성한 모습 입니다.


전체코드

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="styles.css">
    <title>ToDoList</title>
</head>
<body>
    <div id="containerBox" class="container-box">
        <div id="contents" class="contents">
            <h1>To Do List</h1>
            <ul id="list"></ul>
        </div>
    </div>
    <div class="inputlist">
        <h2>아래 입력칸에 오늘 할일을 입력해주세요</h2>
        <form id="listForm">
            <input type="text" placeholder="해야할 일을 입력하세요">
        </form>
    </div>
    <script src="todo.js"></script>
</body>
</html>
@import url('https://fonts.googleapis.com/css?family=Hi+Melody&display=swap&subset=korean');

body {
    margin: 0;
    color: #ffffff;
    background-color: #0f0f0f;
    font-family: 'Hi Melody', cursive;
}

.container-box {
    position: relative;
    width: 800px;
    height: 500px;
    border: solid 5px #fff;
    margin-top: 100px;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
}
.contents h1 {
    margin-top: 30px;
    margin-bottom: 0px;
}
.contents ul {
    
    margin-top: 50px;
    
}
.contents li {
    width: 80%;
    margin-top: 10px;
    margin-left: 50px;
    border-bottom: solid 1px #fff;
}
.inputlist {
    text-align: center;
    margin-top: 50px;
}
.inputlist h2 {
    margin-top: 0;
    margin-bottom: 10px;
}
input {
    text-align: center;
    font-family: 'Hi Melody', cursive;
    font-weight: bold;
    font-size: 18px;
    width: 500px;
    height: 30px;
}
button {
    font-family: 'Hi Melody', cursive;
    font-weight: bold;
    position: absolute;
    right: 50px;
    text-align: center;
    background-color: #fff;
    border-color: rgb(61, 61, 61);
    border-style: solid;
    border-radius: 5px;
}
const containerBox = document.querySelector("#containerBox"),
    contents = containerBox.querySelector("#contents"),
    list = contents.querySelector("#list"),
    inputList = document.querySelector(".inputlist"),
    listForm = inputList.querySelector("#listForm"),
    input = listForm.querySelector("input");
const list_LS = "toDos";

let toDos = [];

function saveList(){
    localStorage.setItem(list_LS, JSON.stringify(toDos));
}

function deleteList(event){
    const btn = event.target;
    const li = btn.parentNode;
    list.removeChild(li);
    const cleanList = toDos.filter(function(toDo){
        return toDo.id !== parseInt(li.id);
    });
    toDos = cleanList;
    saveList();
}

function showingList(text){
    const li = document.createElement("li");
    const delbtn = document.createElement("button");
    const span = document.createElement("span");
    const listNum = toDos.length+1;
    delbtn.innerText = "(지우기)";
    delbtn.addEventListener("click", deleteList);
    span.innerText = text;
    list.appendChild(li);
    li.appendChild(span);
    li.appendChild(delbtn);
    li.id = listNum;
    const toDoObj = {
        text: text,
        id: listNum
    };
    toDos.push(toDoObj);
    saveList();
}

function handleSubmit(event){
    event.preventDefault();
    const currentValue = input.value;
    showingList(currentValue);
    input.value = "";
}

function loadList(){
    const loadedList = localStorage.getItem(list_LS);
    if(loadedList !== null){
        const parsedData = JSON.parse(loadedList);
        parsedData.forEach(function(toDo){
            showingList(toDo.text);
        });
    }
}

function init(){
    loadList();
    listForm.addEventListener("submit", handleSubmit);
}

init();

+ Recent posts