Skip to content
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

[1주차] 김동혁 미션 제출합니다. #2

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions icon/NotCheck.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icon/checkComplete.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 6 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ <h1 class="title">오늘 할 일</h1>

<!-- input container -->
<div class="WriteForm">
Copy link

Choose a reason for hiding this comment

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

저는 html 태그의 id, class 속성으로 주로 케밥케이스를 사용하는데요!

kebab-case란?
하이픈으로 단어를 연결하는 표기법

참고만 하면 될 것 같아요 ㅎㅎ

그치만 시작이름으로 영문 대문자, 숫자, 특수문자는 쓰지 않는다고 해요 !

<div class="writeTodoForm">
<form id="todoForm" class="writeTodoForm">
<img src="./icon/check.svg" class="check_icon" />
Copy link

@songess songess Mar 16, 2024

Choose a reason for hiding this comment

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

svg를 사용해 훨씬 깔끔한 거 같아요!

Copy link

Choose a reason for hiding this comment

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

맞아요 😆 여기서 alt 태그로 이미지 속성값을 넣어주면 더 좋아요 !

우리는 웹 접근성을 위해서 코드를 짤때 시각장애인을 위해 화면을 읽어주는 기능인 '스크린리더'를 고려해주어야 하는데요,

스크린 리더는 img 태그에 대해 이런 특징을 가진다고 해요!

  1. alt 태그를 명시해두지 않으면 src값을 읽어주고
  2. alt= "" 라고 명시하면 해당 이미지를 읽지 않고 넘어가고
  3. alt= "이미지를 나타내는 단어" 라고 명시하면 '이미지를 나타내는 단어' 를 읽어준답니다 > <

<input type="text" class="TodoInput" placeholder="할 일 추가" />
<button class="submitBtn">추가하기</button>
</div>
<button class="submitBtn">추가</button>
Copy link

Choose a reason for hiding this comment

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

button 태그를 사용할 때는 type="button"을 명시하면 좋아요! 😁

button의 기본 타입은 "button"이 아닌 "submit"이기 때문인데요! submit의 경우 폼을 제출하는 이벤트를 발생시켜서 따로 설정을 하지 않는 이상 새로고침에 따라 사용자가 입력한 값을 저장하지 않고 날려버린다고 하네요..🥹

그래서 type="button"을 명시해주어 이 버튼은 그자체로 아무런 이벤트가 없음을 알리고 자바스크립트 click이벤트 등과 연결을 하면 돼요! > <

Copy link
Member Author

Choose a reason for hiding this comment

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

엔터를 누를 시 폼 제출이 되려고 form 태그, 그리고 submit타입을 이용한 것 이였는데, 이런 문제가 있을 수 있군요. 감사합니다!

</form>
</div>

<!-- todo list -->
<ul class="todoList"></ul>
</div>
</div>
</body>
Expand Down
94 changes: 94 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,97 @@ const options = {
const dateString = today.toLocaleDateString("ko-KR", options);

document.getElementById("todayDate").innerText = dateString;

document.addEventListener("DOMContentLoaded", function () {
Copy link

Choose a reason for hiding this comment

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

DOMContentLoaded을 사용하신 이유가 궁금해요!

Copy link

Choose a reason for hiding this comment

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

저도 이번에 파싱이후의 초기화작업을 위해 DOMContentLoaded를 처음 써봤는데요, 아직 정확하게 이해하지는 못하고 공부중이라서 이번 토론시간에 같이 얘기해보면 좋을 것 같아요 > <

Copy link
Member Author

Choose a reason for hiding this comment

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

저도 이번에 과제를 하면서 새롭게 안 기능이라 한번 활용해보았어요!

DOMContentLoaded 이벤트 리스너를 통해 HTML 문서가 완전히 로드되고 파싱된 후에 코드를 실행해요. 이는 할 일 목록 관련 스크립트가 문서의 나머지 부분이 로드되기를 기다리지 않고 실행될 수 있도록 하려고 한번 활용해보았어요.

const todoForm = document.getElementById("todoForm");
const inputField = document.querySelector(".TodoInput");
const todoList = document.querySelector(".todoList");

// 할 일 목록 불러오기 및 표시
function loadToDos() {
// 목록을 비우기
while (todoList.firstChild) {
todoList.removeChild(todoList.firstChild);
}

// 로컬 스토리지에서 할 일 목록을 불러와서 페이지에 추가
const toDos = JSON.parse(localStorage.getItem("toDos")) || [];
Copy link
Member

Choose a reason for hiding this comment

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

로컬 스토리지까지 정말 짱입니다~!

toDos.forEach((todo) => {
addTodoItem(todo, false); // 이미 저장된 항목을 불러오므로, 여기서는 save 파라미터를 false로 설정
});
}

// 할 일 추가
function addTodoItem(todoText, save = true) {
const todoItem = document.createElement("li");
todoItem.classList.add("animate-slide-down");

const todoTextContent = document.createElement("span");
todoTextContent.textContent = todoText;

// 삭제 버튼
const deleteButton = document.createElement("button");
deleteButton.textContent = "삭제";
deleteButton.onclick = function () {
todoList.removeChild(todoItem);
removeTodoFromStorage(todoText);
};

// 완료 체크 이미지 생성
const completeCheck = document.createElement("img");
completeCheck.src = "./icon/NotCheck.svg";
completeCheck.style.cursor = "pointer";
completeCheck.setAttribute("data-checked", "false");

completeCheck.onclick = function () {
const isChecked = this.getAttribute("data-checked") === "true";
if (isChecked) {
this.src = "./icon/NotCheck.svg";
this.setAttribute("data-checked", "false");
todoTextContent.style.textDecoration = "none";
todoItem.style.color = "white";
} else {
this.src = "./icon/checkComplete.svg";
this.setAttribute("data-checked", "true");
todoTextContent.style.textDecoration = "line-through";
todoItem.style.color = "#808080";
}
};

todoList.insertBefore(todoItem, todoList.firstChild);
todoItem.appendChild(completeCheck);
todoItem.appendChild(todoTextContent);
todoItem.appendChild(deleteButton);
Comment on lines +84 to +86
Copy link

Choose a reason for hiding this comment

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

이렇게도 표현이 가능하답니다 😆

Suggested change
todoItem.appendChild(completeCheck);
todoItem.appendChild(todoTextContent);
todoItem.appendChild(deleteButton);
todoItem.append(completeCheck, todoTextContent, deleteButton)

Copy link
Member Author

Choose a reason for hiding this comment

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

한줄로 넣는 방법 감사합니다.


if (save) {
saveTodoToStorage(todoText);
}
}

// 로컬 스토리지에 할 일 저장
function saveTodoToStorage(todoText) {
const toDos = JSON.parse(localStorage.getItem("toDos")) || [];
toDos.push(todoText);
localStorage.setItem("toDos", JSON.stringify(toDos));
}

// 로컬 스토리지에서 할 일 삭제
function removeTodoFromStorage(todoText) {
const toDos = JSON.parse(localStorage.getItem("toDos")) || [];
const updatedToDos = toDos.filter((todo) => todo !== todoText);
localStorage.setItem("toDos", JSON.stringify(updatedToDos));
}

// 폼 제출 이벤트 처리
todoForm.addEventListener("submit", function (e) {
e.preventDefault();
const todoText = inputField.value.trim();
Copy link
Member

Choose a reason for hiding this comment

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

trim()을 사용해 아무것도 입력되지 않을 때 리스트가 추가되지 않도록 꼼꼼하게 신경써주신 것 좋습니다~!

Copy link
Member

Choose a reason for hiding this comment

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

alert()를 함께 띄워줘도 좋을 것 같아요ㅎㅎ

if (todoText !== "") {
addTodoItem(todoText);
inputField.value = "";
}
});

// 페이지 로드 시 할 일 목록 불러오기
loadToDos();
});
70 changes: 66 additions & 4 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ h1 {
margin: 0;
}

/* 애니메이션 */
@keyframes slideDownFadeIn {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

.animate-slide-down {
animation: slideDownFadeIn 0.2s ease-out forwards;
}
Copy link

Choose a reason for hiding this comment

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

애니메이션까지! 좋아요!

/* */
Copy link

Choose a reason for hiding this comment

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

필요없는 주석은 삭제하는 것이 좋아요 > <


.wrapper {
width: 100%;
min-height: 100vh;
Expand Down Expand Up @@ -101,13 +118,58 @@ h1 {
.submitBtn {
cursor: pointer;
background-color: #252423;
border: 1px solid #8e8986;
width: 60px;
height: 30px;
border: 1px solid #788bff;
width: 42px;
height: 22px;
border-radius: 10px;
font-size: 12px;
color: #8e8986;
color: #788bff;
}
.submitBtn:hover {
background-color: #3c3a39;
}

.todoList {
width: 100%;
list-style: none;
}

.todoList li {
width: 100%;
height: 52px;
border-radius: 10px;
font-size: 13px;

Copy link
Member

Choose a reason for hiding this comment

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

스크린샷 2024-03-17 오전 4 42 11

이렇게 쓸 일은 잘 없겠지만 ㅎㅎ 혹시 모를 경우를 방지하기 위해
word-break : break-all;
추가해주셔도 좋을 것 같습니다~!

Copy link
Member Author

Choose a reason for hiding this comment

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

오.. 이런 오류가 있었군요. 리팩토링하면서 수정해볼게요. 감사합니다~!

display: flex;
justify-content: space-between;

align-items: center;
background-color: #252423;
padding-right: 5px;
margin: 5px 0px;
padding: 0 15px 0 15px;
color: #cdcdcd;
}
.todoList li span {
width: 100%;
padding: 0px 26px;
}

.todoList li input {
width: 20px;
height: 20px;
}

.todoList li button {
cursor: pointer;
background-color: #252423;
border: 1px solid #788bff;
width: 36px;
height: 22px;
border-radius: 10px;
font-size: 12px;
color: #788bff;
}
.todoList li button:hover {
background-color: #3c3a39;
}