Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting if beforeunload event was cancelled by an unrelated function

I have a simple function to show a spinner overlay while a new page request is being made.

$(window).on("beforeunload", function() {
  $('#nav-spinner').show();
});

This works perfectly.. but, it is used on a complex WordPress site and there are other (third party) components that also use this event to sometimes cancel the navigation (for instance, a confirmation when navigating away from a partially filled form).

Is there any way to determine if another function cancelled the page unload so I can remove my overlay immediately when they are remaining on the page.

I would like to do this when an actual navigation is cancelled - using a timer to remove the overlay will result in either the overlay being hidden prematurely or remaining for longer than it should.

like image 683
Jomac Avatar asked Oct 18 '25 12:10

Jomac


1 Answers

Test Case that shows the problem

So the following code shows what you have currently. I am setting the background red since it is a minimum amount of code.

window.addEventListener("beforeunload", function(event) {
  document.body.classList.add("red");
});

// 3rd party code that is showing the "are you sure"
window.addEventListener("beforeunload", function(event) {
  event.preventDefault();
  event.returnValue = 'I am 3rd party code';
});
.red {
  background-color: red;
}
<form>
  <button>Click Me then click "Cancel"</button>
</form>

Solving the problem

So now that we have the test case for what is wrong. The background should NOT remain red when the user clicks cancel. So how can we detect it? Well there is NO events that tells you what the user did.

So the only thing you can do would be to add a timer to remove what you added when the user cancels it. So if they click cancel, the timer runs and removes it.

But how do we keep it there if they do not cancel it? We use unload to kill the timeout that hides it. So remove the timeout and it will not fire.

var timer
// update the page as page exits
window.addEventListener("beforeunload", function(event) {
  document.body.classList.add("red");
  // if this timer runs, it means beforeunload was cancelled 
  timer = window.setTimeout( function () {
    document.body.classList.remove("red");
  }, 50);
});
   // remove the timer when the pages finally exits so the class is not removed.
window.addEventListener("unload", function(event) {
  window.clearTimeout(timer)
})


 // 3rd party code that is showing the "are you sure"
window.addEventListener("beforeunload", function(event) {
  event.preventDefault();
  event.returnValue = 'I am 3rd party code';
});
.red {
  background-color: red;
}
<form>
  <button>Click Me then click "Cancel"</button>
</form>

You may have to play with the timeout millisecond values. The flash of content for showing could be lessened with a transition, but hopefully the browser does not kill that unload.

like image 127
epascarello Avatar answered Oct 20 '25 02:10

epascarello