From d5a242e7ea7a5e280f55ec239451ee124ed88e57 Mon Sep 17 00:00:00 2001 From: vista-man <524715@vistacollege.nl> Date: Thu, 27 Mar 2025 09:08:41 +0100 Subject: [PATCH] Improve search functionality by encapsulating event listeners in an IIFE and enhancing visibility toggle for the search close icon --- v2/index.html | 2 + v2/pokemon.js | 476 +++++++++++++++++++++++++------------------------- v2/search.js | 62 +++---- 3 files changed, 273 insertions(+), 267 deletions(-) diff --git a/v2/index.html b/v2/index.html index dd9822e..476e9ca 100644 --- a/v2/index.html +++ b/v2/index.html @@ -5,6 +5,8 @@ Pokedex + + diff --git a/v2/pokemon.js b/v2/pokemon.js index 2a81792..db8a7bd 100644 --- a/v2/pokemon.js +++ b/v2/pokemon.js @@ -1,250 +1,252 @@ -const MAX_POKEMON = 1050; -const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds -const listWrapper = document.querySelector(".list-wrapper"); -const searchInput = document.querySelector("#search-input"); -const numberAscFilter = document.querySelector("#number-asc"); -const numberDescFilter = document.querySelector("#number-desc"); -const nameAscFilter = document.querySelector("#name-asc"); -const nameDescFilter = document.querySelector("#name-desc"); -const notFoundMessage = document.querySelector("#not-found-message"); -const competitorsWrapper = document.querySelector("#competitors-wrapper"); +(() => { + const MAX_POKEMON = 1050; + const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds + const listWrapper = document.querySelector(".list-wrapper"); + const searchInput = document.querySelector("#search-input"); + const numberAscFilter = document.querySelector("#number-asc"); + const numberDescFilter = document.querySelector("#number-desc"); + const nameAscFilter = document.querySelector("#name-asc"); + const nameDescFilter = document.querySelector("#name-desc"); + const notFoundMessage = document.querySelector("#not-found-message"); + const competitorsWrapper = document.querySelector("#competitors-wrapper"); -let allPokemons = []; -let filteredPokemons = []; + let allPokemons = []; + let filteredPokemons = []; -document.addEventListener("DOMContentLoaded", () => { - const cachedData = localStorage.getItem("pokemons"); - const cacheTimestamp = localStorage.getItem("pokemons_timestamp"); + document.addEventListener("DOMContentLoaded", () => { + const cachedData = localStorage.getItem("pokemons"); + const cacheTimestamp = localStorage.getItem("pokemons_timestamp"); - if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp) < CACHE_DURATION) { - allPokemons = JSON.parse(cachedData); - console.log("Loaded Pokémon data from cache:", allPokemons); + if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp) < CACHE_DURATION) { + allPokemons = JSON.parse(cachedData); + console.log("Loaded Pokémon data from cache:", allPokemons); + filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); + displayPokemons(filteredPokemons); + fetchCompetitors(); + } else { + fetchPokemons(); + } + }); + + function fetchPokemons() { + console.log("Fetching Pokémon data from server..."); + fetch(`./get-pokemon.php`) + .then((response) => response.text()) + .then((text) => { + console.log("Server response:", text); + try { + const data = JSON.parse(text); + if (Array.isArray(data)) { + allPokemons = data; + localStorage.setItem("pokemons", JSON.stringify(allPokemons)); + localStorage.setItem("pokemons_timestamp", Date.now().toString()); + console.log("Fetched and cached Pokémon data:", allPokemons); + filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); + displayPokemons(filteredPokemons); + fetchCompetitors(); + } else { + console.error("Unexpected response format:", data); + } + } catch (error) { + console.error("Error parsing JSON:", error); + } + }) + .catch((error) => { + console.error("Error fetching Pokémon data:", error); + }); + } + + async function fetchPokemonDataBeforeRedirect(id) { + try { + console.log(`Fetching data for Pokémon ID ${id} before redirect...`); + const response = await fetch(`./get-pokemon.php?id=${id}`); + const text = await response.text(); + console.log(`Response for Pokémon ID ${id}:`, text); + if (!text) { + throw new Error("Empty response from server"); + } + const pokemon = JSON.parse(text); + + if (pokemon.error) { + throw new Error(pokemon.error); + } + + return true; + } catch (error) { + console.error(`Failed to fetch Pokémon data before redirect for ID ${id}:`, error); + return false; + } + } + + function displayPokemons(pokemons) { + console.log("Displaying Pokémon data:", pokemons); + listWrapper.innerHTML = ""; + + pokemons.forEach((pokemon) => { + const listItem = document.createElement("div"); + listItem.className = "list-item"; + listItem.innerHTML = ` +
+

#${pokemon.id}

+
+
+ ${pokemon.name} +
+
+

${pokemon.name}

+
+ `; + + listItem.addEventListener("click", async () => { + const success = await fetchPokemonDataBeforeRedirect(pokemon.id); + if (success) { + window.location.href = `./detail.html?id=${pokemon.id}`; + } else { + console.error(`Failed to fetch data for Pokémon ID: ${pokemon.id}`); + } + }); + + listWrapper.appendChild(listItem); + }); + + lazyLoadImages(); + } + + function lazyLoadImages() { + console.log("Initializing lazy loading for images..."); + const images = document.querySelectorAll('.img-wrap img[data-src]'); + const config = { + root: null, + rootMargin: '0px', + threshold: 0.1 + }; + + let observer = new IntersectionObserver((entries, self) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + preloadLowResImage(entry.target); + self.unobserve(entry.target); + } + }); + }, config); + + images.forEach(image => { + observer.observe(image); + }); + } + + function preloadLowResImage(img) { + const srcLow = img.getAttribute('data-src-low'); + if (!srcLow) { + return; + } + console.log("Preloading low-resolution image:", srcLow); + img.src = srcLow; + preloadHighResImage(img); + } + + function preloadHighResImage(img) { + const src = img.getAttribute('data-src'); + if (!src) { + return; + } + const highResImg = new Image(); + highResImg.src = src; + highResImg.onload = () => { + console.log("Preloading high-resolution image:", src); + setTimeout(() => { + img.src = src; + }, 2000); // Wait for 2 seconds before switching to high-resolution image + }; + } + + searchInput.addEventListener("keyup", handleSearch); + numberAscFilter.addEventListener("change", handleSort); + numberDescFilter.addEventListener("change", handleSort); + nameAscFilter.addEventListener("change", handleSort); + nameDescFilter.addEventListener("change", handleSort); + + function handleSearch() { + const searchTerm = searchInput.value.toLowerCase(); + console.log("Handling search with term:", searchTerm); + + filteredPokemons = allPokemons.filter((pokemon) => { + const pokemonID = pokemon.id.toString(); + const pokemonName = pokemon.name.toLowerCase(); + return (pokemonID.startsWith(searchTerm) || pokemonName.startsWith(searchTerm)) && !pokemon.deleted; + }); + + displayPokemons(filteredPokemons); + + if (filteredPokemons.length === 0) { + notFoundMessage.style.display = "block"; + } else { + notFoundMessage.style.display = "none"; + } + } + + function handleSort() { + if (numberAscFilter.checked) { + filteredPokemons.sort((a, b) => a.id - b.id); + } else if (numberDescFilter.checked) { + filteredPokemons.sort((a, b) => b.id - a.id); + } else if (nameAscFilter.checked) { + filteredPokemons.sort((a, b) => a.name.localeCompare(b.name)); + } else if (nameDescFilter.checked) { + filteredPokemons.sort((a, b) => b.name.localeCompare(a.name)); + } + + displayPokemons(filteredPokemons); + } + + const closeButton = document.querySelector(".search-close-icon"); + closeButton.addEventListener("click", clearSearch); + + function clearSearch() { + console.log("Clearing search input and displaying all Pokémon..."); + searchInput.value = ""; filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); displayPokemons(filteredPokemons); - fetchCompetitors(); - } else { - fetchPokemons(); - } -}); - -function fetchPokemons() { - console.log("Fetching Pokémon data from server..."); - fetch(`./get-pokemon.php`) - .then((response) => response.text()) - .then((text) => { - console.log("Server response:", text); - try { - const data = JSON.parse(text); - if (Array.isArray(data)) { - allPokemons = data; - localStorage.setItem("pokemons", JSON.stringify(allPokemons)); - localStorage.setItem("pokemons_timestamp", Date.now().toString()); - console.log("Fetched and cached Pokémon data:", allPokemons); - filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); - displayPokemons(filteredPokemons); - fetchCompetitors(); - } else { - console.error("Unexpected response format:", data); - } - } catch (error) { - console.error("Error parsing JSON:", error); - } - }) - .catch((error) => { - console.error("Error fetching Pokémon data:", error); - }); -} - -async function fetchPokemonDataBeforeRedirect(id) { - try { - console.log(`Fetching data for Pokémon ID ${id} before redirect...`); - const response = await fetch(`./get-pokemon.php?id=${id}`); - const text = await response.text(); - console.log(`Response for Pokémon ID ${id}:`, text); - if (!text) { - throw new Error("Empty response from server"); - } - const pokemon = JSON.parse(text); - - if (pokemon.error) { - throw new Error(pokemon.error); - } - - return true; - } catch (error) { - console.error(`Failed to fetch Pokémon data before redirect for ID ${id}:`, error); - return false; - } -} - -function displayPokemons(pokemons) { - console.log("Displaying Pokémon data:", pokemons); - listWrapper.innerHTML = ""; - - pokemons.forEach((pokemon) => { - const listItem = document.createElement("div"); - listItem.className = "list-item"; - listItem.innerHTML = ` -
-

#${pokemon.id}

-
-
- ${pokemon.name} -
-
-

${pokemon.name}

-
- `; - - listItem.addEventListener("click", async () => { - const success = await fetchPokemonDataBeforeRedirect(pokemon.id); - if (success) { - window.location.href = `./detail.html?id=${pokemon.id}`; - } else { - console.error(`Failed to fetch data for Pokémon ID: ${pokemon.id}`); - } - }); - - listWrapper.appendChild(listItem); - }); - - lazyLoadImages(); -} - -function lazyLoadImages() { - console.log("Initializing lazy loading for images..."); - const images = document.querySelectorAll('.img-wrap img[data-src]'); - const config = { - root: null, - rootMargin: '0px', - threshold: 0.1 - }; - - let observer = new IntersectionObserver((entries, self) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - preloadLowResImage(entry.target); - self.unobserve(entry.target); - } - }); - }, config); - - images.forEach(image => { - observer.observe(image); - }); -} - -function preloadLowResImage(img) { - const srcLow = img.getAttribute('data-src-low'); - if (!srcLow) { - return; - } - console.log("Preloading low-resolution image:", srcLow); - img.src = srcLow; - preloadHighResImage(img); -} - -function preloadHighResImage(img) { - const src = img.getAttribute('data-src'); - if (!src) { - return; - } - const highResImg = new Image(); - highResImg.src = src; - highResImg.onload = () => { - console.log("Preloading high-resolution image:", src); - setTimeout(() => { - img.src = src; - }, 2000); // Wait for 2 seconds before switching to high-resolution image - }; -} - -searchInput.addEventListener("keyup", handleSearch); -numberAscFilter.addEventListener("change", handleSort); -numberDescFilter.addEventListener("change", handleSort); -nameAscFilter.addEventListener("change", handleSort); -nameDescFilter.addEventListener("change", handleSort); - -function handleSearch() { - const searchTerm = searchInput.value.toLowerCase(); - console.log("Handling search with term:", searchTerm); - - filteredPokemons = allPokemons.filter((pokemon) => { - const pokemonID = pokemon.id.toString(); - const pokemonName = pokemon.name.toLowerCase(); - return (pokemonID.startsWith(searchTerm) || pokemonName.startsWith(searchTerm)) && !pokemon.deleted; - }); - - displayPokemons(filteredPokemons); - - if (filteredPokemons.length === 0) { - notFoundMessage.style.display = "block"; - } else { notFoundMessage.style.display = "none"; } -} -function handleSort() { - if (numberAscFilter.checked) { - filteredPokemons.sort((a, b) => a.id - b.id); - } else if (numberDescFilter.checked) { - filteredPokemons.sort((a, b) => b.id - a.id); - } else if (nameAscFilter.checked) { - filteredPokemons.sort((a, b) => a.name.localeCompare(b.name)); - } else if (nameDescFilter.checked) { - filteredPokemons.sort((a, b) => b.name.localeCompare(a.name)); + function fetchCompetitors() { + console.log("Fetching competitors data from server..."); + fetch(`./get-competitors.php`) + .then((response) => response.text()) + .then((text) => { + console.log("Competitors data:", text); + try { + const data = JSON.parse(text); + displayCompetitors(data); + } catch (error) { + console.error("Error parsing JSON:", error); + } + }) + .catch((error) => { + console.error("Error fetching competitors data:", error); + }); } - displayPokemons(filteredPokemons); -} + function displayCompetitors(competitors) { + competitorsWrapper.innerHTML = ""; -const closeButton = document.querySelector(".search-close-icon"); -closeButton.addEventListener("click", clearSearch); + competitors.forEach((competitor) => { + const listItem = document.createElement("div"); + listItem.className = "list-item"; + listItem.innerHTML = ` +
+

#${competitor.id}

+
+
+

${competitor.name}

+
+
+

Pokémon: ${competitor.pokemon_count}

+
+ `; -function clearSearch() { - console.log("Clearing search input and displaying all Pokémon..."); - searchInput.value = ""; - filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); - displayPokemons(filteredPokemons); - notFoundMessage.style.display = "none"; -} - -function fetchCompetitors() { - console.log("Fetching competitors data from server..."); - fetch(`./get-competitors.php`) - .then((response) => response.text()) - .then((text) => { - console.log("Competitors data:", text); - try { - const data = JSON.parse(text); - displayCompetitors(data); - } catch (error) { - console.error("Error parsing JSON:", error); - } - }) - .catch((error) => { - console.error("Error fetching competitors data:", error); + competitorsWrapper.appendChild(listItem); }); -} - -function displayCompetitors(competitors) { - competitorsWrapper.innerHTML = ""; - - competitors.forEach((competitor) => { - const listItem = document.createElement("div"); - listItem.className = "list-item"; - listItem.innerHTML = ` -
-

#${competitor.id}

-
-
-

${competitor.name}

-
-
-

Pokémon: ${competitor.pokemon_count}

-
- `; - - competitorsWrapper.appendChild(listItem); - }); -} + } +})(); diff --git a/v2/search.js b/v2/search.js index 2b98c48..6eae27b 100644 --- a/v2/search.js +++ b/v2/search.js @@ -1,38 +1,40 @@ -const inputElement = document.querySelector("#search-input"); -const searchIcon = document.querySelector("#search-close-icon"); -const sortWrapper = document.querySelector(".sort-wrapper"); +(() => { + const inputElement = document.querySelector("#search-input"); + const searchIcon = document.querySelector("#search-close-icon"); + const sortWrapper = document.querySelector(".sort-wrapper"); -inputElement.addEventListener("input", () => { - handleInputChange(inputElement); -}); -searchIcon.addEventListener("click", handleSearchCloseOnClick); -sortWrapper.addEventListener("click", handleSortIconOnClick); + inputElement.addEventListener("input", () => { + handleInputChange(inputElement); + }); + searchIcon.addEventListener("click", handleSearchCloseOnClick); + sortWrapper.addEventListener("click", handleSortIconOnClick); -function handleInputChange(inputElement) { - const inputValue = inputElement.value; + function handleInputChange(inputElement) { + const inputValue = inputElement.value; - if (inputValue !== "") { - document - .querySelector("#search-close-icon") - .classList.add("search-close-icon-visible"); - } else { + if (inputValue !== "") { + document + .querySelector("#search-close-icon") + .classList.add("search-close-icon-visible"); + } else { + document + .querySelector("#search-close-icon") + .classList.remove("search-close-icon-visible"); + } + } + + function handleSearchCloseOnClick() { + document.querySelector("#search-input").value = ""; document .querySelector("#search-close-icon") .classList.remove("search-close-icon-visible"); + clearSearch(); } -} -function handleSearchCloseOnClick() { - document.querySelector("#search-input").value = ""; - document - .querySelector("#search-close-icon") - .classList.remove("search-close-icon-visible"); - clearSearch(); -} - -function handleSortIconOnClick() { - document - .querySelector(".filter-wrapper") - .classList.toggle("filter-wrapper-open"); - document.querySelector("body").classList.toggle("filter-wrapper-overlay"); -} + function handleSortIconOnClick() { + document + .querySelector(".filter-wrapper") + .classList.toggle("filter-wrapper-open"); + document.querySelector("body").classList.toggle("filter-wrapper-overlay"); + } +})();