[30일 챌린지 Day-6] 검색, json 활용

2022. 7. 26. 14:10·개발/html, css, js
728x90
반응형

1. 기본값 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Type Ahead 👀</title>
    <link rel="stylesheet" href="style.css" />
    <style>
      html {
        box-sizing: border-box;
        background: #ffc600;
        font-family: "helvetica neue";
        font-size: 20px;
        font-weight: 200;
      }

      *,
      *:before,
      *:after {
        box-sizing: inherit;
      }

      input {
        width: 100%;
        padding: 20px;
      }

      .search-form {
        max-width: 400px;
        margin: 50px auto;
      }

      input.search {
        margin: 0;
        text-align: center;
        outline: 0;
        border: 10px solid #f7f7f7;
        width: 120%;
        left: -10%;
        position: relative;
        top: 10px;
        z-index: 2;
        border-radius: 5px;
        font-size: 40px;
        box-shadow: 0 0 5px rgba(0, 0, 0, 0.12),
          inset 0 0 2px rgba(0, 0, 0, 0.19);
      }

      .suggestions {
        margin: 0;
        padding: 0;
        position: relative;
        /*perspective: 20px;*/
      }

      .suggestions li {
        background: white;
        list-style: none;
        border-bottom: 1px solid #d8d8d8;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.14);
        margin: 0;
        padding: 20px;
        transition: background 0.2s;
        display: flex;
        justify-content: space-between;
        text-transform: capitalize;
      }

      .suggestions li:nth-child(even) {
        transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001);
        background: linear-gradient(to bottom, #ffffff 0%, #efefef 100%);
      }

      .suggestions li:nth-child(odd) {
        transform: perspective(100px) rotateX(-3deg) translateY(3px);
        background: linear-gradient(to top, #ffffff 0%, #efefef 100%);
      }

      span.population {
        font-size: 15px;
      }

      .hl {
        background: #ffc600;
      }
    </style>
  </head>
  <body>
    <form class="search-form">
      <input type="text" class="search" placeholder="City or State" />
      <ul class="suggestions">
        <li>Filter for a city</li>
        <li>or a state</li>
      </ul>
    </form>
    <script>
      const endpoint =
        "https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json";
    </script>
  </body>
</html>

2-1. 결과값

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Type Ahead 👀</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <form class="search-form">
    <input type="text" class="search" placeholder="City or State">
    <ul class="suggestions">
      <li>Filter for a city</li>
      <li>or a state</li>
    </ul>
  </form>
<script>
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';

const cities = [];
fetch(endpoint)
  .then(blob => blob.json())
  .then(data => cities.push(...data));

function findMatches(wordToMatch, cities) {
  return cities.filter(place => {
    // here we need to figure out if the city or state matches what was searched
    const regex = new RegExp(wordToMatch, 'gi');
    return place.city.match(regex) || place.state.match(regex)
  });
}

function numberWithCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

function displayMatches() {
  const matchArray = findMatches(this.value, cities);
  const html = matchArray.map(place => {
    const regex = new RegExp(this.value, 'gi');
    const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`);
    const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`);
    return `
      <li>
        <span class="name">${cityName}, ${stateName}</span>
        <span class="population">${numberWithCommas(place.population)}</span>
      </li>
    `;
  }).join('');
  suggestions.innerHTML = html;
}

const searchInput = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');

searchInput.addEventListener('change', displayMatches);
searchInput.addEventListener('keyup', displayMatches);

</script>
  </body>
</html>

2-2

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Type Ahead 👀</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <form class="search-form">
      <input type="text" class="search" placeholder="City or State" />
      <ul class="suggestions">
        <li>Filter for a city</li>
        <li>or a state</li>
      </ul>
    </form>
    <script>
      const endpoint =
        "https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json";

      const suggestions = document.querySelector(".suggestions");
      const search = document.querySelector(".search");
      let jsondata = [];
      let suggestionsLi;

      function getJsonData(callback) {
        fetch(endpoint)
          .then((res) => {
            return res.json();
          })
          .then((data) => {
            callback(data);
          });
      }

      function getJsonDataToArr(data) {
        data.forEach((el) => {
          let addList = document.createElement("li");
          suggestions.appendChild(addList);
          addList.innerHTML = `<span class="citystate">${el.city}, ${el.state}</span><span class="population">${el.population}</span>`;
          addList.style.display = "none";
        });
        suggestionsLi = document.querySelectorAll(".suggestions li");
      }
      getJsonData(getJsonDataToArr);

      search.onkeyup = function () {
        let reg = new RegExp(this.value, "gim");
        suggestionsLi[0].style.display = "none";
        suggestionsLi[1].style.display = "none";
        suggestionsLi.forEach((el) => {
          let citystate = el.querySelector(".citystate");
          if (citystate) {
            if (citystate.innerText.match(reg)) {
              el.style.display = "flex";
              let splitString = citystate.innerText
                .split(citystate.innerText.match(reg)[0])
                .join(`<span class="hl">${this.value}</span>`);
              citystate.innerHTML = splitString;
            } else {
              el.style.display = "none";
            }
          }
        });
      };
    </script>
  </body>
</html>

3. 리뷰

2-1 : 

fetch로 data 받아올때 ... 을 썼다.

... : 배열안에 요소가 있다면 요소만 추출하고 없다면 삭제한다.

cities 에 정규표현식을 이용하여 정규표현식에 만족한다면 그 단어를 filter로 뽑아냄

numberWithCommas 안에 있는 정규식 : 3번째 숫자마다 , 를 입력함. 구글링 해보면 바로 나온다.

displayMatches function에서 city와 state에 만족한다면 그 값에 클래스를 넣어주는 span을 HTML로 작성하여 넣어주고 그 값들을 li를 만들어 넣어준다. 이렇게 만들어진 HTML코드를 join으로 모든 배열을 하나의 Text형식으로 만들어준다.

이를 innerHTML 로 넣어주면 li태그를 받아들여 각각의 li태그로 나뉜다.

눌렀다 땠을때의 value값을 받기 위해 keydown이 아닌 keyup을 사용

값이 변했을 때도 적용하기 위해 change event추가

 

2-2 : 

데이터를 콜백으로 받아옴

data의 갯수만큼 forEach를 돌려 li를 생성하고 그 안에 내용 작성 후, 이를 ul에 appendChild로 넣어줌

입력하는 값의 value에 해당하면 display를 이용하여 none과 flex로 조절

정규식에 해당하는 값으로 split한 후 span과 classname을 포함한 태그로 join해서 바꿔줌

이를 innerHTML로 각각 넣어준다.

 

총 리뷰 : 

2-2 방식으로 코딩후 검색할 시 버벅거림과 렉이 걸렸음

각각 태그를 만들고 split join하는것 보다 모든 태그를 Text형식으로 만들고 이를 HTML태그로 받아들이는게 빠르다.

728x90
반응형

'개발 > html, css, js' 카테고리의 다른 글

[JS] 쿠키와 세션  (0) 2022.08.08
[30일 챌린지 Day-7] some,every,find,findIndex  (0) 2022.07.26
[30일 챌린지 Day-5] flex, classname 추가 활용  (0) 2022.07.25
[30일 챌린지 Day-4] 배열,객체 알고리즘  (0) 2022.07.25
[30일 챌린지 Day-3] input값 적용하기  (0) 2022.07.25
'개발/html, css, js' 카테고리의 다른 글
  • [JS] 쿠키와 세션
  • [30일 챌린지 Day-7] some,every,find,findIndex
  • [30일 챌린지 Day-5] flex, classname 추가 활용
  • [30일 챌린지 Day-4] 배열,객체 알고리즘
TeTedo.
TeTedo.
  • TeTedo.
    TeTedo 개발 일기
    TeTedo.
  • 전체
    오늘
    어제
    • 분류 전체보기 (319)
      • 개발 (274)
        • Article (4)
        • 정리 (21)
        • Spring Boot (17)
        • JPA (2)
        • JAVA (6)
        • Database (4)
        • 자료구조 (11)
        • 알고리즘 (32)
        • React (20)
        • Docker (10)
        • node.js (18)
        • Devops (11)
        • Linux (4)
        • TypeScript (3)
        • Go (10)
        • HyperLedger (4)
        • BlockChain (43)
        • html, css, js (48)
        • CS (3)
        • AWS (3)
      • 모아두고 나중에 쓰기 (3)
      • 팀프로젝트 (18)
        • SNS(키보드워리어) (9)
        • close_sea (9)
      • 개인프로젝트 (1)
        • Around Flavor (1)
        • CHAM (13)
        • ethFruitShop (5)
      • 독서 (0)
        • 스프링부트와 AWS로 혼자 구현하는 웹 서비스 (0)
  • 블로그 메뉴

    • 홈
    • 개발일기
    • CS
    • 실습
    • 코딩테스트
    • 웹
    • Go
    • node.js
    • 팀플
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    go
    node
    node.js
    30일 챌린지
    ERC721
    블록체인
    하이퍼레저
    도커
    CSS
    mysql
    html
    명령어
    js
    프로그래머스
    React
    30일챌린지
    go언어
    nodejs
    컨테이너
    erc20
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
TeTedo.
[30일 챌린지 Day-6] 검색, json 활용
상단으로

티스토리툴바