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.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.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 = `
+
+
+
+
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 = `
-
-
-
-
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");
+ }
+})();