잡다한 배똥월드

728x90

이미지 상세 보기 모달 관련

  • 디바이스 가로 길이가 768px 이하인 경우, 모달의 가로 길이를 디바이스 가로 길이만큼 늘려야 합니다.
  • 필수 이미지를 검색한 후 결과로 주어진 이미지를 클릭하면 모달이 뜨는데, 모달 영역 밖을 누르거나 / 키보드의 ESC 키를 누르거나 / 모달 우측의 닫기(x) 버튼을 누르면 닫히도록 수정해야 합니다.
  • 모달에서 고양이의 성격, 태생 정보를 렌더링합니다. 해당 정보는 /cats/:id 를 통해 불러와야 합니다.
  • 추가 모달 열고 닫기에 fade in/out을 적용해 주세요.

 


 

1. 모달 가로 길이

     ImageInfo.js의 render() 내에 추가하기

if (window.innerWidth < 768) {
	document.querySelector(".content-wrapper").style.width = window.innerWidth + "px";
}

 

2. 모달 종료

class ImageInfo {
  $imageInfo = null;
  data = null;

  constructor({ $target, data }) {
    const $imageInfo = document.createElement("div");
    $imageInfo.className = "ImageInfo";
    this.$imageInfo = $imageInfo;
    $target.appendChild($imageInfo);

	//1번 : 모달 영역 밖 눌러서 종료
    $imageInfo.addEventListener("click", function(e){
      if ($imageInfo == e.target) {
        closeModal();
      }
    });

	//2번 : esc키 눌러서 종료
    window.addEventListener("keydown", function(e){
      if (e.keyCode == 27 && $imageInfo.style.display != "none") {
        closeModal();
      }
    })

    this.data = data;

    this.render();
  }

  setState(nextData) {
    this.data = nextData;
    this.render();
  }

  render() {
    if (this.data.visible) {
      console.log(this.data.image);
      const { name, url, temperament, origin } = this.data.image;

      this.$imageInfo.innerHTML = `
        <div class="content-wrapper">
          <div class="title">
            <span>${name}</span>
            <div class="close">x</div>
          </div>
          <img src="${url}" alt="${name}"/>        
          <div class="description">
            <div>성격: ${temperament}</div>
            <div>태생: ${origin}</div>
          </div>
        </div>`;
      this.$imageInfo.style.display = "block";

      if (window.innerWidth < 768) {
        resizeModal();
      }

	  //3번 : x 버튼 눌러서 종료
      const close = document.querySelector(".close");
      close.addEventListener("click", closeModal);
      close.style.cursor = "pointer";

    } else {
      this.$imageInfo.style.display = "none";
    }
  }
}

function closeModal() {
  const target = document.querySelector(".ImageInfo");
  target.style.display = "none";
}

function resizeModal() {
  const modal = document.querySelector(".content-wrapper");
  modal.style.width = window.innerWidth + "px";
}

 

3. 고양이의 성격, 태생 정보를 렌더링

     - api.js에 추가

 fetchModal: id => {
    try {
      return fetch(`${API_ENDPOINT}/api/cats/${id}`).then(res =>
        res.json()
      ).then(data => data);
    } catch (e) {
      console.log(e);
    }
}

 

   - App.js에서 변경

    this.searchResult = new SearchResult({
      $target,
      initialData: this.data,
      onClick: async image => {
        const {data} = await api.fetchModal(image.id);
        this.imageInfo.setState({
          visible: true,
          image: data
        });
      }
    });

여기서 조금 많이 어려웠는데, 일단 api에서 코드 작성하는 것의 쉬웠음

근데 그 후 데이터를 활용하는 데에 어려움을 느꼈는데, async랑 await을 쓰니까 바로 해결됬고, 이게 리턴값이 promise라서 그렇다고는 하는데, 나중에 좀 더 공부를 해야하는 부분이라고 생각했음.

↓ 참고 링크 ↓

 

JavaScript - 자바스크립트 fetch와 async/await

컴퓨터/IT/알고리즘 정리 블로그

chanhuiseok.github.io

 

 

4. fade in/out

     - ImageInfo.js에 추가해서 모달이 생길 때와 사라질 때 각각 함수 추가하기

function fadeIn(target) {
  var opacityNum = 0;

  var interval = setInterval(function() {
    if (opacityNum > 1) clearInterval(interval);

    opacityNum += 0.1;
    target.style.opacity = opacityNum;
  }, 10);
}

function fadeOut(target) {
  var opacityNum = 1;

  var interval = setInterval(function() {
    if (opacityNum < 0) {
      clearInterval(interval);
      target.style.display = "none";
    }

    opacityNum -= 0.1;
    target.style.opacity = opacityNum;
  }, 10);
}

 

 

 

728x90
728x90

HTML, CSS 관련

  • 현재 HTML 코드가 전체적으로 <div> 로만 이루어져 있습니다. 이 마크업을 시맨틱한 방법으로 변경해야 합니다.
  • 유저가 사용하는 디바이스의 가로 길이에 따라 검색결과의 row 당 column 갯수를 적절히 변경해주어야 합니다.
    • 992px 이하: 3개
    • 768px 이하: 2개
    • 576px 이하: 1개
  • 다크 모드(Dark mode)를 지원하도록 CSS를 수정해야 합니다.
    • CSS 파일 내의 다크 모드 관련 주석을 제거한 뒤 구현합니다.
    • 모든 글자 색상은 #FFFFFF , 배경 색상은 #000000 로 한정합니다.
    • 기본적으로는 OS의 다크모드의 활성화 여부를 기반으로 동작하게 하되, 유저가 테마를 토글링 할 수 있도록 좌측 상단에 해당 기능을 토글하는 체크박스를 만듭니다.

 


1. 시맨틱한 방법으로 변경

 

2. column 갯수 변경

@media (max-width: 992px) {
  .SearchResult {
    grid-template-columns: repeat(3, minmax(250px, 1fr));
  }
}

@media (max-width: 768px) {
  .SearchResult {
    grid-template-columns: repeat(2, minmax(250px, 1fr));
  }
}

@media (max-width: 576px) {
  .SearchResult {
    grid-template-columns: repeat(1, minmax(250px, 1fr));
  }
}

 

3. 다크 모드(Dark mode)를 지원

     css에 추가

/*dark mode 처리*/
@media (prefers-color-scheme: dark) {
  body {
    background-color: #000;
    color: white;
  }
}

.darkmode {
  background-color: #000;
  color: #FFF;
}

.mode {
  margin: 0;
  padding: auto 0;
  text-align: center;
}

.Search_Mode_Box {
  display: flex;
  width: 100%;
}

 

     SearchInput.js 변경

const TEMPLATE = '<input type="text">';
const body = document.getElementById("body");

class SearchInput {
  constructor({ $target, onSearch }) {
    const box = document.createElement("div");
    const mode = document.createElement("span");

    const $searchInput = document.createElement("input");
    this.$searchInput = $searchInput;
    this.$searchInput.placeholder = "고양이를 검색해보세요.|";

    box.classList.add("Search_Mode_Box");

    $searchInput.className = "SearchInput";
    box.appendChild(mode);
    box.appendChild($searchInput);

    $target.appendChild(box);

    mode.style.height = $searchInput.offsetHeight + "px";
    mode.style.width = mode.offsetHeight + "px";
    mode.style.lineHeight = mode.offsetHeight + "px";
    mode.classList.add("mode");

    let inputwWidth = box.offsetWidth - mode.offsetWidth;
    $searchInput.style.width = inputwWidth + "px";

    if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
      mode.innerText = "light";
    } else {
      mode.innerText = "dark";
    }

    mode.addEventListener("click", function() {
      body.classList.toggle("darkmode");

      if (mode.textContent == "dark") {
        mode.innerText = "light";
      } else {
        mode.innerText = "dark";
      }
    });

    $searchInput.addEventListener("keyup", e => {
      if (e.keyCode === 13) {
        onSearch(e.target.value);
      }
    });

    console.log("SearchInput created.", this);
  }

  render() {}
}

 

나의 경우에는 검색창 옆에 다크 토글을 만들려고 했고, 나란히 두기 위해서 따로 div 태그를 추가하여 박스를 만들어 flex로 display를 설정했음.

- 라이트 모드

- 다크 모드

 

 

 

728x90

+ Recent posts