Force DOM redraw with javascript on demand

The title of the question expresses what I consider to be the final question behind my specific case.

My case: Inside the click handler, I want to make the image visible (loading animation) just before the busy function starts. Then I want to make it invisible again after the function finishes. Instead of what I expected, I understand that the image never becomes visible. I assume this is because the browser is waiting for the handler to complete before it can redraw (I am sure there are good reasons for this for performance).

Code (also in this script: http://jsfiddle.net/JLmh4/2/ )

HTML:

<img id="kitty" src="http://placekitten.com/50/50" style="display:none"> <div><a href="#" id="enlace">click to see the cat</a> </div> 

JS:

 $(document).ready(function(){ $('#enlace').click(function(){ var kitty = $('#kitty'); kitty.css('display','block'); // see: http://unixpapa.com/js/sleep.html function sleepStupidly(usec) { var endtime= new Date().getTime() + usec; while (new Date().getTime() < endtime) ; } // simulates bussy proccess, calling some function... sleepStupidly(4000); // when this triggers the img style do refresh! // but not before alert('now you do see it'); kitty.css('display','none'); }); }); 

I added an alert call immediately after the sleepStupidly function to show that the browser was redrawing at that moment of rest, but not earlier. I innocently expected it to be redrawn immediately after setting "display" to "block";

For the record, I also tried adding html tags or replacing css classes instead of the image displayed and hiding in this code. The same result.

After all my research, I believe that I need support to get the browser to redraw and stop everyone else until then.

Is it possible? Is this possible with a cross browser? Some plugin that I could not find, maybe ...?

I thought it might be something like a "jquery css callback" (like in this question: In JQuery, is it possible to get a callback function after setting a new css rule? ) Would do the trick ... but that doesn't exist.

I also tried to display the show, function call and hide in different handlers for the same event ... but nothing. Also adding setTimeout to delay the execution of the function (as recommended here: Update the DOM in JavaScript ).

Thanks, and I hope this helps others as well.

javier

EDIT (after setting my preferred answer):

Just to explain why I chose the window.setTimeout strategy. In my real case, I realized that in order to give the browser enough time to redraw the page, I had to give it about 1000 milliseconds (much more than 50 for the violin example). I suppose this is due to the deeper DOM tree (actually, unreasonably deep). The setTimeout approach allows you to do this.

+8
javascript jquery dom
source share
5 answers

Use window.setTimeout() with some short, imperceptible delay to run the slow function:

 $(document).ready(function() { $('#enlace').click(function() { showImage(); window.setTimeout(function() { sleepStupidly(4000); alert('now you do see it'); hideImage(); }, 50); }); }); 

Live demo

+5
source share

Use jQuery show and hide callbacks (or another way to display something like fadeIn / fadeOut).

http://jsfiddle.net/JLmh4/3/

 $(document).ready(function () { $('#enlace').click(function () { var kitty = $('#kitty'); // see: http://unixpapa.com/js/sleep.html function sleepStupidly(usec) { var endtime = new Date().getTime() + usec; while (new Date().getTime() < endtime); } kitty.show(function () { // simulates bussy proccess, calling some function... sleepStupidly(4000); // when this triggers the img style do refresh! // but not before alert('now you do see it'); kitty.hide(); }); }); }); 
+7
source share

To force a redraw, you can use offsetHeight or getComputedStyle ().

 var foo = window.getComputedStyle(el, null); 

or

 var bar = el.offsetHeight; 

"el", which is a DOM element

+1
source share

I don’t know if this works in your case (since I didn’t test it), but when manipulating CSS with JavaScript / jQuery it is sometimes necessary to force a certain element to be redrawn for the changes to take effect.

This is done by simply querying the CSS property.

In your case, I would try to put kitty.position().left; before calling the function before starting with setTimeout .

0
source share

The setting worked for me:

 $(element).css('display','none'); 

After that, you can do whatever you want, and in the end you want to:

 $(element).css('display','block'); 
0
source share

All Articles