Andriy
Andriy

Reputation: 11

How change HTML during event processing?

Until all events are completed changes in html do not occur

(function(){
    function sleep(ms) {
        const date = Date.now();
        do {
        } while (Date.now() - date < ms);
    }
    let button = document.getElementById('update');
    
    //basic code example:
    /*button.addEventListener('click', event => {
        event.target.value = 'aaa';
        sleep(1000);//or another long process
        event.target.value = 'bbb';
    });/**/

    //even so:
    button.addEventListener('click', event => {
        event.target.value = 'aaa';
    });
    button.addEventListener('click', event => {
        sleep(1000);//or another long process
    });
    button.addEventListener('click', event => {
        event.target.value = 'bbb';
    });
})();
<input type="button" value="Update" name="update" id="update">

This applies to all types of events.

What is the reason for this?

Is there a way to change html during(before) the execution of event?

Upvotes: 0

Views: 164

Answers (2)

KooiInc
KooiInc

Reputation: 123026

Add the value change as callback to the long running function and use setTimeout to trigger a repaint:

document.addEventListener("click", bttnEx);

function bttnEx(evt) {
  const origin = evt.target;
  if (origin.name === "update") {
    origin.value = "waiting...";
    const longRun = () => sleep(2000, () => origin.value = "done!");
    return setTimeout(longRun, 1);
  }
}

function sleep(ms, callback) {
  const date = Date.now();
  do {} while (Date.now() - date < ms);
  callback();
}
<input type="button" value="Update" name="update" id="update">

You can also use requestAnimationFrame in a nested fashion:

document.addEventListener("click", bttnEx);

    function bttnEx(evt) {
      const origin = evt.target;
      
      if (origin.name === "update") {
        const runSomethingLongAndReEnable = () => {
          const date = Date.now();
          do {} while (Date.now() - date < 2000);
          origin.value = "Update";
          origin.disabled = false;
        };
        const waitAndDisable = () => {
          origin.value = "Busy...";
          origin.disabled = true;
          requestAnimationFrame(runSomethingLongAndReEnable);
        };
        
        return requestAnimationFrame(waitAndDisable);
      }
    }
body {
  margin: 2rem;
}
input[disabled] {
  color: red !important;
}
<input type="button" value="Update" name="update" id="update">

Upvotes: 0

pilchard
pilchard

Reputation: 12957

As Martin mentioned in the comments, you should read up on the Promise object, and asynchronous operations. see: Using Promises

Here is your snippet with the MDN example Promise.

(function () {
  function sleep(ms) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('done');
      }, ms);
    })
  }
  let button = document.getElementById('update');

  //basic code example:
  button.addEventListener('click', event => {
    sleep(2000).then(res => event.target.value = res);//or another long process
    event.target.value = 'loading...';
  });
})();
<input type="button" value="Update" name="update" id="update">

Upvotes: 1

Related Questions