Westagram 추가구현

mia·2022년 12월 16일
0

🔥 구현 할 내용

  1. ID, PW 유효성 검사 (아이디 '@' 포함, 비밀번호 5글자이상 + 입력했을 때만 버튼 누를 수 있게 설정)
  2. 댓글 좋아요 / 삭제 기능 (모든 댓글에 적용)
  3. 미디어쿼리를 사용하여 반응형 웹 구현
  4. nav bar 프로필 이미지 클릭시 메뉴박스 생성
  5. 아이디 검색 기능

💡핵심 코드

1. 유효성 검사

: id와 pw의 유효성을 각각 체크하는 함수를 만들어 button을 활성, 비활성화 시켜주는 함수에 연결했다.

const idInput = document.getElementById("idInput");
const pwInput = document.getElementById("pwInput");
const loginBtn = document.querySelector(".loginBtn");

let idCheck = false;
let pwCheck = false;

function checkId() {
  idInput.value !== "" && idInput.value.includes("@")
    ? (idCheck = true)
    : (idCheck = false);
  activeButton();
}

function checkPw() {
  pwInput.value.length >= 5 ? (pwCheck = true) : (pwCheck = false);
  activeButton();
}

function activeButton() {
  idCheck === true && pwCheck === true
    ? (loginBtn.style.backgroundColor = "#033b71")
    : (loginBtn.style.backgroundColor = "#c5e1fb");
}

idInput.addEventListener("keyup", checkId);
pwInput.addEventListener("keyup", checkPw);

2. 댓글 좋아요 / 삭제 기능

: className 메소드에서 요소에 속성값을 부여할 수 있는setAttribute 메소드로 변경.
댓글을 새로 만드는 함수안에 하트와 삭제 변수 이름을 활용해 eventListener를 달아 삭제와 하트를 만들어주는 함수를 호출할 수 있도록 만들었다.
대신 하트를 취소할 수 있도록 isRed라는 변수로 스위치처럼 빨간색인지 아닌지 체크해주도록 했다.

const comment = document.getElementById("comment");
const commentInput = document.getElementById("commentInput");
const ul = document.querySelector(".comment-lists");
const heart = document.querySelector(".heart");
const deleteBtn = document.querySelector(".delete");
const commentBtn = document.getElementById("commentBtn");

function addComment(input) {
  const li = document.createElement("li");
  const span_bold = document.createElement("span");
  const span = document.createElement("span");
  const img = document.createElement("img");
  const span_gray = document.createElement("span");
  const span_delete = document.createElement("span");

  span_bold.setAttribute("class", "bold");
  span.setAttribute("class", "space");
  img.setAttribute("class", "heart");
  span_gray.setAttribute("class", "gray");
  span_delete.setAttribute("class", "delete gray");
  img.setAttribute("src", "img/heart.png");

  span_bold.innerText = "mia_seo";
  span.innerText = input;
  span_delete.innerText = "삭제";
  span_gray.innerText = "90분전";

  li.appendChild(span_bold);
  li.appendChild(span);
  li.appendChild(img);
  li.appendChild(span_gray);
  li.appendChild(span_delete);
  ul.appendChild(li);

  img.addEventListener("click", onClickHeart);
  span_delete.addEventListener("click", onClickDelete);
}

function onSubmitInput(event) {
  event.preventDefault();
  addComment(commentInput.value);
  commentInput.value = "";
}

let isRed = false;

function onClickHeart(event) {
  if (isRed === false) {
    event.target.src = "img/heart-fill.png";
    isRed = true;
  } else {
    event.target.src = "img/heart.png";
    isRed = false;
  }
}

function onClickDelete(event) {
  const li = event.target.parentElement;
  li.remove();
}

function onKeyUpInput() {
  commentInput.value !== ""
    ? (commentBtn.style.color = "#2099f1")
    : (commentBtn.style.color = "#c5e1fb");
}

comment.addEventListener("submit", onSubmitInput);
commentInput.addEventListener("keyup", onKeyUpInput);
heart.addEventListener("click", onClickHeart);
deleteBtn.addEventListener("click", onClickDelete);

3. 반응형 웹 구현

: 화면 크기가 815px 보다 작을 경우 사이드 부분을 보이지 않도록 설정.

@media screen and (max-width: 815px) {
  .mainRight {
    display: none;
  }
}

4. nav bar 프로필 이미지 클릭시 메뉴박스 생성

: 처음에는 isClicked 변수를 주어 isClicked의 boolean 값에 따라 메뉴박스의 class를 변경하는 식으로 짰는데 toggle이라는 아름다운 메소드가 스위치해주는 역할을 해주었다.❤️

const myProfile = document.getElementById("myProfile");
const myProfileBubble = document.getElementById("myProfileBubble");

let isClicked = false;

function onClickProfile() {
  if (isClicked === false) {
    myProfileBubble.classList.remove("hide");
    isClicked = true;
  } else {
    myProfileBubble.classList.add("hide");
    isClicked = false;
  }
}

// 또는 이렇게도 구현 가능하다.
function onClickProfile() {
  myProfileBubble.classList.toggle("hide");
}

myProfile.addEventListener("click", onClickProfile);

5. 아이디 검색 기능

: idArray에 id를 배열에 넣고 idObject에 id값을 key, src값을 value로 넣어주었다.
checkArray함수에서는 idArray를 하나씩 돌면서 startsWith 메소드가 input.value의 값으로 시작하면 makeSearch함수로 입력한 값과 일치하는 아이디 값을 주었다.
마지막 makeSearch 함수에서 가져간 key값을 활용해 각각의 id에 맞는 이미지를 연결해서 검색창에 뜨도록 설정해주었다.

const searchInput = document.getElementById("search");
const searchBubble = document.getElementById("searchBubble");
const bubble = document.createElement("div");

const idArray = [
  "greenMon",
  "cco_cco",
  "queoqa",
  "eeeeeasy",
  "drink_lover",
  "huhuhu",
];

const idObject = {
  greenMon: "img/1.png",
  cco_cco: "img/2.png",
  queoqa: "img/3.png",
  eeeeeasy: "img/4.png",
  drink_lover: "img/5.png",
  huhuhu: "img/6.png",
};

function makeSearch(key) {
  const bubble_inside = document.createElement("div");
  const img = document.createElement("img");
  const p = document.createElement("p");

  bubble.setAttribute("class", "bubble");
  bubble_inside.setAttribute("class", "bubble-inside");
  img.setAttribute("src", idObject[key]);
  img.setAttribute("class", "profile-photo active");

  p.innerText = key;

  bubble_inside.appendChild(img);
  bubble_inside.appendChild(p);
  bubble.appendChild(bubble_inside);
  searchBubble.appendChild(bubble);
  deleteBubble(searchBubble);
}

function checkArray() {
  if (searchInput !== "")
    for (let i = 0; i < idArray.length; i++) {
      if (idArray[i].startsWith(searchInput.value)) {
        makeSearch(idArray[i]);
      }
    }
}

searchInput.addEventListener("keyup", checkArray);

❓ 궁금점

  • Templete Literals로 makeSearch나 addComment처럼 추가할 내용을 구현할 수 있다고 하는데 혼자 해보니 잘 되지 않았다. 물론 바닐라 자바스크립트의 DOM을 활용한 방식은 현업에서 잘 사용하지 않는다고 하지만 다시 한번 체크해보는 걸루..
  • 검색창 입력시 keyup 이벤트가 발생할 때마다 체크를 하는 바람에 같은 아이디가 중복해서 나타나는 현상이 발생했다. 해결 방법을 찾아야겠다.
  • git으로 계속 관리하다보니 git push는 commit 할 때 항상 같이 일어나는 부분인지 아니면 commit만 먼저 여러번 하고 push를 한번에 해도 되는지 궁금해졌다.

💞 고생한 나 💞

일주일동안 거의 조울증 수준으로 코드 하나에 기분이 오락가락했다.
중간중간 스스로 의심하고 이대로 괜찮을까 싶었지만 금요일이 되니 많이 성장한것만 같은 기분이 들었다.
오늘은 나 자신을 조금 칭찬해주었댱💓

profile
노 포기 킾고잉

0개의 댓글