From 0e41bc977120eadfeb72f2c9e7191a9e22069e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=A7=84?= Date: Tue, 10 Dec 2024 14:14:32 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[=EC=B4=88=EA=B8=89]=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5,=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func_simple.js | 25 +++++++++++++++++++++++++ simple.html | 1 + 2 files changed, 26 insertions(+) create mode 100644 func_simple.js diff --git a/func_simple.js b/func_simple.js new file mode 100644 index 0000000..5eb0233 --- /dev/null +++ b/func_simple.js @@ -0,0 +1,25 @@ +document.addEventListener('DOMContentLoaded', function () { + const input = document.querySelector('.todo-input'); + const saveButton = document.querySelector('.input-container input[type="button"]'); + const list = document.getElementById('todo-list'); + + saveButton.addEventListener('click', function () { + const inputText = input.value.trim(); + if (inputText === '') { + alert("내용을 입력하세요."); + return; + } + + const isConfirm = confirm(`"${inputText}"를 저장하시겠습니까?`); + if (!isConfirm) { + return; + } + + const newTodo = document.createElement('li'); + newTodo.textContent = inputText; + + list.appendChild(newTodo); + + input.value = ''; + }); +}); diff --git a/simple.html b/simple.html index 2887e44..9631600 100644 --- a/simple.html +++ b/simple.html @@ -1,6 +1,7 @@ + Simple TODO List From 8e819961f46fd9c774f728607a3f535f1b8a0646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=A7=84?= Date: Tue, 10 Dec 2024 16:06:03 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[=EC=A4=91=EA=B8=89]=20=EC=A1=B0=ED=9A=8C,?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C,=20=EC=B6=94=EA=B0=80,=20=EC=88=98?= =?UTF-8?q?=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- detail.html | 5 ++- func_detail.js | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 func_detail.js diff --git a/detail.html b/detail.html index 160571b..c0873e1 100644 --- a/detail.html +++ b/detail.html @@ -1,6 +1,7 @@ + Detail TODO List @@ -9,10 +10,10 @@

TODO LIST

- +
- diff --git a/func_detail.js b/func_detail.js new file mode 100644 index 0000000..f4a261c --- /dev/null +++ b/func_detail.js @@ -0,0 +1,101 @@ +function enterKey(event) { + if(event.key === 'Enter') { + craeteTodo(); + } +} + +function craeteTodo() { + const list = document.getElementById('todo-list'); + const input = document.querySelector('.todo-input'); + const inputText = input.value.trim(); + + if (inputText === '') { + alert("내용을 입력하세요."); + return; + } + + const isConfirm = confirm(`"${inputText}"를 저장하시겠습니까?`); + if (!isConfirm) { + return; + } + // Create List Element + const newTodo = document.createElement('li'); + const checkbox = document.createElement('input'); + const todoText = document.createElement('span'); + const editButton = document.createElement('button'); + const deleteButton = document.createElement('button'); + + // Checkbox + checkbox.type = 'checkbox'; + checkbox.classList.add('todo-checkbox'); + newTodo.appendChild(checkbox); + + // TextContent + todoText.classList.add('todo-text'); + todoText.textContent = inputText; + newTodo.appendChild(todoText); + + // Button + editButton.textContent = "Edit"; + editButton.classList.add('edit-btn'); + editButton.addEventListener('click', () => { editTodo(newTodo) }); + newTodo.appendChild(editButton); + + deleteButton.textContent = "X"; + deleteButton.classList.add('delete-btn'); + deleteButton.addEventListener('click', () => { deleteTodo(newTodo) }); + newTodo.appendChild(deleteButton); + + list.appendChild(newTodo); + + input.value = ''; +} + +function listFilter(event) { + const filter = event.target.value; + const todoList = document.querySelectorAll('#todo-list li') + + todoList.forEach(todo => { + const checkbox = todo.querySelector('.todo-checkbox'); + + if (filter === "all") { + todo.style.display = 'list-item'; + } else if (filter === 'todo' && !checkbox.checked) { + todo.style.display = 'list-item'; + } else if (filter === 'done' && checkbox.checked) { + todo.style.display = 'list-item'; + } else { + todo.style.display = 'none'; + } + }) +} + +function editTodo(item) { + const todo = item.querySelector('.todo-text'); + const editBtn = item.querySelector('.edit-btn'); + + if (editBtn.textContent === 'Edit') { + const input = document.createElement('input'); + input.setAttribute('type', 'text'); + input.setAttribute('class', 'todo-text'); + input.setAttribute('value', todo.textContent); + item.replaceChild(input, todo); + editBtn.textContent = 'Save'; + } else { + const input = item.querySelector('.todo-text'); + if (input.value.trim() === '') { + alert('내용을 입력하세요.'); + return; + } + const editTodo = document.createElement('span'); + editTodo.classList.add('todo-text'); + editTodo.textContent = input.value.trim(); + + item.replaceChild(editTodo, input); + editBtn.textContent = 'Edit'; + } +} + +function deleteTodo(item) { + item.remove(); +} \ No newline at end of file From 760994087baddb06ede57650e987b294dff8d1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=A7=84?= Date: Fri, 13 Dec 2024 18:14:55 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=ED=94=BC=EB=93=9C=EB=B0=B1=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- detail.html | 1 + func_detail.js | 138 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 95 insertions(+), 44 deletions(-) diff --git a/detail.html b/detail.html index c0873e1..5a0a491 100644 --- a/detail.html +++ b/detail.html @@ -10,6 +10,7 @@

TODO LIST

+
diff --git a/func_detail.js b/func_detail.js index f4a261c..37456d7 100644 --- a/func_detail.js +++ b/func_detail.js @@ -1,10 +1,10 @@ function enterKey(event) { if(event.key === 'Enter') { - craeteTodo(); + createTodo(); } } -function craeteTodo() { +function createTodo() { const list = document.getElementById('todo-list'); const input = document.querySelector('.todo-input'); const inputText = input.value.trim(); @@ -18,51 +18,88 @@ function craeteTodo() { if (!isConfirm) { return; } + + // 피드백) Element Create하는 부분들 모듈화(함수를 모듈화해서 객체로 전달하는 것이 좋다. 버튼을 생성할때, 생성 함수는 1개에 인자를 다르게 해서 생성하는 느낌) + // Create List Element const newTodo = document.createElement('li'); - const checkbox = document.createElement('input'); - const todoText = document.createElement('span'); - const editButton = document.createElement('button'); - const deleteButton = document.createElement('button'); - + // Checkbox - checkbox.type = 'checkbox'; - checkbox.classList.add('todo-checkbox'); + const checkbox = createCheckbox('input', 'checkbox', 'todo-checkbox') newTodo.appendChild(checkbox); - + // TextContent + const todoText = document.createElement('span'); todoText.classList.add('todo-text'); todoText.textContent = inputText; newTodo.appendChild(todoText); - + // Button - editButton.textContent = "Edit"; - editButton.classList.add('edit-btn'); - editButton.addEventListener('click', () => { editTodo(newTodo) }); + const editButton = createButton('button', 'Edit', 'edit-btn'); newTodo.appendChild(editButton); - - deleteButton.textContent = "X"; - deleteButton.classList.add('delete-btn'); - deleteButton.addEventListener('click', () => { deleteTodo(newTodo) }); + const saveButton = createButton('button', 'Save', 'save-btn'); + newTodo.appendChild(saveButton); + const deleteButton = createButton('button', 'X', 'delete-btn'); newTodo.appendChild(deleteButton); + // // 피드백) eventListener는 이벤트를 통해서 조작해야하기 때문에 editTodo ParentNode정돈 허용해야한다. + // // -> eventListener는 이벤트가 발생한 요소에 대한 파라미터를 제공함. list.appendChild(newTodo); input.value = ''; } +function createCheckbox(tag, type, className) { + const checkbox = document.createElement(tag); + checkbox.type = type; + checkbox.classList.add(className); + + return checkbox; +} + +function createButton(tag, buttonText, className) { + const button = document.createElement(tag); + button.textContent = buttonText; + button.classList.add(className); + button.addEventListener('click', (e) => { handleButtonEvent(e) } ); + + if (buttonText === 'Save') button.style.display = 'none'; + + return button; +} + +function handleButtonEvent(e) { + const buttonName = e.target.className; + switch (buttonName) { + case 'edit-btn' : + editTodo(e); + break; + case 'save-btn' : + saveTodo(e); + break; + case 'delete-btn' : + deleteTodo(e); + break; + default : + console.warn('Unknown Button Action'); + break; + } +} + function listFilter(event) { const filter = event.target.value; - const todoList = document.querySelectorAll('#todo-list li') - + const todoList = document.querySelectorAll('#todo-list li'); + todoList.forEach(todo => { const checkbox = todo.querySelector('.todo-checkbox'); - + const isChecked = checkbox.checked; + if (filter === "all") { + console.log(filter); todo.style.display = 'list-item'; - } else if (filter === 'todo' && !checkbox.checked) { + } else if (filter === 'todo' && !isChecked) { todo.style.display = 'list-item'; - } else if (filter === 'done' && checkbox.checked) { + } else if (filter === 'done' && isChecked) { todo.style.display = 'list-item'; } else { todo.style.display = 'none'; @@ -70,32 +107,45 @@ function listFilter(event) { }) } -function editTodo(item) { +function editTodo(event) { + // 피드백) 하나의 컴포넌트가 두 개 이상의 작업을 수행하게 되어있음. + // 역할을 나눠놓는 것이 좋다. Edit, Save + const item = event.target.parentNode; const todo = item.querySelector('.todo-text'); const editBtn = item.querySelector('.edit-btn'); + const saveBtn = item.querySelector('.save-btn'); + saveBtn.style.display = 'inline'; + editBtn.style.display = 'none'; - if (editBtn.textContent === 'Edit') { - const input = document.createElement('input'); - input.setAttribute('type', 'text'); - input.setAttribute('class', 'todo-text'); - input.setAttribute('value', todo.textContent); - item.replaceChild(input, todo); - editBtn.textContent = 'Save'; - } else { - const input = item.querySelector('.todo-text'); - if (input.value.trim() === '') { - alert('내용을 입력하세요.'); - return; - } - const editTodo = document.createElement('span'); - editTodo.classList.add('todo-text'); - editTodo.textContent = input.value.trim(); + const input = document.createElement('input'); + // Map으로 중앙화도 가능 + input.setAttribute('type', 'text'); + input.setAttribute('class', 'todo-text'); + input.setAttribute('value', todo.textContent); + item.replaceChild(input, todo); +} - item.replaceChild(editTodo, input); - editBtn.textContent = 'Edit'; +function saveTodo(event) { + const item = event.target.parentNode; + const editBtn = item.querySelector('.edit-btn'); + const saveBtn = item.querySelector('.save-btn'); + + const input = item.querySelector('.todo-text'); + if (input.value.trim() === '') { + alert('내용을 입력하세요.'); + return; } + const saveTodo = document.createElement('span'); + saveTodo.classList.add('todo-text'); + saveTodo.textContent = input.value.trim(); + + item.replaceChild(saveTodo, input); + editBtn.style.display = 'inline'; + saveBtn.style.display = 'none'; } -function deleteTodo(item) { - item.remove(); +// 주어진 걸 최대한 쓰자 이벤트리스너의 파라미터. +function deleteTodo(event) { + const todo = event.target.parentNode; + todo.remove(); } \ No newline at end of file From a49e4ca378fc9d8b27d1c0ae31c317bf1e2e6174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=A7=84?= Date: Fri, 20 Dec 2024 10:41:52 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=EB=A1=9C=EC=BB=AC=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func_detail.js | 152 ++++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 58 deletions(-) diff --git a/func_detail.js b/func_detail.js index 37456d7..b00897d 100644 --- a/func_detail.js +++ b/func_detail.js @@ -4,28 +4,61 @@ function enterKey(event) { } } -function createTodo() { +function loadLocalStorage() { + const savedTodos = JSON.parse(localStorage.getItem('todoItem')) || []; + savedTodos.forEach(todoData => { + createTodo(todoData); + }) +} + +document.addEventListener('DOMContentLoaded', () => { + loadLocalStorage(); +}); + +function getLocalStorageItem(currentItem) { + const todos = JSON.parse(localStorage.getItem('todoItem')) || []; + + const index = Array.from(currentItem.parentNode.children).indexOf(currentItem); + + return {todos, index}; +} + +function saveLocalStorage(todo) { + const existingTodo = JSON.parse(localStorage.getItem('todoItem')) || []; + const content = todo.querySelector('.todo-text').textContent; + const isChecked = todo.querySelector('.todo-checkbox').checked; + const todoObject = { + content : content, + isChecked : isChecked, + }; + existingTodo.push(todoObject); + + localStorage.setItem('todoItem', JSON.stringify(existingTodo)); +} + +function createTodo(todoData) { const list = document.getElementById('todo-list'); const input = document.querySelector('.todo-input'); - const inputText = input.value.trim(); + const inputText = todoData ? todoData.content : input.value.trim(); if (inputText === '') { alert("내용을 입력하세요."); return; } - const isConfirm = confirm(`"${inputText}"를 저장하시겠습니까?`); - if (!isConfirm) { - return; + if (!todoData) { + const isConfirm = confirm(`"${inputText}"를 저장하시겠습니까?`); + if (!isConfirm) { + return; + } } - // 피드백) Element Create하는 부분들 모듈화(함수를 모듈화해서 객체로 전달하는 것이 좋다. 버튼을 생성할때, 생성 함수는 1개에 인자를 다르게 해서 생성하는 느낌) - // Create List Element const newTodo = document.createElement('li'); // Checkbox const checkbox = createCheckbox('input', 'checkbox', 'todo-checkbox') + if (todoData) checkbox.checked = todoData.isChecked; newTodo.appendChild(checkbox); // TextContent @@ -35,57 +68,52 @@ function createTodo() { newTodo.appendChild(todoText); // Button - const editButton = createButton('button', 'Edit', 'edit-btn'); + const editButton = createButton(BUTTON_TYPES.edit); newTodo.appendChild(editButton); - const saveButton = createButton('button', 'Save', 'save-btn'); + const saveButton = createButton(BUTTON_TYPES.save); newTodo.appendChild(saveButton); - const deleteButton = createButton('button', 'X', 'delete-btn'); + const deleteButton = createButton(BUTTON_TYPES.delete); newTodo.appendChild(deleteButton); - // // 피드백) eventListener는 이벤트를 통해서 조작해야하기 때문에 editTodo ParentNode정돈 허용해야한다. - // // -> eventListener는 이벤트가 발생한 요소에 대한 파라미터를 제공함. list.appendChild(newTodo); - - input.value = ''; + + if (!todoData) { + saveLocalStorage(newTodo); + input.value = ''; + } } function createCheckbox(tag, type, className) { const checkbox = document.createElement(tag); checkbox.type = type; checkbox.classList.add(className); + checkbox.addEventListener('change', (event) => { + const item = event.target.parentNode; + const {todos, index} = getLocalStorageItem(item); + todos[index].isChecked = event.target.checked; + localStorage.setItem('todoItem', JSON.stringify(todos)); + }); return checkbox; } -function createButton(tag, buttonText, className) { +const BUTTON_TYPES = { + edit: { tag: 'button', buttonText: 'Edit', className: 'edit-btn', handler: editTodo }, + save: { tag: 'button', buttonText: 'Save', className: 'save-btn', handler: saveTodo }, + delete: { tag: 'button', buttonText: 'X', className: 'delete-btn', handler: deleteTodo }, +}; + +function createButton({tag, buttonText, className, handler}) { const button = document.createElement(tag); button.textContent = buttonText; button.classList.add(className); - button.addEventListener('click', (e) => { handleButtonEvent(e) } ); + button.addEventListener('click', handler); if (buttonText === 'Save') button.style.display = 'none'; return button; } -function handleButtonEvent(e) { - const buttonName = e.target.className; - switch (buttonName) { - case 'edit-btn' : - editTodo(e); - break; - case 'save-btn' : - saveTodo(e); - break; - case 'delete-btn' : - deleteTodo(e); - break; - default : - console.warn('Unknown Button Action'); - break; - } -} - function listFilter(event) { const filter = event.target.value; const todoList = document.querySelectorAll('#todo-list li'); @@ -94,41 +122,36 @@ function listFilter(event) { const checkbox = todo.querySelector('.todo-checkbox'); const isChecked = checkbox.checked; - if (filter === "all") { - console.log(filter); - todo.style.display = 'list-item'; - } else if (filter === 'todo' && !isChecked) { - todo.style.display = 'list-item'; - } else if (filter === 'done' && isChecked) { - todo.style.display = 'list-item'; - } else { - todo.style.display = 'none'; - } - }) + const isVisible = + filter === "all" || + (filter === 'todo' && !isChecked) || + (filter === 'done' && isChecked); + + todo.style.display = isVisible ? 'list-item' : 'none'; + }); } function editTodo(event) { - // 피드백) 하나의 컴포넌트가 두 개 이상의 작업을 수행하게 되어있음. - // 역할을 나눠놓는 것이 좋다. Edit, Save const item = event.target.parentNode; const todo = item.querySelector('.todo-text'); - const editBtn = item.querySelector('.edit-btn'); - const saveBtn = item.querySelector('.save-btn'); - saveBtn.style.display = 'inline'; - editBtn.style.display = 'none'; - + const editButton = item.querySelector('.edit-btn'); + const saveButton = item.querySelector('.save-btn'); + const input = document.createElement('input'); - // Map으로 중앙화도 가능 input.setAttribute('type', 'text'); input.setAttribute('class', 'todo-text'); input.setAttribute('value', todo.textContent); + item.replaceChild(input, todo); + + saveButton.style.display = 'inline'; + editButton.style.display = 'none'; } function saveTodo(event) { const item = event.target.parentNode; - const editBtn = item.querySelector('.edit-btn'); - const saveBtn = item.querySelector('.save-btn'); + const editButton = item.querySelector('.edit-btn'); + const saveButton = item.querySelector('.save-btn'); const input = item.querySelector('.todo-text'); if (input.value.trim() === '') { @@ -140,12 +163,25 @@ function saveTodo(event) { saveTodo.textContent = input.value.trim(); item.replaceChild(saveTodo, input); - editBtn.style.display = 'inline'; - saveBtn.style.display = 'none'; + + const {todos, index} = getLocalStorageItem(todo); + todos[index].content = saveTodo.textContent; + localStorage.setItem('todoItem', JSON.stringify(todos)); + + + editButton.style.display = 'inline'; + saveButton.style.display = 'none'; } -// 주어진 걸 최대한 쓰자 이벤트리스너의 파라미터. function deleteTodo(event) { const todo = event.target.parentNode; + const {todos, index} = getLocalStorageItem(todo); + + todos.splice(index, 1); + localStorage.setItem('todoItem', JSON.stringify(todos)); + if (todos.length === 0) { + localStorage.removeItem('todoItem'); + } + todo.remove(); } \ No newline at end of file From 157eee28377668f9bcefa83daa5cecc33173a6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=96=B4=EC=A7=84?= Date: Fri, 20 Dec 2024 15:51:33 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func_detail.js | 372 ++++++++++++++++++++++++------------------------- 1 file changed, 186 insertions(+), 186 deletions(-) diff --git a/func_detail.js b/func_detail.js index b00897d..1fa2985 100644 --- a/func_detail.js +++ b/func_detail.js @@ -1,187 +1,187 @@ -function enterKey(event) { - if(event.key === 'Enter') { - createTodo(); - } -} - -function loadLocalStorage() { - const savedTodos = JSON.parse(localStorage.getItem('todoItem')) || []; - savedTodos.forEach(todoData => { - createTodo(todoData); - }) -} - -document.addEventListener('DOMContentLoaded', () => { - loadLocalStorage(); -}); - -function getLocalStorageItem(currentItem) { - const todos = JSON.parse(localStorage.getItem('todoItem')) || []; - - const index = Array.from(currentItem.parentNode.children).indexOf(currentItem); - - return {todos, index}; -} - -function saveLocalStorage(todo) { - const existingTodo = JSON.parse(localStorage.getItem('todoItem')) || []; - const content = todo.querySelector('.todo-text').textContent; - const isChecked = todo.querySelector('.todo-checkbox').checked; - const todoObject = { - content : content, - isChecked : isChecked, - }; - existingTodo.push(todoObject); - - localStorage.setItem('todoItem', JSON.stringify(existingTodo)); -} - -function createTodo(todoData) { - const list = document.getElementById('todo-list'); - const input = document.querySelector('.todo-input'); - const inputText = todoData ? todoData.content : input.value.trim(); - - if (inputText === '') { - alert("내용을 입력하세요."); - return; - } - - if (!todoData) { - const isConfirm = confirm(`"${inputText}"를 저장하시겠습니까?`); - if (!isConfirm) { - return; - } - } - - // Create List Element - const newTodo = document.createElement('li'); - - // Checkbox - const checkbox = createCheckbox('input', 'checkbox', 'todo-checkbox') - if (todoData) checkbox.checked = todoData.isChecked; - newTodo.appendChild(checkbox); - - // TextContent - const todoText = document.createElement('span'); - todoText.classList.add('todo-text'); - todoText.textContent = inputText; - newTodo.appendChild(todoText); - - // Button - const editButton = createButton(BUTTON_TYPES.edit); - newTodo.appendChild(editButton); - const saveButton = createButton(BUTTON_TYPES.save); - newTodo.appendChild(saveButton); - const deleteButton = createButton(BUTTON_TYPES.delete); - newTodo.appendChild(deleteButton); - - list.appendChild(newTodo); - - if (!todoData) { - saveLocalStorage(newTodo); - input.value = ''; - } -} - -function createCheckbox(tag, type, className) { - const checkbox = document.createElement(tag); - checkbox.type = type; - checkbox.classList.add(className); - checkbox.addEventListener('change', (event) => { - const item = event.target.parentNode; - const {todos, index} = getLocalStorageItem(item); - todos[index].isChecked = event.target.checked; - localStorage.setItem('todoItem', JSON.stringify(todos)); - }); - - return checkbox; -} - -const BUTTON_TYPES = { - edit: { tag: 'button', buttonText: 'Edit', className: 'edit-btn', handler: editTodo }, - save: { tag: 'button', buttonText: 'Save', className: 'save-btn', handler: saveTodo }, - delete: { tag: 'button', buttonText: 'X', className: 'delete-btn', handler: deleteTodo }, -}; - -function createButton({tag, buttonText, className, handler}) { - const button = document.createElement(tag); - button.textContent = buttonText; - button.classList.add(className); - button.addEventListener('click', handler); - - if (buttonText === 'Save') button.style.display = 'none'; - - return button; -} - -function listFilter(event) { - const filter = event.target.value; - const todoList = document.querySelectorAll('#todo-list li'); - - todoList.forEach(todo => { - const checkbox = todo.querySelector('.todo-checkbox'); - const isChecked = checkbox.checked; - - const isVisible = - filter === "all" || - (filter === 'todo' && !isChecked) || - (filter === 'done' && isChecked); - - todo.style.display = isVisible ? 'list-item' : 'none'; - }); -} - -function editTodo(event) { - const item = event.target.parentNode; - const todo = item.querySelector('.todo-text'); - const editButton = item.querySelector('.edit-btn'); - const saveButton = item.querySelector('.save-btn'); - - const input = document.createElement('input'); - input.setAttribute('type', 'text'); - input.setAttribute('class', 'todo-text'); - input.setAttribute('value', todo.textContent); - - item.replaceChild(input, todo); - - saveButton.style.display = 'inline'; - editButton.style.display = 'none'; -} - -function saveTodo(event) { - const item = event.target.parentNode; - const editButton = item.querySelector('.edit-btn'); - const saveButton = item.querySelector('.save-btn'); - - const input = item.querySelector('.todo-text'); - if (input.value.trim() === '') { - alert('내용을 입력하세요.'); - return; - } - const saveTodo = document.createElement('span'); - saveTodo.classList.add('todo-text'); - saveTodo.textContent = input.value.trim(); - - item.replaceChild(saveTodo, input); - - const {todos, index} = getLocalStorageItem(todo); - todos[index].content = saveTodo.textContent; - localStorage.setItem('todoItem', JSON.stringify(todos)); - - - editButton.style.display = 'inline'; - saveButton.style.display = 'none'; -} - -function deleteTodo(event) { - const todo = event.target.parentNode; - const {todos, index} = getLocalStorageItem(todo); - - todos.splice(index, 1); - localStorage.setItem('todoItem', JSON.stringify(todos)); - if (todos.length === 0) { - localStorage.removeItem('todoItem'); - } - - todo.remove(); +function enterKey(event) { + if(event.key === 'Enter') { + createTodo(); + } +} + +function loadLocalStorage() { + const savedTodos = JSON.parse(localStorage.getItem('todoItem')) || []; + savedTodos.forEach(todoData => { + createTodo(todoData); + }) +} + +document.addEventListener('DOMContentLoaded', () => { + loadLocalStorage(); +}); + +function getLocalStorageItem(currentItem) { + const todos = JSON.parse(localStorage.getItem('todoItem')) || []; + + const index = Array.from(currentItem.parentNode.children).indexOf(currentItem); + + return {todos, index}; +} + +function saveLocalStorage(todo) { + const existingTodo = JSON.parse(localStorage.getItem('todoItem')) || []; + const content = todo.querySelector('.todo-text').textContent; + const isChecked = todo.querySelector('.todo-checkbox').checked; + const todoObject = { + content : content, + isChecked : isChecked, + }; + existingTodo.push(todoObject); + + localStorage.setItem('todoItem', JSON.stringify(existingTodo)); +} + +function createTodo(todoData) { + const list = document.getElementById('todo-list'); + const input = document.querySelector('.todo-input'); + const inputText = todoData ? todoData.content : input.value.trim(); + + if (inputText === '') { + alert("내용을 입력하세요."); + return; + } + + if (!todoData) { + const isConfirm = confirm(`"${inputText}"를 저장하시겠습니까?`); + if (!isConfirm) { + return; + } + } + + // Create List Element + const newTodo = document.createElement('li'); + + // Checkbox + const checkbox = createCheckbox('input', 'checkbox', 'todo-checkbox') + if (todoData) checkbox.checked = todoData.isChecked; + newTodo.appendChild(checkbox); + + // TextContent + const todoText = document.createElement('span'); + todoText.classList.add('todo-text'); + todoText.textContent = inputText; + newTodo.appendChild(todoText); + + // Button + const editButton = createButton(BUTTON_TYPES.edit); + newTodo.appendChild(editButton); + const saveButton = createButton(BUTTON_TYPES.save); + newTodo.appendChild(saveButton); + const deleteButton = createButton(BUTTON_TYPES.delete); + newTodo.appendChild(deleteButton); + + list.appendChild(newTodo); + + if (!todoData) { + saveLocalStorage(newTodo); + input.value = ''; + } +} + +function createCheckbox(tag, type, className) { + const checkbox = document.createElement(tag); + checkbox.type = type; + checkbox.classList.add(className); + checkbox.addEventListener('change', (event) => { + const item = event.target.parentNode; + const {todos, index} = getLocalStorageItem(item); + todos[index].isChecked = event.target.checked; + localStorage.setItem('todoItem', JSON.stringify(todos)); + }); + + return checkbox; +} + +const BUTTON_TYPES = { + edit: { tag: 'button', buttonText: 'Edit', className: 'edit-btn', handler: editTodo }, + save: { tag: 'button', buttonText: 'Save', className: 'save-btn', handler: saveTodo }, + delete: { tag: 'button', buttonText: 'X', className: 'delete-btn', handler: deleteTodo }, +}; + +function createButton({tag, buttonText, className, handler}) { + const button = document.createElement(tag); + button.textContent = buttonText; + button.classList.add(className); + button.addEventListener('click', handler); + + if (buttonText === 'Save') button.style.display = 'none'; + + return button; +} + +function listFilter(event) { + const filter = event.target.value; + const todoList = document.querySelectorAll('#todo-list li'); + + todoList.forEach(todo => { + const checkbox = todo.querySelector('.todo-checkbox'); + const isChecked = checkbox.checked; + + const isVisible = + filter === "all" || + (filter === 'todo' && !isChecked) || + (filter === 'done' && isChecked); + + todo.style.display = isVisible ? 'list-item' : 'none'; + }); +} + +function editTodo(event) { + const item = event.target.parentNode; + const todo = item.querySelector('.todo-text'); + const editButton = item.querySelector('.edit-btn'); + const saveButton = item.querySelector('.save-btn'); + + const input = document.createElement('input'); + input.setAttribute('type', 'text'); + input.setAttribute('class', 'todo-text'); + input.setAttribute('value', todo.textContent); + + item.replaceChild(input, todo); + + saveButton.style.display = 'inline'; + editButton.style.display = 'none'; +} + +function saveTodo(event) { + const item = event.target.parentNode; + const editButton = item.querySelector('.edit-btn'); + const saveButton = item.querySelector('.save-btn'); + + const input = item.querySelector('.todo-text'); + if (input.value.trim() === '') { + alert('내용을 입력하세요.'); + return; + } + const saveTodo = document.createElement('span'); + saveTodo.classList.add('todo-text'); + saveTodo.textContent = input.value.trim(); + + item.replaceChild(saveTodo, input); + + const {todos, index} = getLocalStorageItem(item); + todos[index].content = saveTodo.textContent; + localStorage.setItem('todoItem', JSON.stringify(todos)); + + + editButton.style.display = 'inline'; + saveButton.style.display = 'none'; +} + +function deleteTodo(event) { + const todo = event.target.parentNode; + const {todos, index} = getLocalStorageItem(todo); + + todos.splice(index, 1); + localStorage.setItem('todoItem', JSON.stringify(todos)); + if (todos.length === 0) { + localStorage.removeItem('todoItem'); + } + + todo.remove(); } \ No newline at end of file