View on GitHub

JS30

a bunch of vanilla JS practice projects based on JavaScript 30 by WesBos.

06-ajax-type-ahead

demo gif

Back to home page

User story

Notes

Get the data of places

The goal here is to get an array cities that contains every places.

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

const cities = [];

//fetch create a promise
fetch(endpoint)
 //converting a blob of data into JSON, which will return another promise
 .then(blob => blob.json())
 //push each of the data into array
 .then(data => cities.push(...data));

After some videos from TheCodingTrain, we learned that promises is an object, we use it to handle asynchronous things(avoid the “callback hell”), we use then to handle a fulfilled promise and catch when error occurs.

Search function

Now we have the cities with all the data we need, we want to compare it with user’s input to get the search result.

First, listen for an input event on the search bar, select the ul for displaying the search result.

const input_search = document.querySelector(".input_search");
const ul_result = document.querySelector(".ul_result");
input_search.addEventListener("input", displayMatches);

Then, create a function for returning the result, in other words, filter out non-matches from cities array.

//wordToMatch is the user input
function findMatches(wordToMatch, cities) {
 return cities.filter(place => {
  //if the city or state matches what was searched
  const regex = new RegExp(wordToMatch, "gi");
  return place.city.match(regex) || place.state.match(regex);
 });
}

Display the result on screen

What we want to display:

function displayMatches() {
 //check if the search bar is empty
 if (this.value.length == 0) {
  ul_result.innerHTML = `<li class="li_result">Filter for a city or state</li>`;
 } else {
  //find the matches
  const matchArray = findMatches(this.value, cities);
  //if matched
  if (matchArray.length > 0) {
   //replace the html inside <ul> with list item of result item
   const html = matchArray
    .map(place => {
     //highlight the search word in the result item
     const regex = new RegExp(this.value, "gi");
     const cityName = place.city.replace(regex, `<span class="span_highlight">${this.value}</span>`);
     const stateName = place.state.replace(regex, `<span class="span_highlight">${this.value}</span>`);
     //creating list item for each result item
     return `
    <li class="li_result">
     <span class="span_name">${cityName}, ${stateName}</span>
     <span class="span_population">${numberWithCommas(place.population)}</span>
    </li>
   `;
    })
    .join("");
   //replce the html
   ul_result.innerHTML = html;
  } else {
   //if not found
   ul_result.innerHTML = `<li class="li_result">Result not found</li>`;
  }
 }
}

A function for adding commas to the population number:

function numberWithCommas(x) {
 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}