Reputation: 67
I have the following HTML code. While the screen is covered by the "cover" DIV, click on the button and somewhere else. The click not on the button does not fire. Later when the "cover" DIV is hidden the click on the button fires.
It appears as if there is a timing issue. Can someone please explain this behavior?
Markup:
<div id="cover"></div>
<button onclick="alert('Button clicked')">Click me</button>
<div id="text"></div>
CSS:
#cover {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 100;
background-color: white;
opacity: 0.8
}
Javascript:
function hide ()
{
document.getElementById ("cover").style.display = "none";
}
function show ()
{
document.getElementById ("cover").style.display = "block";
}
function busy (callback)
{
show ();
setTimeout (callback, 1);
}
function work ()
{
var start = (new Date ()).getTime ();
var wait = 3000;
while ((new Date()).getTime () - start < wait)
{
/* do nothing */
}
hide ();
}
function start ()
{
document.getElementById ("cover").onclick = function (ev) {
document.getElementById ("text").innerHTML = 'Cover clicked';
};
busy (work);
}
http://jsfiddle.net/userdude/5DutW/4
Upvotes: 0
Views: 376
Reputation: 67
After a number of tests, I can confirm this behavior. There is a big difference between Firefox and Chrome.
Keep in mind that, as many have said, a Javascript program is single-threaded.
In Firefox, when the function 'work' is performing the Ajax call, clicks are ignored. When the function returns and "cover" disappears, nothing happens.
In Chrome, the clicks are caught and queued. When the function 'work' returns, the onclick events are fired. Since "cover" has disappears, it does not get the onclick event. The button, on the other hand, receives the onclick event. For example, when I click on the button twice (when it was covered), later I get two alerts.
I find the Chrome behavior is confusing and IMHO wrong, because at the time I click my eyes naturally tells me that the button is covered thus can not be clicked (it doesn't appear as clicked button).
Thanks for all the answers and clues. I really appreciate it.
Upvotes: 0
Reputation: 13967
This happens because you are locking the page thread:
while ((new Date()).getTime () - start < wait)
{
/* do nothing */
}
This prevents events from being handled until it finishes, as well as prevent updates to the UI.
Why not just use a timeout instead? setTimeout(hide,wait);
Upvotes: 0
Reputation: 71918
Your work
function doesn't work (no pun intended): it will freeze the UI for 3 seconds, so clicks and other interactions will be queued up as you describe. Why don't you just pass 3000
to setTimeout
instead of 1
?
function busy (callback)
{
show ();
setTimeout (callback, 3000);
}
function work ()
{
hide ();
}
Upvotes: 4