글 작성자: 택시 운전사
반응형

🤳 Day6 - JavaScript로 정규표현식을 이용한 검색창 구현하기

JavaScript 30의 여섯 번째 프로젝트는 정규표현식을 이용하여 검색창을 구현하는 프로젝트입니다.

😃 HTML 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Type Ahead 👀</title>
    <link rel="stylesheet" href="main.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 src="main.js"></script>
  </body>
</html>
 
cs


😃 CSS 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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;
}
 
cs

CSS는 원 코드가 이뻐서 그대로 나뒀습니다. transform과 linear-gradient를 이용하여 입체감을 살렸습니다.

😃 JavaScript 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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));
 
findMatches = (wordToMatch, cities) =>
  cities.filter(place => {
    // 이 곳에서 검색어와 매치 되는 지를 확인해야 합니다
    const regex = new RegExp(wordToMatch, "gi");
    return place.city.match(regex) || place.state.match(regex);
  });
 
numberWithCommas = x => {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
 
displayMatches = e => {
  const word = e.target.value;
  const matchArray = findMatches(word, cities);
  const html = matchArray
    .map(place => {
      const regex = new RegExp(word, "gi");
      const cityName = place.city.replace(
        regex,
        `<span class="hl">${word}</span>`
      );
      const stateName = place.state.replace(
        regex,
        `<span class="hl">${word}</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);
 
cs

우선 기존에 있는 apiendpoint를 이용하여 데이터를 cities에 저장합니다.


그 뒤에 findMatches라는 cities 배열에서 특정 단어를 찾는 함수를 구현합니다. 여기서 new RegExp(wordToMatch, "gi")를 이용해 전체에서 wordToMatch와 비교하여 대소문자 구분없이 같은 단어가 있는 곳을 찾는 정규 표현식을 만들고, cities의 각 placecitystate에 매치되는 부분이 있는 지 확인합니다.


다음은 검색창에서 데이터를 가져오는 코드를 구현합니다. search 클래스에 해당하는 inputsearchInput이라 하고 changekeyup의 이벤트에 실제 불러올 데이터를 가져오는 displayMatches를 추가합니다.


displayMatches는 우선 앞에서 구현한 findMatches를 이용해 추천 검색어를 가져옵니다. 그리고 해당 검색어가 추천 검색어의 어느 부분과 같은 지 보여주기 위해 replace를 이용하여 매치되는 단어를 하이라이트 태그로 감싼 단어로 바꿔줍니다. 마지막으로 하이라이트 된 단어들을 포함한 전체 추천 검색어에 해당하는 html 태그를 반환해줍니다.


링크


반응형