I'm trying to fadeout message containers after a few seconds. Usually there's only one, and that works fine, but when there are 2 or more, only the last one seems to get processed.
Code:
function fadeOut(elementToFade) {
var element = document.getElementById(elementToFade);
console.log(`fo element = ${element}, ${element.id}`)
element.style.opacity = (parseFloat(element.style.opacity) - 0.1).toString();
if (parseFloat(element.style.opacity) <= 0.0) {
element.style.display = "none";
} else {
setTimeout("fadeOut(\"" + elementToFade + "\")", 150);
// setTimeout("fadeOut(\"" + element.id + "\")", 150);
}
};
var message_elements_nodelist = document.querySelectorAll("div[id^='message_container']");
var pauseBeforeFadeout = 5000;
for (var i = 0; i < message_elements_nodelist.length; i++) {
var el = document.getElementById(message_elements_nodelist[i].id)
console.log(`element = ${el}, ${el.id}`)
setTimeout(function () {
el.style.opacity = "1.0";
fadeOut(el.id);
}, pauseBeforeFadeout);
};
The console logging shows:
element = [object HTMLDivElement], message_container-0
element = [object HTMLDivElement], message_container-1
2fo element = [object HTMLDivElement], message_container-1
10fo element = [object HTMLDivElement], message_container-1
So the code finds both elements, but then the timeout only seems to get applied to the last one in the list and I cannot work out why this would be.
Edit
Putting in a Promise
now looks like this:
const message_elements_nodelist = document.querySelectorAll("div[id^='message_container']")
const pauseBeforeFadeout = 5000
async function fadeOut(elementToFade) {
const element = document.getElementById(elementToFade);
console.log(`fo element = ${element}, ${element.id}`)
element.style.opacity = (parseFloat(element.style.opacity) - 0.1).toString()
if (parseFloat(element.style.opacity) <= 0.0) {
element.style.display = "none"
} else {
setTimeout("fadeOut(\"" + elementToFade + "\")", 150)
}
}
async function fadeOutAllMessages() {
for (let i = 0; i < message_elements_nodelist.length; i++) {
const el = document.getElementById(message_elements_nodelist[i].id)
console.log(`element = ${el}, ${el.id}`)
await new Promise(resolve => setTimeout(() => {
el.style.opacity = "1.0"
fadeOut(el.id)
}, pauseBeforeFadeout))
}
}
fadeOutAllMessages()
Unfortunately, now the first message is cleared, but the second isn't, and the console.log
messages look like this:
element = [object HTMLDivElement], message_container-0
fo element = [object HTMLDivElement], message_container-0
9 fo element = [object HTMLDivElement], message_container-0
Those last 9 messsages appear 5 seconds after the first, so one await
is working, then it seems to bundle them all through with only the 1st loop instance.