[JS30] Day06: Ajax Type Ahead
這一堂課要製作一個搜尋清單,清單有許多城市,會隨著我們的輸入進行篩選與標出關鍵字。
JavaScript
首先先透過fetch取得資料,一般的操作方式如下
fetch("http://example.com/movies.json")
.then((response) => response.json())
.then((data) => console.log(data));
這裡我們透過fetch取得城市資料,存入 cities 中
const endpoint =
"https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json";
const cities = [];
fetch(endpoint)
.then((res) => res.json())
.then((json) => cities.push(...json));
new RegExp可以建立 RegExp 物件,keywords 為我們在 input 輸入的文字,cities 為被搜尋的陣列
function findMatches(keywords, cities) {
const regex = new RegExp(keywords, "gi"); // global, insensitive
return cities.filter((place) => {
return place.city.match(regex) || place.state.match(regex);
});
}
regex 實驗網站 https://regexr.com/
我們要將搜尋到的陣列轉成 HTML 的字串,透過innerHTML塞進 suggestion 元素裡面。
numberWithCommas函式為每三個數字加上逗號
字串可以透過replace來取代給定的 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>${numberWithCommas(place.population)}</span>
</li>
`;
})
.join("");
suggestions.innerHTML = html;
}
透過 input 元素的change和keyup事件,來去呼叫displayMatches來呈現推薦列表
const searchInput = document.querySelector(".search");
const suggestions = document.querySelector(".suggestions");
searchInput.addEventListener("change", displayMatches);
searchInput.addEventListener("keyup", displayMatches);