자신에게 친절할 것 :)

Projects

[Momentum_ problem shooting] 체크박스 클릭 시 리스트 아래로, 체크된 리스트 삭제, 투두 수정 등 모멘툼 기능 구현 끝!

Tashapark 2024. 4. 28. 23:55
728x90

모멘툼을 직접 계속 사용하면서 생각하고,

사용하는 다른 친구들한테도 피드백 받았던 기능들은 전부 구현을 끝냈다!

 

아직 코드 리팩토링이랑

css 파일 분할을 못했지만 브라우저는 완성된 셈이다. 

 

기간을 딱 픽스하고 한 것이 아니라,

다른 것 하면서 매일 조금씩 한 것이라서 "해냈다!!" 보다는 뭔가

해야할 것.. 질질 끌던 것.. 드디어 끝냈다!!! 같다 ㅎㅎ

이것들 외에도 자잘하게 수정하던 것들이 많지만,, 기억이 안나서 굵직한 것들로만 가지고 왔다. 

...

+ 생각해보니 아직 페이지 새로고침 시.. 배경화면 로딩 시간이... 긴 문제는 해결하지 못했네..ㅎ


1. 체크 박스 클릭 한 것을 자동으로 리스트 끝으로 보내기

이유)  이것은 사용하다 보니 순서대로 끝내는 것이 아니라서, 들쭉 날쭉으로 체크된 것이 보기 싫어서 고민하다가 구현했다. 

 

문제와 해결) 구현 시 제일 어려웠던 것은 "어떻게" 끝으로 보낼 것인가.

1.  처음에는 아직도 컴퓨터적인 사고를 못해서 어떻게 내릴 지를 고민했는데 검색을 하다보니,

 --> 현재 위치에서 "지우고 splice()", 맨 밑에 다시 "추가 push()" 하면 되어서 checkedMoveTodo 함수를 만들었음 

 

2. 새로고침을 해야지만, 계속 리스트의 끝에 추가되고 바로 적용이 안됨

- gpt 와 계속 싸우기 시작...

- 문제의 원인을 계속 찾지 못하고, 구현에 문제가 없다는 이야기를 반복하고, 

나 역시, 콘솔 상에 안나오는데 에러도 없다.. 디버깅이 안된다를 반복했음.

- 결국 reload 버튼을 만들어서 누르게 하려다가 

-  전체 코드를 다시 살펴보는데.. 

    // 목록에서 해당 li 요소 삭제
    toDoList.removeChild(li);
    // 목록의 마지막에 다시 추가
    toDoList.appendChild(li);

......ㅎ 화면 상 보이게 안 했으니,, 새로고침을 해야지만 나타나는 것이었다.

 

--> 위 코드를 추가함. 

 

3. 코드가 너무 겹침.

- 이미 checkToDo 함수가 있고 겹치는 부분이 많아서, 기존 코드에 추가하는 것으로  --> 리팩토링함. 

function checkToDo(event) {
  //체크박스 줄 그어지는 것 만들어주려고
  const checkbox = event.target; //무조건 따로 정의를 해줄 것
  const text = checkbox.nextElementSibling; // 체크박스 다음 요소인 텍스트 가져오기
  const li = checkbox.parentElement; // li 요소를 가져옵니다.

  // 체크된 상태인 경우에만 마지막으로 이동시킵니다.
  if (checkbox.checked) {
    // 목록에서 해당 li 요소를 삭제합니다.
    toDoList.removeChild(li);
    // 목록의 마지막에 다시 추가합니다.
    toDoList.appendChild(li);
  }
  if (checkbox.checked) {
    text.style.textDecorationLine = "line-through";
  } else {
    text.style.textDecorationLine = "none";
  }
  // 변경된 체크박스 상태를 로컬 스토리지에 저장
  const todoId = li.id; // 부모 요소인 li의 id 가져오기
  const index = toDos.findIndex((todo) => todo.id.toString() === todoId); // 해당 id를 가진 todo의 인덱스 찾기
  if (index !== -1) {
    toDos[index].checked = checkbox.checked; // 해당 todo의 checked 속성 업데이트

    if (checkbox.checked) {
      const checkedItem = toDos.splice(index, 1)[0]; //index 위치의 1개를 제거하되, [0] 제거한 인덱스의 1번째 즉 제거한 것 반환
      toDos.push(checkedItem);
    }
    saveToDos(); // 변경된 todo 리스트를 다시 저장
  }
}

 

 

2. 체크 박스  삭제 버튼 만들기

이유)  하나씩 체크된 것을 삭제시키기가 귀찮아서 만들게 됨

 

문제와 해결) 기능과 css 문제가 있었음. 

1.  기능 구현을 했는데 코드에 따라서 새로고침 때마다 저장이 안됨. 

 --> 함수의 위치를 바꾸고, 기존 코드를 최대한 살려서 만들고, saveToDos() 추가

--> forEach로 체크된 것 훓어서 지우도록 만듦. 

 

2. deleteChecked() 하나의 함수로 끝내고 싶었으나, 그럼 루틴에서 체크된 것도 동시에 삭제. 

--> 코드 분리해서 각각 deleteCheckedTodo()와 deleteCheckedRoutine() 함수로 만들어줌. 

 

3. html에 버튼을 넣어서 스크롤에 따라서 같이 움직이고, 리스트 위 아래에 고정되게 만들고 싶었으나 실패.

- list class에 postion: relative를 넣고, btn에 position: absolute를 넣었으나, 계속 리스트가 아닌 body를 부모로 인식해서 실패함. 

--> 휴지통 버튼의 위치를 to-do form 옆으로 옮기고 form에 display: flex를 줘서 align 한 것으로 만족.. ㅎ

 

# css

.routine__btn__delete {
  position: fixed;
  top: 140px;
  left: 170px;
  border: none;
  font-size: 15px;
  background: transparent;
  color: aliceblue;
  transition: transform 0.3s ease-in-out;
}

#todo-form {
  display: flex;
  justify-content: center;
  text-align: center;
  align-items: center;
  font-size: 30px;
  padding-top: 20px;
  padding-bottom: 10px;
  margin-top: 0;
  margin-bottom: 0;
}

.todo__btn__delete {
  padding: 20px 6px 10px 6px;
  border: none;
  font-size: 15px;
  background: transparent;
  color: aliceblue;
  transition: transform 0.3s ease-in-out;
}

.routine__btn__delete:hover,
.todo__btn__delete:hover {
  color: steelblue;
  background-color: aliceblue;
  border: none;
  border-radius: 15px;
}

 

# js 

const toDoDeleteBtn = document.querySelector(".todo__btn__delete");
const routineDeleteBtn = document.querySelector(".routine__btn__delete");


function deleteCheckedTodo() {
  const checkboxes = document.querySelectorAll(
    "#todo-list input[type='checkbox']:checked"
  );
  checkboxes.forEach((checkbox) => {
    const li = checkbox.parentElement;
    li.remove();
    toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
  });

  saveToDos();
}

function deleteCheckedRoutine() {
  const routineCheckboxes = document.querySelectorAll(
    "#routine-list input[type='checkbox']:checked"
  );
  routineCheckboxes.forEach((checkbox) => {
    const li = checkbox.parentElement;
    li.remove();
    routineToDos = routineToDos.filter(
      (routine) => routine.id !== parseInt(li.id)
    );
  });

  saveRoutines();
}

toDoDeleteBtn.addEventListener("click", deleteCheckedTodo);
routineDeleteBtn.addEventListener("click", deleteCheckedRoutine);

 

 

3. 투두 리스트 수정하기 

이유)  처음에는 그냥 지우고 만들지 하다가, 그렇게 되면 리스트가 밀리고, 친구의 요청으로 추가

 

문제와 해결) 기능 구현이 오래 걸렸고, 저장 문제가 있었음. 

 

1.  기능 구현을 할 때 event.target 변수를 빼먹어서 구현이 계속 안 됐음. 

 --> gpt 조언대로 해도 계속 구현이 안 되서 기존 코드를 살피면서 전면 수정했음.

--> this를 굳이 쓸 필요가 없어서 제외했고, text가 써진 span을 가지고 와야 하는 데 그것을 생각하지 못해서 오래 걸렸음.

-->  attribute = "contenteditable" 수정을 위한 속성을 배움. 

--> 인덱스를 찾은 경우 innerText가 변경되도록 구현. 

 

function editToDo(event) {
  const editBtn = event.target;
  const li = editBtn.parentElement;
  const editText = li.querySelector("span"); // span 요소를 찾음
  if (editText) {
    // editText가 null이 아닌 경우에만 실행
    editText.setAttribute("contenteditable", true); // 편집 가능하도록 설정
    editText.focus(); // 편집 상태로 이동
    editText.addEventListener("blur", () => {
      // 포커스를 잃으면
      editText.removeAttribute("contenteditable"); // contenteditable 속성 제거하여 편집 완료
      const todoId = li.id;
      const index = toDos.findIndex((todo) => todo.id === parseInt(todoId));
      // -1은 특정 아이템을 찾지 못했을 때 반환하는 값
      if (index !== -1) {
        toDos[index].text = editText.innerText;
        saveToDos();
      }
    });
  }
}

 

2. 이 경우는 html에 추가 할 필요 없이 리스트가 생성될때 나타나도록 할 때 fontawesome  넣고 싶었음. 

--> setattribute에 class로 넣어도 되는 데..  개인적으로 이게 더 직관적이라고 느껴져서 이렇게 함. 

function paintToDo(newTodo) {
	...
    const editBtn = document.createElement("button");
    editBtn.innerHTML = '<i class="fa-regular fa-pen-to-square"></i>';
    editBtn.addEventListener("click", editToDo);
    ...
    li.appendChild(editBtn);
    ...
    }

 

 


앞으로도 배경화면이나, 글귀들은 계속 업로드를 하겠지만,

기능적으로는 크게 달라지지 않을 것 같다. 

 

거의 최종본!

 

+++ 아 아직 날씨 api 적용 안되는 거 확인을 안 했구나.. ㅎ

++ 에러보면 웹사이트 내 변경 문제인 것 같던데.. 귀찮아서.. 미루는 중이다 ㅎ

 

 

 

녹음 하다보니...

마지막으로 추가한 영상 버튼이.. 

playlist 입력 input이랑 겹치는 것을 확인해서.. 

저장하고,, 수정하러 가기로 ㅎㅎㅎ

 

증맬 끝이 없구나 ㅎ

728x90
반응형