본문 바로가기

Web Development/Front-end

[Javascript] TodoList

그냥 공부하다보니, 혼자 프로젝트해보는 경험이 계속 필요하겠더라구요.

클론코딩이던 뭐던 강의에서 익힌것이 100% 머리에 남아 활용할 수 없으니깐요.

 

그래서 이번엔 '투두리스트'를 한번 만들어봤습니다.

 

TodoList

ㅋㅋ 뭔가 디자인이 어정쩡하죠? ㅠㅠ 디자이너가 아닌 제 한계인듯요 ㅋㅋ..

아무튼, 어떻게 만들었을까요?

 

일단 순서도를 그렸어요. 제로초강의에서 배웠던것처럼요. ㅋㅋ

만들다보니 순서도대로 완벽히 간 것 같진않은데, 확실히 코드쓰다보면 어? 이거다음 뭐해야하지? 할 때 유용하더라구요.

todoList 순서도

 

자 그럼 만든 결과물 코드를 한번 살펴보겠습니다.

 

todo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Todo List</title>
    <link rel="stylesheet" href="todo.css">
</head>
<body>
    <div class=background></div>
    <header>
        <div class='date'></div>
        <div class='time'></div>
    </header>
    <h1>Blockmonkey's TodoList</h1>
    <form class='input_submit_form'>
        <div><input type="text" id='user_input' maxlength="15" placeholder="오늘 해야할 일을 입력해주세요" style = "width:305px; height: 50px; font-size: 25px;"></div>
        <input type="submit" value="입력" class='input_btn' style = "width:305px; height: 50px; font-size: 25px; margin-top: 20px;">
    </form>

    <div class='todo_list'>
    </div>
    <script src='todo.js'></script>
</body>
</html>

제가 써놓고도 복잡시럽네요;

일단, background 배경을 넣을 태그를하나 잡고, 시계를 만들 헤더를 만들고, <h1>태그로 제목부분을 만들어줬습니다.

그리고 form태그 안에, text입력창, 그리고 제출버튼을 만들어줬습니다.

그리고 그 아래에, todo_list를 출력할 부분을 만들어주고,

todo.js파일을 임포트해왔습니다.

 

todo.js(part1)

let user_input = document.getElementById('user_input');
let input_btn = document.querySelector('.input_btn');
let todolist = document.querySelector('.todo_list');
let time_blank = document.querySelector('.time');
let date_blank = document.querySelector('.date');
let data = [];
let delete_btn;
let lists;

input_btn.addEventListener('click', (event)=>{
    event.preventDefault();
    if(user_input.value !== ''){
        data.push(user_input.value);
        delete_btn = document.createElement('button');
        delete_btn.textContent = '삭제';
        lists = document.createElement('span');
        lists.textContent = data[data.length-1];
        lists.append(delete_btn);
        todolist.append(lists);
        user_input.value = '';
        user_input.focus();

        delete_btn.addEventListener('click', (event)=>{
            event.preventDefault();
            let 삭제버튼_부모_span = event.target.parentNode;
            let 삭제버튼_부모_부모_div = event.target.parentNode.parentNode;
            //span태그 삭제하기
            삭제버튼_부모_부모_div.removeChild(삭제버튼_부모_span);
            //데이터 삭제.
            let deleted_data_index = data.findIndex((item)=>{
                return item === 삭제버튼_부모_span.textContent.replace(/삭제/g, '');
            })
            data.splice(deleted_data_index, 1);
        });
    }
})

다음으로 만든 부분은, 입력버튼을 입력했을 때, 발생할 이벤트들입니다. 우선, 데이터셋(배열)하나와, 실제 눈에 보이는 부분을 분리해서 함께 매칭시키는 작업이라고하나? 이걸 해주는데 고생좀 했습니다. ㅠㅠ 아무튼..

 

그리고, 데이터를 입력할 때마다, 데이터셋(배열) 내에 사용자가 입력한 리스트 정보를 push해서 넣어줬습니다. 그리고, 각 투두리스트마다 삭제버튼이 필요하니, span << 여기에 투두리스트 입력값을 넣어주고, 그 span태그내에, button(삭제)을 넣어주고, 그리고 이것들을 모두 todolist출력할 HTML 부분에 넣어줬습니다. 또... focus를 해줘서 엔터나, 마우스 클릭 후에도 커서가 유지될 수 있도록 해줬습니다.

 

근데 이렇게 하니깐, 입력값이 없을때도 공리스트(빈리스트)가 생성되는 문제가 있더라구요. 그래서 if조건으로 사용자 입력값이 '' << 이렇게 비었을 때는 작동하지 않을 수 있도록 해줬습니다. 맨 위에 event.preventDefault() 이 부분은 새로고침 막아주는 역할을합니다.

 

그리고 삭제버튼에 이벤트리스너를 달아주는데..

target 아주 유용하더라구요. 원래 class이름을 매겨서 어떻게 해야하나 -_- 하면서 고민 많이 했습니다.

아무튼, 그래서 target을 이용해서, 삭제버튼에 맞는 span태그를 삭제할 수 있도록 만들어줬습니다.

 

data.Index << 이건 데이터셋 내에서 원하는 데이터의 인덱스값을 찾는 함수입니다. 여기서, 문제가 발생했는데요. span태그 내에, 사용자가 입력한 입력값 + 삭제(버튼이름) 이게 자꾸 같이 출력되는 것입니다. (Ex : HTML삭제, CSS삭제) 이런식으로요..

그래서, 저걸 뭐라불르던데.. 정규식이었나, 아무튼 저걸 이용하면, 삭제 << 이문자열을 '' << 이걸로 바꿔준다 ! 라는 의미입니다. 저걸통해서, 배열내에 인덱스값을 찾고, splice를 활용해, 데이터셋에서 그 값을 삭제하고 그럼, 자동적으로 화면에 출력되는 부분도 데이터셋에 없는 것을 출력할 수는 없으니 삭제되겟죠!

 

자 여기까지가 투두리스트 기본적인 내용들이었고, 다음은 날짜 출력부분입니다.

 

todo.js(part2)

//날짜출력부분.
let date = new Date;
const makeDay = () => {
    if(date.getDay() === 1){
        return '월';
    }
    if(date.getDay() === 2){
        return '월';
    }
    if(date.getDay() === 3){
        return '월';
    }
    if(date.getDay() === 4){
        return '월';
    }
    if(date.getDay() === 5){
        return '월';
    }
    if(date.getDay() === 6){
        return '월';
    } else {
        return '일';
    }
}

const makeHours = () => {
    if(date.getHours() < 10){
        return `0${date.getHours()}`;
    } else {
        return `${date.getHours()}`;
    }
}

const makeMinutes = () => {
    if(date.getMinutes() < 10){
        return `0${date.getMinutes()}`;
    } else {
        return `${date.getMinutes()}`
    }
}

const makeSeconds = () => {
    if(date.getSeconds() < 10){
        return `0${date.getSeconds()}`;
    } else {
        return `${date.getSeconds()}`;
    }
}

setInterval(()=>{
    date = new Date;
    let fullDate = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()} (${makeDay()})`
    let fullTime = `${makeHours()}:${makeMinutes()}:${makeSeconds()}`;
    date_blank.textContent = `현재날짜 : ${fullDate}`
    time_blank.textContent = `현재시간 : ${fullTime}`
}, 1000);

이런식으로 만들어줬는데요. 뭔 코드가 이리많아 싶은데,  음, newDate() << 날짜를 생성해주는 이 함수를 보면, 참 애매 모호하게 출력해요. 월화수목금토일 << 이건 1,2,3,4,5,6,7 이런식으로 출력하고, 시간을 출력하는 부분은 08 09 << 이렇게 출력하면 안건들겠는데, 한자리 시간일 경우에는 1 2 3 4 5 6 7 이러다가, 두자리 넘어가면 갑자기 10 11 이렇게 두자리로 변하는데, 보기 별로 잖아요, 그래서 그걸 함수 + 조건문으로 바꿔준 것입니다.

 

다음은 setInterval << 이건 저번에 게임만들면서 사용해봤습니다. setTimeout은 설정시간 이후 1회 실행, setInterval은 설정시간 간격마다 실행, 그럼 시간은 매초마다 갱신되면 되겟죠? 그래서 1000이라는 설정시간값을 주고, setInterval 내에 시간을 출력하는 부분을 넣어, 매초마다 시간이 실시간으로 흐를 수 있도록 설정해줍니다.

 

마지막으로 css는 설명드릴게 없어서; 저도 찾아보면서 다 친거라;; 공유만합니다.

todo.css

.background{
    background-image: url('./img/3.jpg');
    opacity: 0.7;
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
}

h1{
    font-family: Georgia, "Times New Roman", serif;
    color: black;
    text-align: center;
}

.input_submit_form{
    text-align: center;
}

.todo_list_div{
    text-align: center;
}

.todo_list{
    font-family: Fantasy, "Times New Roman", serif;
    margin-top:50px;
    list-style:none;
    text-align: center;
    color: black(24, 174, 220);
    font-size: 40px;
}

span{
    display: block;
}

header{
    font-family: Georgia, "Times New Roman", serif;
    color: rgb(56, 23, 175);
    font-size: x-large;
    position: fixed;
    font-size: large;
    font-weight: bolder;
    margin-left: 77%;
    border: 2mm ridge rgba(15, 51, 79, 0.906);
}

 

 

이제 슬슬 제로초 JS 강의도 막바지에 있습니다.

아마 이번주내에 모두 끝날 것 같구요.

음.. 저번에 잠시 포스팅을 쉬는동안..

Nodejs 200제, DoitNodejs등.. 여러 Node책을 봤는데, 계속 노드를 공부할지,

React도 공부해볼지 고민이네요...

 

아무튼 ! 이렇게 해서 ~ 이번엔 '투두리스트'를 만들어보는 시간을 가졌습니다 !