Can anyone tell me why I'm unable to detect the load event on this image element and set the loading GIF to display: none? I'd like to set the div with the loader class to display: none when the first image loads after the Add Image button is clicked. Right now it only sets the style after I click the Add Doggo button twice.
Here's the code:
HTML:
<title>image loader</title>
</head>
<body>
<h1>Dog Images</h1>
<button class="add-doggo">Add Image</button>
<div class="doggos">
<div class="loader"><img src="src/Preloader.gif" /></div>
</div>
<script src="src/doggos.js"></script>
</body>
CSS:
.loader {
display: none;
}
JavaScript:
const DOG_URL = 'https://dog.ceo/api/breeds/image/random';
const doggos = document.querySelector('.doggos');
let loader = document.querySelector('.loader');
let dogImage, isLoaded;
function addNewDoggo() {
const promise = fetch(DOG_URL);
promise
.then(function (response) {
const processingPromise = response.json(); //This line of code parses the API response into a usuable js object
return processingPromise; //this code returns a new promise and this process is called | PROCESS-CHAINING
})
.then(function (processedResponse) {
const img = document.createElement('img');
img.classList.add('dog-image');
img.src = processedResponse.message;
img.alt = 'Cute doggo';
doggos.appendChild(img);
});
}
document.querySelector('.add-doggo').addEventListener('click', () => {
dogImage = document.querySelector('.dog-image');
isLoaded = dogImage?.complete && dogImage?.naturalHeight !== 0;
if (!isLoaded) {
loader.style.display = 'block';
console.log(true);
} else if (isLoaded) {
loader.style.display = 'none';
console.log('IMAGE LOADED');
}
return addNewDoggo();
});
// Adding event listener on the image element itself to detect if it's loaded
document.querySelector('.dog-image').addEventListener('load', () => {
console.log('DOG IMAGE LOADED');
isLoaded = dogImage?.complete && dogImage?.naturalHeight !== 0;
if (isLoaded) {
loader.style.display = 'none';
}
});
Here, as mentioned in a comment, you can clearly see that the first thing I do with the newly created image element is to give it an event handler for the load event. That's really all there is to it AFAIK.
"use strict";
function byId(id){return document.getElementById(id)}
function qsa(sel,parent=document){return parent.querySelectorAll(sel)}
function newEl(tag){return document.createElement(tag)}
window.addEventListener('load', onLoaded, false);
function onLoaded(evt)
{
qsa('button')[0].addEventListener('click', addNewDog, false);
}
const dogUrl = "https://dog.ceo/api/breeds/image/random";
function addNewDog()
{
qsa('.loader')[0].classList.remove('hidden');
fetch(dogUrl)
.then( response => response.json() )
.then( jsObj => {
let img = newEl('img');
img.addEventListener('load', onUserImgLoaded, false);
img.classList.add('dog-image');
img.alt = 'cute dog';
img.src = jsObj.message;
qsa('.doggos')[0].appendChild(img);
}
);
}
function onUserImgLoaded(evt)
{
qsa('.loader')[0].classList.add('hidden');
}
.hidden
{
display: none;
}
.loader img
{
max-width: 128px;
}
<h1>Dog Images</h1>
<button class="add-doggo">Add Image</button>
<div class="doggos">
<div class="loader hidden"><img src="https://flevix.com/wp-content/uploads/2020/01/Bounce-Bar-Preloader-1.gif" /></div>
</div>