Rules:
<progress> element.Problem:
If you click rapidly it will only animate the last progress bar. And animations should happen one by one until completion.
Question:
When clicking rapidly, why are the animations out of order?
HTML:
<div class="container">
<div class="add-progress-container">
<input class="input-seconds" type="number" min="1" max="10" value="1">
<button class="add-progress">Add progress</button>
</div>
<div class="progress-container"></div>
</div>
JS:
const container = document.querySelector('.progress-container');
const inputSeconds = document.querySelector('.input-seconds');
const addBtn = document.querySelector('.add-progress');
let animating = false;
function animateProgress(duration, el) {
const intervalId = setInterval(() => {
if(el.value >= el.max) {
animating = false;
window.clearInterval(intervalId);
console.log('finished');
checkQueue();
return;
}
el.value += el.max/duration;
}, 1000);
}
function getSeconds() {
return parseInt(inputSeconds.value, 10);
}
let progressCount = 0;
function createProgress() {
const template = `<progress data-progress="${progressCount}" value="0" max="100"></progress>`;
container.innerHTML += template;
const el = document.querySelector(`[data-progress="${progressCount}"]`);
progressCount++;
return el;
}
let queue = [];
function addProgress() {
const el = createProgress()
queue.push(el);
checkQueue();
}
function checkQueue() {
if(queue.length && !animating) {
animating = true;
animateProgress(getSeconds(), queue.shift());
}
}
addBtn.addEventListener('click', addProgress);
The innerHTML+= assignment will recreate all previous elements within the container element, meaning that your references to other progress elements are no longer to the actual elements that this assignment creates.
You should add a new progress element like this:
function createProgress() {
const el = document.createElement("progress");
el.setAttribute("data-progress", progressCount);
el.setAttribute("value", 0);
el.setAttribute("max", 100);
container.appendChild(el);
return el;
}
As Makyuu commented below, the number of steps for the individual progress elements are only taken when their animations start. This means that if you change the input value, it will apply also to previously created elements (when they have not started animating yet).
If it is intended to use the number of steps as they were indicated at the moment of element creation, then modify two lines in your code:
queue.push([getSeconds(), el]);
and:
animateProgress(...queue.shift());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With