3

I have a button (lets call it Toggler) that changes the disabled property of another button then displays an alert() message.

In Internet Explorer 11, when one clicks on Toggler, the button visually becomes disabled when the alert message displays.

However, in Chrome (54.0.2840.99), when one clicks on Toggler, the button does NOT visually become disabled when the alert message displays. Only after closing the alert box does the button become disabled.

How would I make both browsers (and Safari, Edge, etc - company computer so I don't have them) have the button appear disabled when the alert message pops up?

Barebones code to demonstrate

var btn;
var enabled = true;

function toggle() {
  if (enabled) {
    disableBtn(btn);
    alert("Now Disabled");
  } else {
    enableBtn(btn);
    alert("Now Enabled");
  }
  enabled = !enabled
}

function disableBtn(element) {
  element.disabled = true;
}

function enableBtn(element) {
  element.disabled = false;
}

window.onload = function() {
  btn = document.getElementById("btn");
}
<button onclick="toggle();">Button to toggle things</button>
<br />
<br />
<button id="btn">Button that shows if enabled or not</button>
Kevin L
  • 1,066
  • 3
  • 12
  • 21

1 Answers1

4

What's happening is the alert is being created by the browser (native code) faster than the JavaScript runtime can update the display of the button.

An alert() isn't actually created by JavaScript. JavaScript can initiate a request for one, but an alert is part of the window API (it's actually window.alert()) and the window API is managed by the browser, not the JavaScript runtime.

So, if you've got some JavaScript on one line that does something that should cause the UI to update and the next line initiates a request for an alert, even though the two lines were processed one at a time, they happen one right after the other with very little delay between them. At that point, it's a race between the browser and the JavaScript runtime to see which can update the UI first. Since the browser (which is written in native code) is faster than the JS runtime, the browser wins the race (even though its instruction came second) and produces the alert() before the button's rendering is completed.

Now, because an alert is a "blocking" component, that is it blocks the UI from updating, the button's display now cannot be updated until the alert completes.

To solve this, you can delay the request for the alert() just long enough to ensure the button's rendering changes first with setTimeout(). setTimeout() (another window API), requires you pass it a function that will run after a specified millisecond delay, when the JavaScript runtime is idle, which won't happen until (at least) the current function completes.

var btn = document.getElementById("btn");
var enabled = true;

function toggle() {
    if(enabled) {
     disableBtn(btn);
  
        // Add a short delay to allow the UI to catch up
        setTimeout(function() {
            alert("Now Disabled");
        }, 20);  
    } else {
        enableBtn(btn);
    
        setTimeout(function() {
            alert("Now Enabled");
        }, 20);
    }
    enabled = !enabled;
}

function disableBtn(element) {  element.disabled = true; }
function enableBtn(element) {  element.disabled = false; }
<button onclick="toggle();">Button to toggle things</button><br /><br />
<button id="btn">Button that shows if enabled or not</button>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Do you have any idea what kind of delay would be required to make it work across varying machines/browsers? Ideally I would use the smallest delay needed to have everything update. – Kevin L Nov 30 '16 at 22:49
  • I would imagine that it shouldn't need to be more than 1/10th of a second to be sure. In my example, I'm using 1/4 of a second (250 milliseconds). – Scott Marcus Nov 30 '16 at 22:50
  • @Sébastien Please limit your edits of other people's questions/answers to corrections, not your personal preferences. I had the code formatted the way I did on purpose. Altering it to match your particular coding preference is not what edits are for. – Scott Marcus Dec 31 '17 at 18:43
  • ?? This must have been part of my first wave. Again I'm sorry, I did not edit anymore of your posts after your first remarks yesterday. – Sébastien Dec 31 '17 at 18:48