JS | 바닐라로 검색기 만들기

sik2·2022년 8월 30일
0

JavaScript

목록 보기
11/11

App.js

const API_ENDPOINT = "api url이 들어갑니다."
      
const api = {
  fetchCats: async keyword => {
    try{
      const response = await fetch(`${API_ENDPOINT}/api/items/search?q=${keyword}`);
      if(response.ok)
        return await response.json();
    }catch(e){
      console.error(e);
    }
  },

  itemId: async id => {
    try{
      const response = await fetch(`${API_ENDPOINT}/api/items/${id}`);
      if(response.ok)
        return await response.json();
    }catch(e){
      console.error(e);
    }

  }
};

SearchResult.js


class SearchResult {
    $searchResult = null;
    data = null;
    onClick = null;
  
    constructor({ $target, initialData, onClick }) {
      this.$searchResult = document.createElement("div");
      this.$searchResult.className = "SearchResult";
      $target.appendChild(this.$searchResult);
  
      this.data = initialData;
      this.onClick = onClick;
  
      this.render();
  
      window.addEventListener('scroll', (e) => {
        let scrollLocation = document.documentElement.scrollTop;
        let windowHeight = window.innerHeight;
        let fullHeight = document.body.scrollHeight;
      
        if(scrollLocation + windowHeight >= fullHeight){
          this.appendPage();
          
        }
      });
    }
  
    //[D] Data추가
    appendPage() {
      const list = this.data
      .map(
        cat => {
          const div = document.createElement('div');
          div.className = "item";
          div.innerHTML =
          `
        <img src=${cat.url} alt=${cat.name} />
        <div class="hover">${cat.name}</div>
        `;
        this.$searchResult.appendChild(div);
      });
      
      this.$searchResult.querySelectorAll(".item").forEach(($item, index) => {
        $item.addEventListener("click", () => {
          this.onClick(this.data[index]);
        });
      });
    }
  
    setState(nextData) {
      this.data = nextData;
      this.render();
    }
  
    render() {
      if(this.data.length !== 0){
        this.$searchResult.innerHTML = this.data
          .map(
            item => `
              <div class="item">
                <img src=${item.url} alt=${item.name} />
                <div class="hover">${item.name}</div>
              </div>
            `
          )
          .join("");
    
        this.$searchResult.querySelectorAll(".item").forEach(($item, index) => {
          $item.addEventListener("click", () => {
            this.onClick(this.data[index]);
          });
        });
      }else {
        this.$searchResult.innerHTML =`
            <strong>검색된 결과가 없습니다</strong>
        `
      }
    }
  }
  • SearchInput.js
const TEMPLATE = '<input type="text">';

class SearchInput {
  constructor({ $target, onSearch, onClick }) {
    const box = document.createElement('div');
    box.className = 'box';

    const $searchInput = document.createElement("input");
    this.$searchInput = $searchInput;
    this.$searchInput.placeholder = "아이템을 검색해보세요.|";

    // [D] autofocus 추가
    this.$searchInput.setAttribute('autofocus','autofocus');

    $searchInput.className = "SearchInput";

    this.$randomButton = document.createElement('button');
    this.$randomButton.className ='button';

    box.appendChild(this.$searchInput);
    box.appendChild(this.$randomButton);
    $target.appendChild(box);

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

    this.$randomButton.addEventListener("click", () => {
      onClick();
    });
 
  }
  render() {}
}

ImageInfo.js

class ImageInfo {
    $imageInfo = null;
    data = null;
  
    constructor({ $target, data }) {
      const $imageInfo = document.createElement("div");
      $imageInfo.className = "ImageInfo";
      this.$imageInfo = $imageInfo;
      $target.appendChild($imageInfo);
  
      this.data = data;
  
      this.render();
  
      this.$imageInfo.addEventListener('click', (e) => {
        const className = e.target.className;
        if(className ==='ImageInfo' || className === 'close') {
   
          this.fadeOut(this.$imageInfo);
        }
      })
  
      window.onkeyup = (e) => {
        var key = e.keyCode ? e.keyCode : e.which;
        if(key === 27){
          if(this.$imageInfo.style.display === 'block')
            this.fadeOut(this.$imageInfo);
        }
      }
    }
  
    setState(nextData) {
      this.data = nextData;
      this.render();
    }
  
    fadeOut(element) {
      var op = 1;
      var timer = setInterval(function () {
          if (op <= 0.1){
              clearInterval(timer);
              element.style.display = 'none';
          }
          element.style.opacity = op;
          element.style.filter = 'alpha(opacity=' + op * 100 + ")";
          op -= op * 0.1;
      }, 50);
    }
  
    fadeIn(element) {
      var op = 0.1;
      element.style.display = 'block';
      var timer = setInterval(function () {
          if (op >= 1){
              clearInterval(timer);
          }
          element.style.opacity = op;
          element.style.filter = 'alpha(opacity=' + op * 100 + ")";
          op += op * 0.1;
      }, 10);
    }
  
    render() {
      if (this.data.visible) {
        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>`;

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

Loading.js

const template = `
    <div class="loading"></div>
    <div id="loading-text">loading</div>
`;

class LoadingInfo {
    $loadingInfo = null;
    data = null;
  
    constructor({ $target, data }) {
        const $loadingInfo = document.createElement("div");
        $loadingInfo.className = "loading-container";
        this.$loadingInfo = $loadingInfo;
        this.data = data;
        this.$loadingInfo.style.display = this.data.visible ? 'block' : 'none';
        $target.appendChild($loadingInfo);
    
        this.render();
  
    }

    onChange() {
        this.data.visible = !this.data.visible;
        this.$loadingInfo.style.display = this.data.visible ? 'block' : 'none';
    }
  
    render() {
        this.$loadingInfo.innerHTML = template;
    }
  }
profile
기록

0개의 댓글