Skip to content

[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

Open
wants to merge 1 commit into
base: changsubkwak
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 171 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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')) ?? [];
Comment on lines +41 to +42

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변하는 값이 아니라면 let 보다는 const를 사용하는게 좋습니다! let은 나중에 변수 할당해야할 필요가 있거나 등의 꼭 필요한 이유가 있는 경우 아니고서야 기본적으로 const를 사용한다고 보시면됩니다. 이유는 계속해서 한개의 변수에 다른 값을 할당하면 디버깅이나 유지보수 측면에서 추적이 힘들 수 있다고 알고있습니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵, 알겠습니다. ^^


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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

배열순회를 목적으로 하신다면 for문보다는 map이나 foreach의 사용을 추천드립니다ㅎㅎ

Comment on lines +49 to +51

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for 보다는 array method나 for in for of를 사용하는 것도 좋아보입니다!

Copy link
Author

Choose a reason for hiding this comment

The 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>";
Comment on lines +60 to +68
Copy link

Choose a reason for hiding this comment

The 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>`

이런식으로 백틱()` 을 이용해서 한번에 기입하는 것도 좋을 것 같아요 ㅎㅎ

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵, 감사합니다.


Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

백틱(`)으로 템플릿 리터럴을 사용을 추천드립니다😸
이를 사용하면, 기존의 따옴표 방식에서는, + 연산자를 사용하지 않고
않에 표현식을 작성할 수 있습니다 ㅎㅎ

Copy link
Author

Choose a reason for hiding this comment

The 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));

Choose a reason for hiding this comment

The 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);
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&&로 체크하기 보다는 거짓 조건을 먼저 달아서 함수를 끝내는 것도 방법입니다

if (newTodoTitle.value === '') return

if (e.key === "Enter") {
  #code
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네, 동의합니다. 장후님 말씀하신 대로의 코드를 지향하는데, 놓친 부분이에요.

});

let test;

// document.addEventListener("mouseup", (e) => { // 왜 mouseup로 하면 안되는 이유는 나중에 찾아보기
document.addEventListener("click", (e) => {
let className = e.target.className;

// 요구사항 #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

Choose a reason for hiding this comment

The 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);
todo.remove();
localStorage.setItem('todoData', JSON.stringify(todoData));

// 요구사항 #5 - item갯수를 count한 갯수를 리스트의 하단에 보여주기
document.getElementById("total-count").innerText = todoData.length;
}

// 요구사항 #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;
}

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) => {

Choose a reason for hiding this comment

The 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>