-
Notifications
You must be signed in to change notification settings - Fork 216
[10기 곽창섭] TodoList with CRUD #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: changsubkwak
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ <h1>TODOS</h1> | |
<input class="toggle-all" type="checkbox" /> | ||
<ul id="todo-list" class="todo-list"></ul> | ||
<div class="count-container"> | ||
<span class="todo-count">총 <strong>0</strong> 개</span> | ||
<span class="todo-count">총 <strong id='total-count'> 0</strong> 개</span> | ||
<ul class="filters"> | ||
<li> | ||
<a class="all selected" href="#">전체보기</a> | ||
|
@@ -36,3 +36,173 @@ <h1>TODOS</h1> | |
</div> | ||
</body> | ||
</html> | ||
<script type="text/javascript"> | ||
const newTodoTitle = document.getElementById("new-todo-title"); | ||
let todoView = document.getElementById("todo-list"); | ||
let todoData = JSON.parse(localStorage.getItem('todoData')) ?? []; | ||
|
||
console.log("todoData", todoData); | ||
|
||
initLoadTodoData(); | ||
|
||
function initLoadTodoData() { | ||
for (let i = 0 ; i < todoData.length ; i++) { | ||
addTodoItem(todoData[i], true); | ||
} | ||
Comment on lines
+49
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 배열순회를 목적으로 하신다면 for문보다는 map이나 foreach의 사용을 추천드립니다ㅎㅎ
Comment on lines
+49
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for 보다는 array method나 for in for of를 사용하는 것도 좋아보입니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 향후, 개선된 코드를 보여드리도록 하겠습니다. |
||
document.getElementById("total-count").innerText = todoData.length; | ||
} | ||
|
||
function addTodoItem(todoObj, isFilter) { | ||
let id = ( isFilter ? todoObj.id : new Date().getTime() ); | ||
let isComplete = (todoObj.isComplete === "false" ? "false" : "completed"); | ||
let isChecked = (todoObj.isComplete === "false" ? "false" : "checked"); | ||
|
||
let itemHTML = ""; | ||
itemHTML += "<li id='" + id + "' class='" + isComplete + "'>"; | ||
itemHTML += "<div class='" + todoObj.type + "'>"; | ||
itemHTML += "<input class='toggle' type='checkbox' id='" + id + "' " + isChecked + " />"; | ||
itemHTML += "<label class='label'>" + todoObj.value + "</label>"; | ||
itemHTML += "<button class='destroy' id='" + id + "'></button>"; | ||
itemHTML += "</div>"; | ||
itemHTML += "<input class='edit' value='" + todoObj.value + "' />"; | ||
itemHTML += "</li>"; | ||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+60
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. `<li >
<div class="view">
<input class="toggle" type="checkbox" data-node-id=${todo.idx} />
//중략
</li>` 이런식으로 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵, 감사합니다. |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 백틱(`)으로 템플릿 리터럴을 사용을 추천드립니다😸 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵, 참고하겠습니다. |
||
todoView = document.getElementById("todo-list"); | ||
// console.log("todoView", todoView); | ||
|
||
todoView.innerHTML += itemHTML; | ||
|
||
if (!isFilter) { | ||
todoData.push({ | ||
id : id, | ||
isComplete : isComplete, | ||
type : todoObj.type, | ||
value : todoObj.value, | ||
}); | ||
localStorage.setItem('todoData', JSON.stringify(todoData)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. setitem getitem같은걸 유틸로 분리해서 사용하면 좋을 것 같아요! |
||
|
||
// 요구사항 #5 - item갯수를 count한 갯수를 리스트의 하단에 보여주기 | ||
document.getElementById("total-count").innerText = todoData.length; | ||
} | ||
} | ||
|
||
// 엔터키 이벤트 추가 | ||
// 요구사항 #1 - todo list에 todoItem을 키보드로 입력하여 추가하기 | ||
newTodoTitle.addEventListener("keyup", (e) => { | ||
// console.log("todoData", todoData); | ||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (e.key === "Enter" && newTodoTitle.value !== '') { | ||
let todoObj = { | ||
isComplete : "false", | ||
type : "view", | ||
value : newTodoTitle.value, | ||
} | ||
addTodoItem(todoObj, false); | ||
newTodoTitle.value = ''; | ||
} | ||
Comment on lines
+93
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. &&로 체크하기 보다는 거짓 조건을 먼저 달아서 함수를 끝내는 것도 방법입니다 if (newTodoTitle.value === '') return
if (e.key === "Enter") {
#code
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네, 동의합니다. 장후님 말씀하신 대로의 코드를 지향하는데, 놓친 부분이에요. |
||
}); | ||
|
||
let test; | ||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// document.addEventListener("mouseup", (e) => { // 왜 mouseup로 하면 안되는 이유는 나중에 찾아보기 | ||
document.addEventListener("click", (e) => { | ||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let className = e.target.className; | ||
|
||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 요구사항 #2 - todo list의 체크박스를 클릭하여 complete 상태로 변경 | ||
// (li tag 에 completed class 추가, input 태그에 checked 속성 추가) | ||
if (className === "toggle") { | ||
if (e.target.getAttribute("checked") === "") { | ||
e.target.setAttribute("false", ""); | ||
e.target.removeAttribute("checked"); | ||
Comment on lines
+114
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. attribute를 사용할 때 e.target.checked = true
e.target.checked = false 이런식으로 사용해도 좋을 것 같아요! |
||
} else { | ||
e.target.setAttribute("checked", ""); | ||
e.target.removeAttribute("false"); | ||
} | ||
|
||
let listItemClass = document.getElementById(e.target.id).className; | ||
listItemClass = (listItemClass === "false" ? "completed" : "false"); | ||
document.getElementById(e.target.id).className = listItemClass; | ||
|
||
let allTodo = Array.prototype.slice.call( todoView.children ); | ||
let todo = e.target.parentElement.parentElement; | ||
let index = allTodo.indexOf(todo); | ||
todoData[index].isComplete = listItemClass; | ||
|
||
localStorage.setItem('todoData', JSON.stringify(todoData)); | ||
} | ||
|
||
// 요구사항 #3 - todo list의 x버튼을 이용해서 해당 엘리먼트를 삭제 | ||
if (className === "destroy") { | ||
let allTodo = Array.prototype.slice.call( todoView.children ); | ||
let todo = e.target.parentElement.parentElement; | ||
let index = allTodo.indexOf(todo); | ||
|
||
todoData.splice(index, 1); | ||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
todo.remove(); | ||
localStorage.setItem('todoData', JSON.stringify(todoData)); | ||
|
||
// 요구사항 #5 - item갯수를 count한 갯수를 리스트의 하단에 보여주기 | ||
document.getElementById("total-count").innerText = todoData.length; | ||
} | ||
|
||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 요구사항 #6 | ||
if (className === "all selected") { | ||
todoView.innerText = ""; | ||
todoData.forEach(element => { | ||
addTodoItem(element, true); | ||
}); | ||
document.getElementById("total-count").innerText = todoData.length; | ||
} | ||
|
||
if (className === "active") { | ||
todoView.innerText = ""; | ||
let count = 0; | ||
todoData.forEach(element => { | ||
if (element.isComplete === "false") { | ||
count++; | ||
addTodoItem(element, true); | ||
} | ||
}); | ||
document.getElementById("total-count").innerText = count; | ||
} | ||
ChangSubKwak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (className === "completed") { | ||
todoView.innerText = ""; | ||
|
||
let count = 0; | ||
todoData.forEach(element => { | ||
if (element.isComplete === "completed") { | ||
count++; | ||
addTodoItem(element, true); | ||
} | ||
}); | ||
// todoData.filter( todo => todo.isComplete === "completed") | ||
|
||
document.getElementById("total-count").innerText = count; | ||
} | ||
|
||
}); | ||
|
||
|
||
// 요구사항 #4 - todo list를 더블클릭했을 때 input 모드로 변경 (li tag 에 editing class 추가) | ||
// - 단 이때 수정을 완료하지 않은 상태에서 esc키를 누르면 수정되지 않은 채로 다시 view 모드로 복귀 | ||
document.addEventListener("dblclick", (e) => { | ||
let li = e.target.parentElement.parentElement; | ||
li.classList.add("editing"); | ||
li.addEventListener('keyup', (e2) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. e2보다는 좀 더 명확한 변수명을 사용하는게 좋을 것 같아요! |
||
let orgValue = e.target.innerText; | ||
if (e2.key === "Enter") { | ||
let labelTag = e2.target.parentElement.getElementsByClassName("label")[0]; | ||
labelTag.innerText = e2.target.value; | ||
localStorage.setItem('todoData', JSON.stringify(todoData)); | ||
e2.target.parentElement.classList.remove("editing"); | ||
} | ||
|
||
if (e2.key === "Escape") { | ||
e2.target.value = orgValue; | ||
e2.target.parentElement.classList.remove("editing"); | ||
} | ||
|
||
}); | ||
}); | ||
|
||
</script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변하는 값이 아니라면 let 보다는 const를 사용하는게 좋습니다! let은 나중에 변수 할당해야할 필요가 있거나 등의 꼭 필요한 이유가 있는 경우 아니고서야 기본적으로 const를 사용한다고 보시면됩니다. 이유는 계속해서 한개의 변수에 다른 값을 할당하면 디버깅이나 유지보수 측면에서 추적이 힘들 수 있다고 알고있습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵, 알겠습니다. ^^