From 8388831301110a1e956dd98722c9a4c4b8c70617 Mon Sep 17 00:00:00 2001 From: vista-man <524715@vistacollege.nl> Date: Tue, 25 Mar 2025 13:51:25 +0100 Subject: [PATCH] =?UTF-8?q?Increase=20cache=20duration=20to=2024=20hours?= =?UTF-8?q?=20and=20implement=20local=20storage=20caching=20for=20Pok?= =?UTF-8?q?=C3=A9mon=20data=20with=20lazy=20loading=20for=20images?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2/get-pokemon.php | 2 +- v2/pokemon.js | 99 +++++++++++++++++++++++++++++++--------------- 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/v2/get-pokemon.php b/v2/get-pokemon.php index ead884f..dbeb748 100644 --- a/v2/get-pokemon.php +++ b/v2/get-pokemon.php @@ -10,7 +10,7 @@ if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } -header("Cache-Control: max-age=3600"); // Cache for 1 hour +header("Cache-Control: max-age=86400"); // Cache for 24 hours if (isset($_GET['id'])) { $id = intval($_GET['id']); diff --git a/v2/pokemon.js b/v2/pokemon.js index 0633375..087d1df 100644 --- a/v2/pokemon.js +++ b/v2/pokemon.js @@ -1,4 +1,5 @@ const MAX_POKEMON = 151; +const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds const listWrapper = document.querySelector(".list-wrapper"); const searchInput = document.querySelector("#search-input"); const numberFilter = document.querySelector("#number"); @@ -7,23 +8,42 @@ const notFoundMessage = document.querySelector("#not-found-message"); let allPokemons = []; -fetch(`./get-pokemon.php`) - .then((response) => response.json()) - .then((data) => { - if (Array.isArray(data)) { - allPokemons = data; - cacheImages(allPokemons); - displayPokemons(allPokemons); - } else { - console.error("Unexpected response format:", data); - } - }); +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); + displayPokemons(allPokemons); + } else { + fetchPokemons(); + } +}); + +function fetchPokemons() { + fetch(`./get-pokemon.php`) + .then((response) => response.json()) + .then((data) => { + if (Array.isArray(data)) { + allPokemons = data; + localStorage.setItem("pokemons", JSON.stringify(allPokemons)); + localStorage.setItem("pokemons_timestamp", Date.now().toString()); + displayPokemons(allPokemons); + } else { + console.error("Unexpected response format:", data); + } + }) + .catch((error) => { + console.error("Error fetching Pokémon data:", error); + }); +} async function fetchPokemonDataBeforeRedirect(id) { try { - const pokemon = await fetch(`./get-pokemon.php?id=${id}`).then((res) => - res.json() - ); + const response = await fetch(`./get-pokemon.php?id=${id}`); + const text = await response.text(); + console.log(`Response for Pokémon ID ${id}:`, text); + const pokemon = JSON.parse(text); if (pokemon.error) { throw new Error(pokemon.error); @@ -36,27 +56,10 @@ async function fetchPokemonDataBeforeRedirect(id) { } } -function cacheImages(pokemons) { - pokemons.forEach((pokemon) => { - const img = new Image(); - img.src = pokemon.image_url; - img.onload = () => { - localStorage.setItem(`pokemon_image_${pokemon.id}`, pokemon.image_url); - }; - }); -} - -function getCachedImageUrl(pokemonId) { - return localStorage.getItem(`pokemon_image_${pokemonId}`); -} - function displayPokemons(pokemons) { listWrapper.innerHTML = ""; pokemons.forEach((pokemon) => { - const cachedImageUrl = getCachedImageUrl(pokemon.id); - const imageUrl = cachedImageUrl || pokemon.image_url; - const listItem = document.createElement("div"); listItem.className = "list-item"; listItem.innerHTML = ` @@ -64,7 +67,7 @@ function displayPokemons(pokemons) {
#${pokemon.id}
#${pokemon.name}
@@ -82,6 +85,38 @@ function displayPokemons(pokemons) { listWrapper.appendChild(listItem); }); + + lazyLoadImages(); +} + +function lazyLoadImages() { + 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) { + preloadImage(entry.target); + self.unobserve(entry.target); + } + }); + }, config); + + images.forEach(image => { + observer.observe(image); + }); +} + +function preloadImage(img) { + const src = img.getAttribute('data-src'); + if (!src) { + return; + } + img.src = src; } searchInput.addEventListener("keyup", handleSearch);