CodeNewbie Community 🌱

Cover image for Commit19 //#JavaScript30 - Day 6 [Type Ahead API]
Janet Webster
Janet Webster

Posted on

Commit19 //#JavaScript30 - Day 6 [Type Ahead API]

Photo of Type Ahead API


I am learning with Skillcrush. Please check them out and consider signing up if you're looking to break into tech! Receive $250 off your course by using the link above. Use the coupon code: TWIXMIXY
NOTE: this discount is for Break Into Tech + Get Hired package exclusively. It's the same program I am participating in!


Today's challenge comes from JavaScript30.

I have a migraine today, so I will try to get through today's challenge and explain everything that I'm learning. Do you experience severe headaches or migraines? I'd love to know what you've done or do to help alleviate them or ideally not bring them on to begin with. HMU in the comments!

JavaScript30 - Day 6

All the CSS and HTML are completed for this challenge, so we'll be jumping right into the JS.

We're creating a searchable database. The data is city/state with population information.

The information on the cities was already laid out for us in the script as well.

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

</script>
Enter fullscreen mode Exit fullscreen mode

Our first line of code will be writing an empty array to put our cities into.

const cities = [];
Enter fullscreen mode Exit fullscreen mode

Next we need to fetch our data.

fetch(endpoint)
  .then(blob => blob.json())
  .then(data => cities.push(...data));
Enter fullscreen mode Exit fullscreen mode

OK. So this immediately became confusing to me. We're using the Arrow Function, which is fine! BUT I'm just not really understanding .then or blob really.

I think I understand the cities.push(...data) is putting the endpoint data into the cities array, so it's now fetching the cities array. But that's really all I got from that so far.

Here's what I have so far...

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

const cities = [];

fetch(endpoint)
  .then(blob => blob.json())
  .then(data => cities.push(...data));

console.log(cities);
</script>
Enter fullscreen mode Exit fullscreen mode

And when I ran my cities console log it did come back with all of the endpoint data. So that's why I think I understand that aspect of it.

Now we are going to create functions that will call on the array so that when typing in the search bar, it will pull back the data we are requesting.

function findMatches(wordToMatch, cities) {
  return cities.filter(place => {
    // here we need to figure out if the city of state matches what was searched
    const regex = new RegExp(wordToMatch, 'gi');
    return place.city.match(regex) || place.state.match(regex)
  });
}
Enter fullscreen mode Exit fullscreen mode

This function covers a lot. So we are creating findMatches with the parameters being wordToMatch and our already created variable cities.

We return cities and of course we want to filter it, because we are looking to have it search (aka filter) on the wide array of cities listed in our json file.

The part where it gets tricky for me is the variable within the function, regex. I looked up RegExp and it means a regular expression relating to matching data, so that makes some sense. Then the parameters for it are the wordToMatch and "gi". gi means global and insensitive (not case sensitive).

Finally we return the data using the match with the parameter of the new regex variable. Returning place for both the city or the state.

Note I haven't been able to get this to validate in my console log, so I may have a bug in my code at this point. I'm going to keep pushing forward to see if I can get it working later.

Next we move on to the display function.

function displayMatches() {
  console.log(this.value);
}
Enter fullscreen mode Exit fullscreen mode

This did nothing in my console, but I also didn't see it do anything in the instructors console.

We are now moving on to pulling in classes from the HTML to begin manipulating what's seen on the screen.

const searchInput = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');
Enter fullscreen mode Exit fullscreen mode

Now that we have those tied in we can create event listeners.

searchInput.addEventListener('change', displayMatches);
Enter fullscreen mode Exit fullscreen mode

The data I am typing in the search bar is now displaying in the console log.

Console log search data

We added another event listener, so the search works for each letter entered.

searchInput.addEventListener('keyup', displayMatches);
Enter fullscreen mode Exit fullscreen mode

Console log keyup search data

Returning to the displayMatches function, we created a variable that pulls in the findMatches variable, so now when typing into the search bar, the console will pull back matching values.

displayMatches => findMatces

OK. The next step is all about the pulled back data and how it's displaying.

function displayMatches() {
  // console.log(this.value);
  const matchArray = findMatches(this.value, cities);
  // console.log(matchArray);
  const html = matchArray.map(place => {
    return `
    <li>
      <span class="name">${place.city}, ${place.state}</span>
      <span class="population">${place.population}</span>
    </li>
      `;
  }).join('');
  suggestions.innerHTML = html;
}
Enter fullscreen mode Exit fullscreen mode

We created a new variable html which we are mapping over the matchArray, so we can return some HTML which displays the city, state and population. Since it's an array we needed to add .join at the end. Don't fully understand that, but I'm sure I'll learn some day.

Then we tie in the suggestions to manipulate our HTML with the new html variable written.

Dispay matches

Nearly there, next we want to highlight the text typed into the search bar.

function displayMatches() {
  // console.log(this.value);
  const matchArray = findMatches(this.value, cities);
  // console.log(matchArray);
  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">${place.population}</span>
    </li>
      `;
  }).join('');
  suggestions.innerHTML = html;
}
Enter fullscreen mode Exit fullscreen mode

To do this we are using .replace, which isn't something I've utilized before. Using the weird regex thing again. What it's doing is basically finding the regex and replacing it with the new highlighter span we created.

Finally, we need to add in commas for the population. Basically the instructor just copies/pastes this one in.

function numberWithCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};
Enter fullscreen mode Exit fullscreen mode

Still needed to update the displayMatches function so the display of the population was properly updated.

<span class="population">${numberWithCommas(place.population)}</span>
Enter fullscreen mode Exit fullscreen mode

Commas

That's it! Of course I want to update the appearance a bit, but this is great if I ever want to build a search engine. I feel like I could definitely use this as a starting place.

Start your search here!

Top comments (0)