0

I want to create a simple loading bar with jQuery. I have n ajax requests that I run in sequence and I want to update the bar after each of them. The problem is that the HTML updates only when all of them are done. I can see the attribute changing as they load, but the visual changes appear only in the end. How can I make them appear during pageload?

I update bar width with this line progressDiv.attr('style', 'width: ' + perc + '%'); The width updates while loading, but the actual changes is only in the end.

Deez
  • 849
  • 2
  • 9
  • 28

3 Answers3

1

Try progressDiv.css('width', perc + '%');

Anis D
  • 761
  • 11
  • 25
1

Problem is that the browser engine will hold on to the CSS changes to the page untill the scripts are complete. This is a approach to have a better performance.

Why it happens?

For better understanding look at this example which changes the div color in each line of the script. Observer the behaviour

$('div').css('background-color','red');
alert('now showing red!');
$('div').css('background-color','yellow');
alert('now showing yellow!');
$('div').css('background-color','green');
alert('now showing green!');
$('div').css('background-color','blue');
alert('now showing blue!');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width:100px;height:100px;"></div>

You can notice that the background color is not changed until the scripts are completed. This is because the browser engine keeps a track of all the changes happening on the element in its memory and once everything is complete it goes ahead and updates the UI, imagine if the browser had started updating the UI for every call? if there were many changes then you would see performance issue.

How to resolve it?

Look into this example

setTimeout(function(){
 $('div').css('background-color','red');
 alert('now showing red!');
},0);

setTimeout(function(){
 $('div').css('background-color','yellow');
 alert('now showing yellow!');
},0);

setTimeout(function(){
 $('div').css('background-color','green');
 alert('now showing green!');
},0);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width:100px;height:100px;"></div>

So wrapping your functions inside a setTimeout will resolve the issue.

That means wrapping your line progressDiv.attr('style', 'width: ' + perc + '%'); within a setTimeout must fix your issue.

setTimeout(function(){
 progressDiv.attr('style', 'width: ' + perc + '%');
},0)

To get more details on why this setTimeout(function(){},0) works... Here is more detailed explanation

Hope this helps.

Community
  • 1
  • 1
Rajshekar Reddy
  • 18,647
  • 3
  • 40
  • 59
  • I placed the timeout function in `success: function(data) {}` for each request and in a general `$(document).ajaxComplete(function() {});` - it still refreshes only after the last one. – Deez Dec 07 '16 at 14:52
  • Can you share the code via Jsfiddle? so that I can take a look – Rajshekar Reddy Dec 07 '16 at 15:19
0

The correct syntax is

progressDiv.css('width', perc + '%');

or

progressDiv.css({width: perc + '%'});
André Dion
  • 21,269
  • 7
  • 56
  • 60
  • Same result - width only increases after full page load and the bar pops up full right away. – Deez Dec 07 '16 at 14:17
  • Btw, you need to put the code who updates the bar size in a callback function to all of those request. It will be a lot easier with the code, but you can try this approach. You can chain the requests too, but i dont think it is really needed – Lima Chaves Dec 07 '16 at 14:20