Gcq1 Gcq1 - 1 month ago 7
Javascript Question

SetValue and bootstrap progress-bar width not matching in jquery setInterval function

The values going into setting the progress-bar width are fine, but when I check on them within console or look at the results on the page, they're clearly incorrect. For some reason, this only happens when the check box choice is 1 and not 2.

var timeInterval;
// For procedure parameter
var choice;
if (document.getElementById('myonoffswitch').checked == false) {
choice = 1;
timeInterval = 300;
} else {
choice = 2;
timeInterval = 13400;
};

var $bar = $('.progress-bar');
var $barWidth = $('#pBar');
var barIntervalLength = 0;
var curBarWidth = 0;
var setWidth = 0;

var percentDisplay = 0;

$bar.width(0);

var progress = setInterval(function () {
barIntervalLength = $barWidth.width() / 20;
curBarWidth = $bar.width();
setWidth = barIntervalLength + curBarWidth;

percentDisplay = percentDisplay + 5;
if (percentDisplay > 100) {
clearInterval(progress);
$('.progress').removeClass('active');
} else {
$bar.width(setWidth);
$bar.text(percentDisplay + "%");

console.log("set: " + setWidth);
console.log("barWidth: " + $barWidth.width());
console.log("barIntervalLength: " + barIntervalLength);
console.log("bar.width: " + $bar.width());
};

}, timeInterval);


Below are the results from console:

set: 27.9
barWidth: 558
barIntervalLength: 27.9
bar.width: 0
set: 46.9
barWidth: 558
barIntervalLength: 27.9
bar.width: 19
set: 67.9
barWidth: 558
barIntervalLength: 27.9
bar.width: 40


The 2nd bar.width: should be 27.9, and 3rd should be 55.8 (or very close to those numbers).

These are the results if the box is checked (option 2), these are correct:

set: 27.9
barWidth: 558
barIntervalLength: 27.9
bar.width: 0
set: 55.9
barWidth: 558
barIntervalLength: 27.9
bar.width: 28
set: 83.9
barWidth: 558
barIntervalLength: 27.9
bar.width: 56
set: 111.9


I'm just banging my head against my desk trying to figure this out.

Hopefully someone can tell me what's going on.

Answer

Bootstrap progress bars widen/shorten using a css transition. The jquery width() function returns the actual width of the element. When choice=1 your interval is 300ms, which is much lower than the transition time. Thus, you're retrieving a width that is in between the initial width and the width you set.

Here's a demonstration of what's happening:

$(function() {
  setInterval(function() {
    $('.progress').width(1000);
  }, 1000);
  setInterval(function() {
    console.log($('.progress').width());
  }, 100);
});
.progress {
  width: 0;
  height: 40px;
  background: blue;
  transition: linear 10s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="progress"></div>

Instead, save the actual width you want the element to be in js. Something like:

var $bar = $('.progress-bar');
var $barWidth = $('#pBar');
var barIntervalLength = 0;
var curBarWidth = 0;

var percentDisplay = 0;

$bar.width(curBarWidth);

var progress = setInterval(function () {
barIntervalLength = $barWidth.width() / 20;
curBarWidth += barIntervalLength ;

    percentDisplay = percentDisplay + 5;
if (percentDisplay > 100) {
    clearInterval(progress);
    $('.progress').removeClass('active');
} else {
    $bar.width(curBarWidth);
    $bar.text(percentDisplay + "%");

    console.log("barWidth: " + $barWidth.width());
    console.log("barIntervalLength: " + barIntervalLength);
    console.log("bar.width: " + $bar.width());
    };

}, timeInterval);