Anthony Chao

JS30 day6 Ajax Type Ahead

#Javascript

JS30 day06 - Ajax Type Ahead

作業內容

今天要做的是做出一個網頁,畫面上有一個輸入欄位,填入字之後就會依照這個字去找出美國哪個州或城市名字裡面有包含你輸入的字的內容 可以參考這份 CodePen

學到什麼

列點如下:

  • CSS

    1. 第一次碰到 outline 屬性,他跟 border 有什麼差呢?
    • border 會影響這個元素的大小(因為他在 box-model 裡),而 outline 不會
    • border 可以對上下左右有不同設定,但 outline 不行
    • outline 預設是 focus 才會出現,而 border 預設原本就是這個元素常態要出現的一部分
    1. 做出立體感:下面這個是我覺得很厲害的一小段 css,利用各種旋轉跟微妙的顏色作出立體效果(跪)
    .suggestions li:nth-child(even) {
      transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001);
      background: linear-gradient(to bottom,  #ffffff 0%,#EFEFEF 100%);
    }
  • JS

    1. 常數是陣列的話,不能 assign 值給他,但是可以 push,如果要用 assign 的話要改用 let
    const arr = []
    arr = [1, 2, 3]
    // 錯誤
    arr.push([1, 2, 3])
    // [1, 2, 3]
    1. fetch 是一個發送 request 的方法,除了最簡單的 fetch(網址) 之外,還可以指定 method / header 等等 fetch 拿到的東西是帶有 response 的 promise 物件,使用 then 將回傳值傳遞下去 他本身附有一些屬性跟方法,最常用的應該是 .json() 方法 參考資料:https://www.oxxostudio.tw/articles/201908/js-fetch.html

    2. JS 的 match() 方法裡面放的是常規表示法 ex.

    var regexp = /[A-E]/gi;
    var matches_array = str.match(regexp);

    如果傳進去一個非正規的表達式的物件obj,就會視為傳入new RegExp(obj)

    1. JS 的常規表示物件 RegExp,用法可以參考下面 參考資料: http://syunguo.blogspot.com/2013/04/jsregular-expressions.html https://pjchender.github.io/2017/09/26/js-%E6%AD%A3%E5%89%87%E8%A1%A8%E9%81%94%E5%BC%8F-regular-expression-regex/

    2. 箭頭函式跟一般的 function 裡面的 this 會不同 https://pjchender.blogspot.com/2017/01/es6-arrow-function.html

總結

我怎麼覺得今天的難度一下提高了,一次多了很多比較不熟的概念,可能是第一次接觸 JS 的 Regex 又同時碰到更不熟的 promise 吧XD 但寫完之後覺得如果靠自己最寫不出來的應該還是CSS… 那個立體感好厲害R!

參考資料: https://github.com/wesbos/JavaScript30

code 內容: 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;
}

JS:

const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';

let cities = [];

const prom = fetch(endpoint)
.then(function(response){
  return response.json();
}).then(function(data){
  return cities.push(...data);
});

function findMatches(wordToMatch, cities){
  return cities.filter(function(place){
    const regex = new RegExp(wordToMatch, 'gi');
    return place.city.match(regex) || place.state.match(regex)
  });
};

const searchInput = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');

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>${place.population}</span>
      </li>
    `;
  }).join('');
  suggestions.innerHTML = html;
};

searchInput.addEventListener('change', displayMatches);
searchInput.addEventListener('keyup', displayMatches);