Clive Atkins
Clive Atkins

Reputation: 543

Javascript Progess bar wont load correctly

I am working on a simple jquery loading bar that I can post amounts to. My issue is it seems to only jump to the last result even with settimeout set in javascript.

The test script includes 3 buttons which work perfectly, however I need to be able to call the function from the inline code at the bottom. This will seem to jump to the last result 75% without showing the 25% for and waiting 3 seconds as I am hoping for.

<!DOCTYPE html>
<html>
<style>
#Progress {
  width: 100%;
  background-color: #ddd;
}

#Bar {
  width: 1%;
  height: 30px;
  background-color: #4CAF50;
}
</style>
<body>

<h1>Progress Bar</h1>

<div id="Progress">
  <div id="Bar" style="width:0px;"></div>
</div>

<br>
Buttons for testing bar not needed in actual script<br>
<button onclick="move(50)">Test Bar 50%</button> <br>
<button onclick="move(75)">Test Bar 75%</button> <br>
<button onclick="move(100)">Test Bar 100%</button> <br>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script>
function move(amount) {
  var elem = document.getElementById("Bar");   
  elem.style.width = amount + '%'; 
}
// Inline calls I need to use for my script. These seem to jump to the last one when loaded dispite timeout.
setTimeout(function(){
  move(25);
}, 3000);
setTimeout(function(){
  move(75);
}, 3000);
</script>

</body>
</html>

Upvotes: 1

Views: 47

Answers (1)

Robin Mackenzie
Robin Mackenzie

Reputation: 19289

At the moment, both setTimeout calls run in parallel so on completion you see only the 75% result (even though the 25% result occurred it is not visible anymore).

You could nest the setTimeout calls so they act sequentially. See the snippet below:

function move(amount) {
  var elem = document.getElementById("Bar");
  elem.style.width = amount + '%';
}
// nest the setTimeout calls so they fire sequentially
setTimeout(function() {
  move(25);
  setTimeout(function() {
    move(75);
  }, 3000);
}, 3000);
#Progress {
  width: 100%;
  background-color: #ddd;
}

#Bar {
  width: 1%;
  height: 30px;
  background-color: #4CAF50;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="Progress">
  <div id="Bar" style="width:0px;"></div>
</div>

<br> Buttons for testing bar not needed in actual script<br>
<button onclick="move(50)">Test Bar 50%</button> <br>
<button onclick="move(75)">Test Bar 75%</button> <br>
<button onclick="move(100)">Test Bar 100%</button> <br>

Update

If you have a variable number of points of progress to display then you can use the technique below which was adapted from this useful answer.

function move(amount) {
  var elem = document.getElementById("Bar");
  elem.style.width = amount + '%';
}

// set array of points:
var movements = [10, 20, 30, 50, 75, 99, 100];
var i = -1;

function moveSequence() {
  move(movements[i++]);
  if (i < movements.length) setTimeout(moveSequence, 1000);
}
moveSequence();
#Progress {
  width: 100%;
  background-color: #ddd;
}

#Bar {
  width: 1%;
  height: 30px;
  background-color: #4CAF50;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="Progress">
  <div id="Bar" style="width:0px;"></div>
</div>

<br> Buttons for testing bar not needed in actual script<br>
<button onclick="move(50)">Test Bar 50%</button> <br>
<button onclick="move(75)">Test Bar 75%</button> <br>
<button onclick="move(100)">Test Bar 100%</button> <br>

Upvotes: 1

Related Questions