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태그로 받아들이는게 빠르다.
'개발 > 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 |