Problem:
I want a progress bar to unhide when the button is pressed and then to update. However, with the following code the progress bar shows but does not update.
If I remove style="display: none"
the bar updates as expected. Any ideas?
document.getElementById("submit-btn").addEventListener("click", function() {
document.getElementById("progress-top").style.display = 'block';
var i = 0;
if (i == 0) {
i = 1;
var width = 1;
var id = setInterval(frame, 50);
function frame() {
if (width >= 100) {
clearInterval(id);
i = 0;
} else {
width++;
document.getElementsByClassName('progress-bar').item(0).setAttribute('aria-valuenow', width);
document.getElementsByClassName('progress-bar').item(0).setAttribute('style', 'width:' + Number(width) + '%');
}
}
}
})
<div class="progress" style="display: none" id="progress-top">
<div class="progress-bar" role="progressbar" aria-valuenow="" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
I’m using Bootstrap 4 for the CSS
.progress {
display: flex;
height: $progress-height;
overflow: hidden; // force rounded corners by cropping it
font-size: $progress-font-size;
background-color: $progress-bg;
@include border-radius($progress-border-radius);
@include box-shadow($progress-box-shadow);
}
.progress-bar {
display: flex;
flex-direction: column;
justify-content: center;
color: $progress-bar-color;
text-align: center;
background-color: $progress-bar-bg;
@include transition($progress-bar-transition);
}
Solution:
Consider using the <progress>
element were you just need to se the value
.
To prevent starting the loop twice, consider checking the PID.
let id = null;
document.getElementById("submit-btn").addEventListener("click", function() {
document.getElementById("progress-top").style.display = 'block';
if (id === null) {
var val = 1;
id = setInterval(frame, 50);
function frame() {
if (val >= 100) {
clearInterval(id);
id = null;
} else {
val++;
document.getElementById('progress').setAttribute('value', val);
}
}
}
})
.progress {
height: 150px;
}
<div class="progress" style="display: none" id="progress-top">
<progress id="progress" value="0" max="100">0%</progress>
</div>
<button id='submit-btn'>Click me</button>
Regarding the Bootstap variant, you’ll need to set both style.width
and innerHTML
.
The aria-valuenow
doesn’t need to be updated.
let id = null;
document.getElementById("submit-btn").addEventListener("click", function() {
document.getElementById("progress-top").style.display = 'block';
if (id === null) {
var val = 1;
id = setInterval(frame, 50);
function frame() {
if (val >= 100) {
clearInterval(id);
id = null;
} else {
val++;
document.getElementsByClassName('progress-bar')[0].style.width = val + '%';
document.getElementsByClassName('progress-bar')[0].innerHTML = val + '%';
}
}
}
})
.progress {
height: 150px;
width: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="progress" id="progress-top" style="display: none">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<button id='submit-btn'>Click me</button>