Skip to content

Commit 756d8ce

Browse files
committed
man some really really useful stuff in this one, from fetching data to working with it on the user end to redisplay it, so much to learn here take this one slow, mad real world here!
1 parent b650930 commit 756d8ce

1 file changed

Lines changed: 125 additions & 5 deletions

File tree

06 - Type Ahead/index-START.html

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,137 @@
66
<link rel="stylesheet" href="style.css">
77
</head>
88
<body>
9-
109
<form class="search-form">
1110
<input type="text" class="search" placeholder="City or State">
1211
<ul class="suggestions">
1312
<li>Filter for a city</li>
1413
<li>or a state</li>
1514
</ul>
1615
</form>
17-
<script>
18-
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
16+
<script>
17+
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
18+
// lets create an empty array to hold our cities
19+
const cities = [];
20+
21+
fetch(endpoint)
22+
.then(
23+
data => {
24+
/* if you check the log at this point you
25+
will see that its a Response and a 200 status
26+
looks good but beyond that its weird looking and where
27+
actually is our data? (this is why wes calls this var 'blob')
28+
because we dont know what type of data this is coming back yet:
29+
html, video, image, audio, document etc. we know that it IS json
30+
so the raw data needs to be converted TO json. if you look in the
31+
log under Response prototype you will see a json: json() method
32+
so if we call data.json() (wes uses blob) that will return another
33+
promise containing our data in json format
34+
*/
35+
data.json()
36+
/*
37+
ok cool so now how do we get our data into our cities[] array?
38+
since its a const we cant just assign cites = data, you could use let
39+
but if you want to keep your variable as const you can push the data
40+
items into the cities array
41+
.then(data => cities.push(data));
42+
if you do this then you are nesting your data and you'll be placing an array
43+
inside the cities array. (probably not what we want)
44+
notice that every time you push something to the cities array it adds a new
45+
item in the cities array. so the way that we can change this array into
46+
individual arguments is we _spread into it_ via the es6 spread operator!
47+
*/
48+
.then(data => cities.push(...data));
49+
});
50+
/* next when someone types into the text input we want to write
51+
a function (findMatches()) that takes this massive cites array and
52+
filters it down into a subset where you can then listen for it
53+
findMatches will define the wordToMatch and it will also take in our
54+
cities array as the functions data that its going to filter. from that
55+
we are going to return the cities array and call filter on it which
56+
will chisle it down
57+
*/
58+
const findMatches = (wordToMatch, cities) => {
59+
return cities.filter(place => {
60+
/*
61+
here we need to figure out if the city or state matches
62+
what was searched (our `wordToMatch`)
63+
we are going to need a regular expression here.
64+
we need to put a variable `wordToMatch`
65+
in a regular expression and then pass in any flags we want.
66+
`g` is for global - meaning its going to look thru the entire
67+
string for that specific one, `i` is insensitve meaning its case
68+
insensitive and will match on either uppercase or lowercase.
69+
then we call .match and pass in our regex and return if either
70+
a city or state from `wordToMatch` matches
71+
*/
72+
const regex = new RegExp(wordToMatch, 'gi');
73+
return place.city.match(regex) || place.state.match(regex);
74+
});
75+
};
76+
/*
77+
now we need to create a displayMatches function
78+
that is going to be called every time someone
79+
changes the value
80+
*/
81+
const searchInput = document.querySelector('.search');
82+
const suggestions = document.querySelector('.suggestions');
83+
// wes didnt explain this function just that it formats a string into
84+
// commented one and just grabbed it from the internet
85+
const numberWithCommas = (x) => {
86+
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
87+
};
1988

20-
</script>
21-
</body>
89+
const displayMatches = () => {
90+
// console.log('this value in displayMatches: ', searchInput.value);
91+
// console.log('this value in displayMatches: ', this.value);
92+
// note if you are not using an arrow function use this which refers
93+
// to the searchInput
94+
// so in here we are going to use findMatches:
95+
const matchArray = findMatches(searchInput.value, cities);
96+
// console.log('matchArray: ', matchArray);
97+
// when we map over each place the map method will return an
98+
// array, when we really want one string, so we can call a quick
99+
// .join on the end and that will turn it from an array with
100+
// multiple items, into one big string
101+
const html = matchArray.map(place => {
102+
// const regex = new RegExp(this.value, 'gi');
103+
// const cityName = place.city.replace(
104+
// regex,
105+
// `<span class="hl">${this.value}</span>`
106+
// );
107+
const regex = new RegExp(searchInput.value, 'gi');
108+
const cityName = place.city.replace(
109+
regex,
110+
`<span class="hl">${searchInput.value}</span>`
111+
);
112+
const stateName = place.state.replace(
113+
regex,
114+
`<span class="hl">${searchInput.value}</span>`
115+
);
116+
return `
117+
<li>
118+
<span class="name">${cityName}, ${stateName}</span>
119+
<span class="population">${numberWithCommas(place.population)}</span>
120+
</li>
121+
`;
122+
})
123+
.join('');
124+
suggestions.innerHTML = html;
125+
};
126+
127+
searchInput.addEventListener('change', displayMatches);
128+
// at this point we only listen for change which happens when
129+
// a user focuses off the input, not when they type something different
130+
// so lets add another listener and run displayMatches on keyup
131+
searchInput.addEventListener('keyup', displayMatches);
132+
/*
133+
couple last things we need to do here is to format the population
134+
value as well as highlighting the input value if it matches
135+
lets go back to our displayMatches map function and before that return lets
136+
create a regex that will match the city name and then we'll use
137+
that regex to replace the word that it matches with a span with
138+
a class of `hl` and the word that it matches
139+
*/
140+
</script>
141+
</body>
22142
</html>

0 commit comments

Comments
 (0)