今天繼續來做JS30~!這篇其實花了我不少的時間,原因在於在專案中也幾個函式我並沒有接觸過,花了一些時間查資料,結果又打開了新的潘朵拉盒子~整個就沒完沒了~!
回到主題,這次的專案練習主要有幾個目標:
1.打造一個類似searchbar的功能,用來搜尋json檔案內的資料
2.根據鍵入的文字,直接在下方框顯示搜尋結果(有點類似autocomplete的功能)
3.highlight搜尋結果中符合條件的文字,例如鍵入bos 會做出類似Boston的效果
HTML
<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>
CSS
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; }
Javascript
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json'; const cities = [] const input_search = document.querySelector('.search') const suggestions = document.querySelector('.suggestions') fetch(endpoint) .then(response => response.json()) .then(json => cities.push(...json)); input_search.addEventListener('change', display) input_search.addEventListener('keyup', display) function numberWihCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') } function FindMacthes(wordToMatch, cities) { return cities.filter(item => { let re = new RegExp(wordToMatch, 'gi') return item.city.match(re) || item.state.match(re) }) } function display() { const MatchArray = FindMacthes(this.value, cities) let html = MatchArray.map(item => { const regrex = new RegExp(this.value, 'gi') const newName = item.city.replace(regrex, `<span class ='hl'>${this.value}</span>`) const newState = item.state.replace(regrex, `<span class ='hl'>${this.value}</span>`) return ` <li> <span class = 'name'>${newName} , ${newState}</span> <spna class = 'population'> ${numberWihCommas(item.population)}</span> </li> `; }).join(''); suggestions.innerHTML = html; console.log(MatchArray); }
學習重點
- 練習初次接觸的fetch功能,注意fetch首先會回傳一個promise,資料可用.json、.text、.blob方法讀取
- 由將數字加入千分位的函式(x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ‘,’)複習regrex positive lookahead & negative lookahead 以及\B的意義(找尋非邊界的位置)
- 利用map&join將陣列內的內容轉為字串存放在li的結構裡面(實用)
- 利用動態regrex配合css做出類似autocomplete的效果(一旦關鍵字match資料庫,在form內便新增對應的li)
最終成品

參考文章
正则表达式/\B(?=(\d{3})+(?!\d))/怎样给数字添加千分符的
RegExp 應用: lookahead , lookbehind