-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
196 lines (163 loc) · 5.82 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/**
* Useful links for project:
* https://github.com/PokeAPI/sprites
* https://github.com/PokeAPI/pokeapi/issues/346
* https://pokeapi.co/
*/
'use strict';
import * as pokemonHandler from './modules/pokemonHandler.js';
/**
* Constants
*/
const ENDPOINT = 'https://pokeapi.co/api/v2/';
//So we can cache the results of the API call and not have to call it repeatedly for each search
const POKEMON_CACHE = {
allPokemon: [],
currentPokemon: {}
};
//DOM elements and templates
const MAIN_CONTENT_CONTAINER = document.querySelector('#mainContent');
const SEARCH_PAGE_TEMPLATE = document.querySelector('#searchPageTemplate');
const SEARCH_RESULT_TEMPLATE = document.querySelector('#searchResultTemplate');
const POKEMON_DETAILS_PAGE_TEMPLATE = document.querySelector('#pokemonDetailsPageTemplate');
/**
* Global variables
*/
let search = '';
//needs to be accessible globally
let searchResultsContainer;
document.addEventListener("DOMContentLoaded", function() {
initialise();
});
/**
* Initialises the page
* @returns {void}
*/
function initialise() {
//fill the cache with all the pokemon
fillCache();
//clone the search page template and add it to the DOM
setupPage();
}
/**
* Fills the cache with all pokemon
* @returns {void}
* @async
*/
async function fillCache() {
//fetch all pokemon
let response = await fetch(ENDPOINT + 'pokemon/?limit=3000&offset=0');
let responseJson = await response.json();
//fill cache
POKEMON_CACHE.allPokemon = responseJson.results;
}
/**
* Clones the search page template and adds it to the DOM
* Then sets the searchResultsContainer global variable
* @returns {void}
*/
function setupPage() {
const node = SEARCH_PAGE_TEMPLATE.content.cloneNode(true);
MAIN_CONTENT_CONTAINER.appendChild(node);
searchResultsContainer = document.querySelector('#searchResultsContainer');
//add event listener to search bar
const searchBar = document.querySelector('#searchbar');
searchBar.addEventListener('input', searchPokemon);
}
/**
* Clears the search results container
* @returns {void}
*/
function clearSearchResults() {
searchResultsContainer.innerHTML = '';
}
/**
* Filter the pokemon in the cache by search string
* @param {string} search
* @returns {Array}
*/
function getSearchResults(search) {
//search in cache for pokemon containing search string
//put the pokemon that start with search string first
const searchResults = POKEMON_CACHE.allPokemon.filter(pokemon => pokemon.name.includes(search));
const searchResultsStartsWith = searchResults.filter(pokemon => pokemon.name.startsWith(search));
const searchResultsContains = searchResults.filter(pokemon => !pokemon.name.startsWith(search));
//add pokemon that don't start with search string to the end of the array of pokemon that do
const combinedSearchResults = searchResultsStartsWith.concat(searchResultsContains);
return combinedSearchResults;
}
/**
* Clones the search result template, fills it with the pokemon data, sets up the event listeners and adds it to the DOM
* @param {object} pokemon
* @returns {void}
*/
function cloneSearchResultTemplate(pokemon) {
//clone the document fragment
const searchResultNode = SEARCH_RESULT_TEMPLATE.content.cloneNode(true);
//assign the button
const nodeButton = searchResultNode.querySelector('a');
//fill the template with the pokemon data
searchResultNode.querySelector('.pokemonName').innerText = pokemon.name;
searchResultNode.querySelector('.pokemonName').setAttribute('data-pokemon-name', pokemon.name);
nodeButton.addEventListener('click', displayPokemon);
searchResultsContainer.appendChild(searchResultNode);
}
/**
* Takes the input from the search bar and handles the search logic and updating the search results
* @param {InputEvent} inputEvent
* @returns {void}
*/
function searchPokemon(inputEvent) {
search = inputEvent.target.value;
if (search.length < 1) {
return;
}
clearSearchResults();
let searchResults = getSearchResults(search);
//fill search results container with search results
searchResults.forEach(pokemon => {
cloneSearchResultTemplate(pokemon);
});
}
/**
* Clears the page and reruns the setup for the search page
* @returns {void}
*/
function returnToSearch() {
clearPage();
setupPage();
}
/**
* Clears the main content container
* @returns {void}
*/
function clearPage() {
MAIN_CONTENT_CONTAINER.innerHTML = '';
}
/**
* Gets the current pokemons details and pass them to the pokemon handler to display them
* @param {clickEvent} clickEvent
* @returns {void}
*/
async function displayPokemon(clickEvent) {
//set the current pokemon in the cache
POKEMON_CACHE.currentPokemon.name = clickEvent.target.dataset.pokemonName;
//get the pokemon details from the API
const pokemonJSON = await pokemonHandler.getPokemon(POKEMON_CACHE.currentPokemon.name, ENDPOINT);
//clear the page and display the pokemon details
clearPage();
switchToPokemonDetailsPage(pokemonJSON);
}
/**
* Displays the current pokemon details page via the pokemon handler
* @param {object} pokemonJSON
* @returns {void}
*/
function switchToPokemonDetailsPage(pokemonJSON) {
//clone the document fragment
const pokemonDetailsPageNode = POKEMON_DETAILS_PAGE_TEMPLATE.content.cloneNode(true);
//fill the document fragment with the pokemon details and add it to the DOM
const filledNode = pokemonHandler.fillPokemonData(pokemonJSON, pokemonDetailsPageNode);
filledNode.querySelector('#backToSearchButton').addEventListener('click', returnToSearch);
MAIN_CONTENT_CONTAINER.appendChild(filledNode);
}