user3504410
user3504410

Reputation: 183

DOM changes not executing immediately

So I have a hidden element, I want to show it and then trigger an alert right after.

I tried using jquery:

$('#myElement').show();
alert('test');

I also tried using just regular javascript:

document.getElementById('myElement').setStyle('display: block');
alert('test');

However in both cases I see that when I run this, the alert appears, my element is still not visible, and then once I close the alert then the element begins to show.

Why is the alert being run before the DOM is updated? Do I have any way to force a DOM update or do i need to add a manual timeout after I show the element?

I have tried playing around with $.then() and $.done() but neither seems to work.

Upvotes: 2

Views: 2155

Answers (3)

Duc Hong
Duc Hong

Reputation: 1189

If you're using jQuery, then you can add an callback after show() is executed.

Link for document: http://api.jquery.com/show/

$('#myElement').show(400, function() {
   alert('test')
})

Upvotes: -1

Rory McCrossan
Rory McCrossan

Reputation: 337714

This is because alert() is a modal operation which blocks the UI thread of the browser from updating. In the code above, when you call alert() the DOM is still in the process of being updated, but has not yet finished being redrawn, yet the thread has been blocked from completing until the user dismisses the alert().

You have three solutions. Firstly you could put the alert() in a timeout to delay it:

$('#myElement').show();
setTimeout(function(){
  alert('test');
}, 20); // 20ms should be a long enough delay even on the slowest machines

Secondly, you could use a library to display non-modal alerts within the DOM itself, ie. Notify.

Lastly, assuming your purpose is just for testing/debuggin, you can use console.log() as it does not a modal operation:

$('#myElement').show();
console.log('test');

To see the console, press F12 in your browser. Note that this method, along with console.dir(), should always be used for debugging, not alert().

Upvotes: 2

Quentin
Quentin

Reputation: 944430

Browser repaints triggered by JS run on the main JavaScript event loop.

The DOM is updating, but the rendering of it isn't done until JS isn't busy with something else.

The alert() is blocking, so all JS on the main event loop is paused until it is dismissed.

You could wait for an animation frame before running your alert.

document.getElementById('myElement').setStyle('display: block');
requestAnimationFrame(() => alert('test');)

Upvotes: 5

Related Questions