Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

훈돌라

2024. 5. 7. 두 번째 팀 과제 (4) 본문

카테고리 없음

2024. 5. 7. 두 번째 팀 과제 (4)

훈돌라 2024. 5. 7. 19:37

저번 글에 이어서

오늘은 팀원분이 완성해두신 상세페이지 -> 리뷰 작성 기능에 유효성 검사를 추가해보려고 한다.

 

 

우선 어떤 식으로 유효성 검사를 구현할지 먼저 생각을 좀 해봤다.

 

1. 댓글 텍스트 수

2. 캡스락 keyup 여부
3. 한/영 여부

인데, 사실 한/영 여부는 불필요하다고 생각했고, 댓글 텍스트 수도 실제로는 제한이 없기 때문에

 

2. 캡스락 keyup 여부를 구현하기로 했다.

 

  const usernameInput = document.getElementById("username");

  usernameInput.addEventListener("keyup", function (event) {
    if (event.getModifierState("CapsLock")) {
      // CapsLock이 켜져 있을 때
      document.getElementById("capslock-warning").innerText = "CapsLock 이 활성화 되어있는 상태입니다";
    } else {
      // CapsLock이 꺼져 있을 때
      document.getElementById("capslock-warning").innerText = "";
    }
  });

 

사실 이벤트 리스너에 대해 구글링을 하다 keyup 게시글도 우연히 보게 되어서 어떻게 구현해야 할지 대충

 

감이 잡혀있는 상태여서 비교적 쉽게 (?) 구현할 수 있었다.

 

무슨 기능이 있고, 어떻게 쓰이며, 어디에 들어가야 할지만 안다면 시간이 좀 걸릴 뿐 불가능하진 않은 것 같다.

 

그래서 많이 검색해보고, 구현해보고, 보지만 말고 직접 해보는게 중요한 것 같다. (개인적 견해입니다)

 

단점은, 아직 내 코드에 대해 시원하게 풀이를 하지 못한다는 점? 그리고 알고리즘에 약하다는 점....

익숙해지겠지?

 

 

 

username 인풋에서 capsLock 을 누를 시 innertext 로 문구를 띄움.

 


 

 

유효성 검사만 구현하려고 하다보니 시간이 꽤 남아서 팀원분들께 " 수정할거 없나요, 저 조금 더 고생해도 되는데 "

 

라고 하니 

 

수정하는 버튼 누르면 아예 비밀번호 입력이랑 수정할 내용을 한꺼번에 모달창으로 띄워도 괜찮을 것 같다는 생각이 들었어요!

 

라는 아이디어를 제시 해주셨다. ( 당시엔 이게 나의 하루를 잡아먹을거라고는 전혀 생각하지 못했다. )

 

 

 

기존 코드는 수정하기 버튼을 눌렀을 때 alert 을 띄워 패스워드를 입력하게 하고, 패스워드가 일치한다면

 

새로운 내용을 작성하게 하고, 작성 후 확인 버튼을 누르면 댓글창에 반영이 되는 방식이였다.

 

기능 구현에 의의를 둔다면 이것도 상관없긴 하지만, 조금 더 깔끔하게? 하고 싶으셨던 모양이다!

 

그리고 또 하나의 문제는 alert 은 비밀번호를 **** 표시 할 수 없다는 점.


여러모로 모달창을 띄우는 편이 깔끔하기도 하고, 기능적으로도 괜찮을 것 같다는 생각이 들었다.

 


 

    <!-- 모달 창 (댓글수정) -->
    <div id="modal" class="modal">
      <div class="modal-content">
        <div class="modal-input">
          <input id="passwordInput" type="password" placeholder="패스워드를 입력하세요.">
          <textarea id="commentInput" placeholder="수정하실 내용을 입력하세요."></textarea>
        </div>
        <div class="modalbtn">
          <button id="submitBtn"><span style="color: white;">확인</span></button>
          <button id="cancelBtn"><span style="color: white;">취소</span></button>
        </div>
      </div>
    </div>

 

스크립트 작성에 앞서 우선 html 에 모달창을 만들어줬다.

 

비밀번호 input, 본문이 들어갈 input, 확인 버튼, 취소 버튼으로 이루어져 있다.

 

 

  display: none;
  /* 기본적으로는 숨김 */
  position: fixed;
  /* 고정 위치 */
  z-index: 1;
  /* 다른 요소 위에 표시 */
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  /* 스크롤 가능 */
  background-color: rgba(0, 0, 0, 0.4);
  /* 배경색과 투명도 */
}

.modal-content {
  background-color: #fefefe;
  margin: 15% auto;
  /* 중앙 정렬 */
  padding: 60px;
  border: 1px solid #888;
  width: 80%;
  /* 모달창 너비 */
}

#passwordInput {
  margin-bottom: 10px;
  border: 1px solid #ccc;
  /* 테두리 스타일 지정 */
  padding: 5px;
  /* 안쪽 여백 지정 */
  border-radius: 4px;
  /* 테두리 모서리를 둥글게 만듦 */
}

#commentInput {
  width: 1215px;
  height: 85;
  border: 1px solid #ccc;
  /* 테두리 스타일 지정 */
  padding: 5px;
  /* 안쪽 여백 지정 */
  border-radius: 4px;
  /* 테두리 모서리를 둥글게 만듦 */
}

.modalbtn {
  float: right;
  padding-top: 20px;
}

#submitBtn {
  background-color: blue;
}

#cancelBtn {
  background-color: red;
}

 

모달창은 수정하기 버튼을 눌렀을 때만 나와야 하기 때문에 display : none; 으로 기본적으로는 숨김 상태여야 한다.

 

그리고 팝업창 느낌으로 다른 요소 위에 표시하기 위해 z-index: 1; 을 사용했다.

 

모달창이 떠있는 중에도 페이지를 스크롤 할 수 있게  overflow : auto; 를 사용했다.

 

 

완성된 모달창

 

 

  // 댓글 수정 (모달)
  const editComment = (e) => {
    const commentBox = e.target.parentNode.parentNode.parentNode.parentNode;
    const commentOnStorage = getComments(movieId);
    const modal = document.getElementById("modal");
    const passwordInput = document.getElementById("passwordInput");
    const commentInput = document.getElementById("commentInput");
    const submitBtn = document.getElementById("submitBtn");
    const cancelBtn = document.getElementById("cancelBtn");

    modal.style.display = "block"; // 모달창 열기

    // 모달창 닫기
    const closeModal = () => {
      modal.style.display = "none";
      passwordInput.value = "";
      commentInput.value = "";
    };

    // 확인 버튼 클릭 시
    submitBtn.onclick = () => {
      const passwordEditTry = passwordInput.value;
      commentOnStorage.forEach((element) => {
        if (commentBox.getAttribute("id") === String(element.Id)) {
          if (passwordEditTry === element.Password) {
            element.Review = commentInput.value;
            saveComments(movieId, commentOnStorage);
            alert("저장되었습니다.");
            closeModal(); // 모달 닫기
            location.reload(); // 페이지 새로고침
          } else {
            alert("비밀번호가 일치하지 않습니다.");
            closeModal(); // 모달 닫기
          }
        }
      });
    };

    // 취소 버튼 클릭 시
    cancelBtn.onclick = () => {
      closeModal(); // 모달 닫기
    };

    // 모달 외부 클릭 시 닫기
    window.onclick = (event) => {
      if (event.target === modal) {
        closeModal(); // 모달 닫기
      }
    };
  };

  const editBtn = document.querySelectorAll(".edit");
  editBtn.forEach((element) => element.addEventListener("click", editComment));

 

각각의 댓글에는 수정 버튼이 존재하고, 수정 버튼을 클릭하면 만들어둔 모달 창이 나오게 하는 코드다.

 

댓글을 작성했을 때 기입해둔 패스워드와 입력한 패스워드가 일치하고, 수정할 본문을 작성한 후 확인 버튼을 누르면

 

댓글이 수정되고, 모달 창이 닫히며, 페이지가 로드되어 새로고침 하지 않아도 자동으로 수정된 댓글이 반영된다.

 

비밀번호가 일치하지 않으면 "비밀번호가 일치하지 않습니다. " 라는 alert 과 함께 모달창이 닫혀버리고, 댓글은 수정되지 않는다.

 


 

 

 

수정하기 옆 삭제하기 버튼 클릭 시, 수정하기와 마찬가지로 모달창을 띄워 패스워드를 입력하게 끔 구현했고,

댓글 작성 시 기입한 패스워드와 일치한다면 "삭제되었습니다" alert 과 함께 페이지가 로드되고, 댓글이 삭제된다.

 

else -> 비밀번호가 일치하지 않다면,  "비밀번호가 일치하지 않습니다." alert 과 함께 모달창이 닫힌다.

 

    <!-- 모달 창 (댓글삭제) -->
    <div id="delmodal" class="delmodal">
      <div class="delmodal-content">
        <span class="close">&times;</span>
        <p style="text-align: center;">패스워드를 입력해주세요.</p>
        <div class="delbtn">
        <input type="password" id="delpasswordInput" />
        <button id="delconfirmBtn">확인</button>
      </div>
      </div>
    </div>

 

댓글삭제 모달창 html

 

.delmodal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0, 0, 0);
  background-color: rgba(0, 0, 0, 0.4);
}

.delmodal-content {
  background-color: #fefefe;
  margin: 15% auto;
  padding: 20px;
  border: 1px solid #888;
  width: 80%;
}

.close {
  color: #aaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: black;
  text-decoration: none;
  cursor: pointer;
}

#delpasswordInput {
  border: 1px solid #ccc;
  /* 테두리 스타일 지정 */
  padding: 5px;
  /* 안쪽 여백 지정 */
  border-radius: 4px;
  /* 테두리 모서리를 둥글게 만듦 */
}

.delbtn {
  margin-left: 500px;
  margin-top: 10px;
}

 

댓글삭제 모달창 css

 

const modal = document.getElementById("delmodal");
  const confirmBtn = document.getElementById("delconfirmBtn");
  const passwordInput = document.getElementById("delpasswordInput");

  const deleteComment = (event) => {
    const li = event.target.parentElement.parentElement.parentElement.parentElement;
    let cancelSwitch = Boolean;

    commentDrawn.forEach((element) => {
      if (li.getAttribute("id") === String(element.Id)) {
        modal.style.display = "block";

        confirmBtn.onclick = () => {
          const passwordTry = passwordInput.value;
          if (passwordTry === element.Password) {
            cancelSwitch = true;
            li.remove();

            const newComments = commentDrawn.filter(
              (element) => element.Id !== li.getAttribute("id")
            );
            saveComments(movieId, newComments);
            alert("삭제되었습니다.");
            location.reload();
          } else {
            cancelSwitch = false;
            alert("비밀번호가 일치하지 않습니다.");
          }
          modal.style.display = "none";
        };

        modal.querySelector(".close").onclick = () => {
          modal.style.display = "none";
          cancelSwitch = false;
          alert("취소되었습니다.");
        };
      }
    });
  };

  const deleteBtn = document.querySelectorAll(".delete");
  deleteBtn.forEach((element) =>
    element.addEventListener("click", deleteComment)
  );

 

댓글삭제 모달창 script

 

기본중의 기본이지만, 수정 모달창과, 삭제 모달창의 id, class 값을 부여할 때 중복되지 않게 조심해야 한다..

(생각없이 작성하다가 id 값이 똑같은걸 못 찾고 한 참을 헤맴)

 

 

3일을 쉬어서 뇌가 리셋이 된 건 아닐까, 하고 불안했는데 오히려 조금 쉬고 오니 머리가 더 잘 돌아가는 느낌이네.

 

오놀은 진짜 많이 성장했다. 많이 쳐보고 경험치 많이 쌓자.