어느정도 왠만한 todo-list 같아졌다.
아래는 js 파일.
index.js
let todoList = [];
let completedList = [];
let num =1;
//returnId는 string
const todoListElement = document.querySelector(".todo-list");
const completedListElement = document.querySelector(".completed-list");
const initTodoDivElement = document.querySelector(".todo-initDiv");
const initTodoFormElement = document.querySelector(".todo-item");
const initTodoInputElement = document.querySelector("input");
const proposeNewTodoElement = document.querySelector(".todo-item-add");
/*로컬스토리지에 저장하는 함수들*/
const TODOS_KEY = "todos";
function saveToDos() { //로컬스토리지에 투두를 저장하는 함수
localStorage.setItem(TODOS_KEY, JSON.stringify(todoList));
}
const COMPLETEDS_KEY = "completeds";
function saveCompleted() { //로컬스토리지에 완료한 일을 저장하는 함수
localStorage.setItem(COMPLETEDS_KEY, JSON.stringify(completedList));
}
/*Handle 함수들(eventListener의 함수)*/
function handleToDoInitSubmit(event){ //처음에 할 일을 입력하고 저장했을 때
event.preventDefault();
const initTodo = initTodoInputElement.value;
const initTodoArr = [num,initTodo];
todoList.push(initTodoArr);
initTodoDivElement.remove();
paintTodo(initTodo);
paintProposeNewTodo();
saveToDos();
}
function handleButtonModify(event) //수정 버튼을 클릭했을 때
{ const mustDeleteTodoElement = event.target.parentElement;
const returnId = mustDeleteTodoElement.id;
const beforeModifyTodo = mustDeleteTodoElement.querySelector("span").innerText;
mustDeleteTodoElement.remove();
paintModifyTodo(beforeModifyTodo,returnId);
SendBackProposeNewTodo();
}
function handleButtonSave(event){ //수정 하고 submit했을 때. //한번 수정한 전적이 있는 투두는 이후 수정을 또 하고 저장해도 이 상태
event.preventDefault();
const mustDeleteTodoElement = event.target.parentElement.parentElement;
const returnId = mustDeleteTodoElement.id;
const afterModifyTodo = mustDeleteTodoElement.querySelector("input").value;
mustDeleteTodoElement.remove();
for (let todo of todoList){
if (todo[0] === parseInt(returnId)) {
todo[1] = afterModifyTodo;
};
}
saveToDos();
const div = document.createElement("div");
div.className ="todo-item";
div.id = returnId;
const span = document.createElement("span");
span.className = "todo-readonly";
span.innerText = afterModifyTodo;
const buttonModify = document.createElement("button");
buttonModify.innerText = "✏️";
buttonModify.addEventListener("click",handleButtonModify);
const buttonComplete = document.createElement("button");
buttonComplete.innerText = "✓";
buttonComplete.addEventListener("click",handleButtonComplete);
const buttonDelete = document.createElement("button");
buttonDelete.innerText = "❌";
buttonDelete.addEventListener("click",handleButtonDeleteReadonly);
div.appendChild(span);
div.appendChild(buttonModify);
div.appendChild(buttonComplete);
div.appendChild(buttonDelete);
todoListElement.appendChild(div);
SendBackProposeNewTodo();
}
function handleNewTodoElement() { //"할 일 추가"를 눌렀을 때
const proposeNewTodoElement = document.querySelector(".todo-item-add");
proposeNewTodoElement.remove()
PaintWriteTodo();
}
function handleToDoSubmit(event){ //새로운(not init) 할 일을 추가하고 submit했을 때
event.preventDefault();
const mustDeleteTodoElement = event.target.parentElement.parentElement;
const todo = mustDeleteTodoElement.querySelector("input").value;
mustDeleteTodoElement.remove();
const todoArr = [num,todo];
todoList.push(todoArr);
saveToDos();
paintTodo(todo);
paintProposeNewTodo();
}
function handleButtonComplete(event) { //완료(✓) 버튼을 눌렀을 때
const mustDeleteTodoElement = event.target.parentElement;
const returnId = mustDeleteTodoElement.id;
const completed = mustDeleteTodoElement.querySelector("span").innerText;
mustDeleteTodoElement.remove();
todoList = todoList.filter((element) =>element[0] !==parseInt(returnId));
saveToDos();
const completedArr = [parseInt(returnId),completed];
completedList.push(completedArr);
saveCompleted();
paintCompleted(completed,returnId);
}
function handleButtonUp(event) { //completed를 다시 todo로 올리는 버튼을 눌렀을 때
const mustDeleteTodoElement = event.target.parentElement;
const completed = mustDeleteTodoElement.querySelector("span").innerText;
const returnId = mustDeleteTodoElement.id;
mustDeleteTodoElement.remove();
const todoArr = [parseInt(returnId),completed];
todoList.push(todoArr);
saveToDos();
completedList = completedList.filter((element) =>element[0] !==parseInt(returnId));
saveCompleted();
paintTodo(completed,returnId);
SendBackProposeNewTodo();
}
function handleButtonDeleteReadonly(event) { //form 형식이 아닌 투두들을 지우는데 사용
const mustDeleteTodoElement = event.target.parentElement;
const returnId = mustDeleteTodoElement.id;
mustDeleteTodoElement.remove();
todoList = todoList.filter((element) =>element[0] !==parseInt(returnId));
saveToDos();
}
function handleButtonDeleteWhileModify(event) { //form 형식인 투두들을 지우는데 사용
event.preventDefault();
const mustDeleteTodoElement = event.target.parentElement.parentElement;
const returnId = mustDeleteTodoElement.id;
mustDeleteTodoElement.remove();
todoList = todoList.filter((element) =>element[0] !==parseInt(returnId));
saveToDos();
}
/* Paint functions*/
function PaintWriteTodo() { //todo를 새롭게 입력하는 상태 paint
const div = document.createElement("div");
num +=1;
div.id = num.toString();
const form = document.createElement("form");
form.className = "todo-item";
const input = document.createElement("input");
input.type = "text";
input.className = "todo-input";
input.placeholder= "할 일을 입력하세요";
const buttonSave = document.createElement("button");
buttonSave.type = "submit";
buttonSave.className = "save";
buttonSave.innerText = "저장";
buttonSave.addEventListener("click",handleToDoSubmit);
form.appendChild(input);
form.appendChild(buttonSave);
div.appendChild(form);
todoListElement.appendChild(div);
}
function paintTodo(todo,returnId){ //todo를 입력하고 저장하면 나타나는 상태 paint //수정 전에만 나타남.
const div = document.createElement("div");
div.className ="todo-item";
if (returnId === undefined)
{
div.id = num.toString();
}
else{ //completed였던 항목이 올라올 때
div.id = returnId;
}
const span = document.createElement("span");
span.className = "todo-readonly";
span.innerText = todo;
const buttonModify = document.createElement("button");
buttonModify.innerText = "✏️";
buttonModify.addEventListener("click",handleButtonModify);
const buttonComplete = document.createElement("button");
buttonComplete.innerText = "✓";
buttonComplete.addEventListener("click",handleButtonComplete);
const buttonDelete = document.createElement("button");
buttonDelete.innerText = "❌";
buttonDelete.addEventListener("click",handleButtonDeleteReadonly);
div.appendChild(span);
div.appendChild(buttonModify);
div.appendChild(buttonComplete);
div.appendChild(buttonDelete);
todoListElement.appendChild(div);
}
function paintModifyTodo(beforeModifyTodo,returnId) { //todo를 수정하는 중인 상태 paint
const div = document.createElement("div");
div.id = returnId;
const form = document.createElement("form");
form.className = "todo-item";
const input = document.createElement("input");
input.type = "text";
input.className = "todo-input";
input.value = beforeModifyTodo;
const buttonSave = document.createElement("button");
buttonSave.innerText = "저장";
buttonSave.addEventListener("click",handleButtonSave);
const buttonDelete = document.createElement("button");
buttonDelete.innerText = "❌";
buttonDelete.addEventListener("click",handleButtonDeleteWhileModify);
form.appendChild(input);
form.appendChild(buttonSave);
form.appendChild(buttonDelete);
div.appendChild(form);
todoListElement.appendChild(div);
SendBackProposeNewTodo();
}
function paintProposeNewTodo() { //할일 추가 상자 paint
const div1 = document.createElement("div");
div1.className = "todo-item-add";
div1.addEventListener("click",handleNewTodoElement);
const div2 = document.createElement("div");
div2.className = "content";
const span = document.createElement("span");
span.innerText = "할 일 추가";
div2.appendChild(span);
div1.appendChild(div2);
todoListElement.appendChild(div1);
}
function paintCompleted(completed,returnId) { //완료된 todo 상태 paint
const div = document.createElement("div");
div.className = "completed-item";
div.id = returnId
const span = document.createElement("span");
span.className = "completed-readonly";
span.innerText = completed;
const buttonUp = document.createElement("button");
buttonUp.className = "completed-button";
buttonUp.innerText = "⬆";
buttonUp.addEventListener("click",handleButtonUp);
div.appendChild(span);
div.appendChild(buttonUp);
completedListElement.appendChild(div);
}
/* etc functions*/
function SendBackProposeNewTodo() { //할일 추가 상자가 항상 맨 아래에 있게 하는 역할
const proposeNewTodoElements = document.querySelectorAll(".todo-item-add");
if (proposeNewTodoElements.length >1){
if (proposeNewTodoElements !== null){
proposeNewTodoElements.remove();
}
}
else {
for (let proposeNewTodoElement of proposeNewTodoElements) {
if (proposeNewTodoElement !== null){
proposeNewTodoElement.remove();
}
}
}
paintProposeNewTodo();
}
console.log(localStorage.getItem(TODOS_KEY));
if (localStorage[TODOS_KEY] !== undefined) {
if (localStorage[COMPLETEDS_KEY] !== undefined) {
for (completedArr of localStorage[COMPLETEDS_KEY])
{
console.log(completedArr);
}
}
for (todoArr of localStorage[TODOS_KEY]) {
console.log(todoArr);
}
}
initTodoFormElement.addEventListener("submit",handleToDoInitSubmit); //초기 todo에 대한 eventListener
아래는 html 파일
index.html
<!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" />
<link rel="stylesheet" href="index.css" />
<title>Document</title>
</head>
<body>
<div class="container todo">
<h1>오늘의 할 일 Todo</h1>
<div class="todo-list todo-button">
<div id="1" class="todo-initDiv">
<form class="todo-item">
<input type="text" class="todo-input" placeholder="할 일을 입력하세요">
<button type = "submit" class="save">저장</button>
</form>
</div>
</div>
</div>
<div class="container completed" style="margin-top: 3em;">
<h1>완료한 일 Completed!</h1>
<div class = "completed-list">
</div>
</div>
<script src="index.js"></script>
</body>
</html>
<!-- 여러가지 형태의 항목들 -->
<!-- <div class="todo-item"><input type="text" class="todo-input" placeholder="수정할 때 상황." readonly><button>✏️</button><button>✓</button><button>❌</button></div>
<div class="todo-item"><div class="todo-readonly"><span >기존에 입력되어져 있었던 일</span></div><button>✏️</button><button>✓</button><button>❌</button></div>
<div class="todo-item"><span class="todo-readonly">기존에 입력되어져 있었던 일</span><button>✏️</button><button>✓</button><button>❌</button></div>
<div class="todo-item"><input type="text" class="todo-input" value="기존에 입력되어져 있었던 일."><button>저장</button><button>❌</button></div>
<div class="todo-item"><input type="text" class="todo-input" placeholder="할 일을 입력하세요"><button>저장</button></div>
<div class="todo-item-add"><div class="content"><span>할 일 추가</span></div></div> -->
아래는 css 파일.
index.css
html,
body,
h1 {
margin: 0;
padding: 0;
}
h1 {
text-align: center;
}
.container {
background-color: white;
width: 600px;
margin: 0 auto;
padding-top: 1em;
position: relative;
top: 50%;
}
/**** todo ****/
.todo {
}
.todo-initDiv {
}
.todo-list {
margin-top: 2em;
margin-left: 2em;
margin-right: 2em;
border:2px solid;
border-radius: 1em;
padding: 2em;
}
.todo-item {
margin-bottom: 1em;
padding: 0 auto;
display: flex;
justify-content: space-between;
height: 56px;
}
.todo-input {
background-color: #fff;
display: flex;
justify-content: space-between;
width: 500px;
margin-top: 0 auto;
margin-bottom :0 auto;
height: 50px;
}
.todo-readonly {
background-color: #fff;
/* display: flex; */
justify-content: space-between;
width: 468px;
padding-top: 17px ;
padding-bottom :10px;
text-align: center;
border: 2px solid;
}
.todo-item-add {
margin-bottom: 1em;
padding: 0 auto;
display: flex;
justify-content: space-between;
height: 56px;
border:2px dotted;
color: lightgray;
font-size: 1.5em;
}
.todo-item-add .content {
/* display: flex; */
justify-content: space-between;
width: 468px;
padding-top: 16px ;
padding-bottom :10px;
text-align: center;
}
.container .todo-button button{
background-color: white;
margin-right: 1px;
margin-left:2px;
}
/**** completed ****/
.completed {
}
.completed-list {
margin-top: 2em;
margin-left: 2em;
margin-right: 2em;
border:2px solid;
border-radius: 1em;
padding: 2em;
}
.completed-item {
background-color: black;
color:white;
margin-bottom: 1em;
padding: 0 auto;
display: flex;
justify-content: space-between;
height: 56px;
}
.completed-readonly {
background-color: black;
color:white;
justify-content: space-between;
width: 468px;
padding-top: 17px ;
padding-bottom :10px;
text-align: center;
}
.completed-button {
background-color: black;
color:white;
}
/**** 버튼 ****/
button .save {
}
/**** etc ****/
.hidden {
display: none;
}
이정도까지 만들기까지 생각보다 상당히 오래 걸렸다.
한 30시간?
localstorage에 저장은 했지만
새로고침 시에 다 사라지는 건 아직 해결하지 못했다.
일단 리액트부터 배우고 오자.
'Front-End > JavaScript' 카테고리의 다른 글
[Javascript] async, await (0) | 2023.08.20 |
---|---|
[Javascript] Testing code (0) | 2023.08.20 |
[JavaScript] Todo-List 만들기(1) (0) | 2023.03.30 |
[JavaScript] 230327 학습일기 (0) | 2023.03.29 |
[JavaScript] 230326 학습일기 (0) | 2023.03.27 |