iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 6
1
Modern Web

一直想著要做,卻懶得做的JS30系列系列 第 6

JS30-Day6

來到了第一個禮拜六,聽說假日最容易中斷,真的是差一點啊... 這次要做的是在input打上關鍵字,會顯示出帶有關鍵字的選項

Day6

一樣先上Demo,畫面部分比較簡單,就先做一個input,以及ul搭配li,來放之後會出現的搜尋結果
html:

<input type="text" class="search" placeholder="City or State">
    <ul class="suggestions">
      <li>Filter for a city</li>
      <li>or a state</li>
    </ul>

css
css:比較特別的地方是利用transform屬性做了一點折疊效果

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;
}

js:js部分先使用fetch去取得資料來源,並且轉換為物件後,將資料丟入我們宣告的陣列,並利用array的一些methods搭配正則表達式去篩選我們的資料,之後將資料整理成li元素,再丟到html當中

//取得json資料的網址
    const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
    //宣告一個陣列儲存資料
    const cities = [];
    //使用fetch取得資料,要注意瀏覽器支援程度
    fetch(endpoint)
      .then(blob => blob.json())
      //使用es6 spread語法將資料丟到陣列裡
      .then(data => cities.push(...data));
    //函式帶有兩個參數,一個是使用者輸入的文字,另一個是取回丟到陣列裡的資料  
    function findMatches(wordToMatch, cities) {
      //將資料用filter語法去篩選
      return cities.filter(place => {
        // here we need to figure out if the city or state matches what was searched
        //使用正則表達式,g表示找到所有匹配,而不是找到第一個就停,i表示忽略大小寫
        const regex = new RegExp(wordToMatch, 'gi');
        //有符合的話回傳資料的city屬性的值跟state屬性的值
        return place.city.match(regex) || place.state.match(regex)
      });
    }
    //函式作用為將數字轉為帶有逗點的數字
    function numberWithCommas(x) {
      return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }
    //將符合的結果組成li並顯示在網頁上
    function displayMatches() {
      //呼叫findMatches函式,這邊的this會指向input,因為監聽事件綁定在他身上
      const matchArray = findMatches(this.value, cities);
      //將回傳結果逐一組成li並塞到html中
      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>
    `;
        //map回傳值為一個陣列,用join將陣列每個值組成字串
      }).join('');
      suggestions.innerHTML = html;
    }
    //選取元素
    const searchInput = document.querySelector('.search');
    const suggestions = document.querySelector('.suggestions');
    //監聽change跟keyup事件
    searchInput.addEventListener('change', displayMatches);
    searchInput.addEventListener('keyup', displayMatches);

以上就是第六天內容!


上一篇
JS30-Day5
下一篇
JS30-Day7
系列文
一直想著要做,卻懶得做的JS30系列13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言