Capturing result of window.onbeforeunload confirmation dialog
Asked Answered
N

3

17

Is there a way to capture to result of the window.onbeforeunload confirmation dialog like the one below from Stack Overflow (this happens when leaving the 'Ask Question' page without posting the question)?

This is how it appears in Chrome, I believe it's slightly different in other browsers, but you always have some form of yes/no buttons.

window.onbeforeunload confirmation dialog

Presumably if they're still on the offending page after the event has been triggered they chose to stay and you could probably figure this out by watching the sequence of js. However I would like to know how to determine if they clicked "Leave this page"?

I've implemented this like below:

// concept taken from SO implementation
function setConfirmUnload(showMessage, message) {
    window.onbeforeunload = showMessage ? (message ? message : "this is a default message") : null;
}

// pseudo code
listen to changes on inputs
if any inputs fire a change event
   call setConfirmUnload(true, 'My warning message')

note I'm using jQuery within my site.

I'm essentially trying to implement a Gmail like drafting implementation, wherein if a user leaves a page with a form they've made changes to without saving they're warmed with a similar dialog. If they choose to discard they're changes and leave the page, I need to clean up some temporary records from the database (I'm thinking an AJAX call, or simply submitting the form with a delete flag) then sending them on their way.

My question also relates to:

jQuery AJAX call in onunload handler firing AFTER getting the page on a manual refresh. How do I guarantee onunload happens first?

Nereus answered 23/3, 2011 at 0:43 Comment(0)
P
7

You can have the exit confirmation using window.onbeforeunload but there isn't a way to find out which button the user clicked on.

To quote an earlier response from jvenema from this thread:

The primary purpose for the beforeunload is for things like allowing the users the option to save changes before their changes are lost.

Besides, if your users are leaving, it's already too late [...]

Pompom answered 23/3, 2011 at 2:4 Comment(4)
To test what the user clicked: i found a successful solution using window.onfocus(). That function will be triggered when the user clicks on STAY, and is returned to the page. However, note that onfocus() will also be triggered when changing tabs, windows etc. Set a global variable in onbeforeunload() to be able to check/capture from where the user is coming. If the user DOES want to leave the page, you can do some final stuff in window.onunload()Kinetic
The window.onfocus trick didn't work in Firefox and Chrome for me (just IE) but I found that using setTimeout in the 'beforeunload' handler (to call run some code if a user chose to stay on the page) worked. You can see a working example here: jsfiddle.net/nathanbedford/uscobrm0/10Rundell
I found both these methods do not work (reliably) when refreshing the page in firefox 75.0, The timeout seems to work, but it must be set to longer than the reload time of the page. I tested it and sometimes a timeout of a second triggered thus impacting the reloaded page.Furan
did some more digging and found the timeout must be set to longer than the time the user needs to make up their mind as the timer will continue to run in the background.Furan
R
7

How about this:

$( window ).bind( 'beforeunload' , function( event ) {
    setTimeout( function() {
        alert( 'Hi againe!' );
    } );
    return '';
} ).bind( 'unload', function( event ) {
    alert( 'Goodby!' );
} );
Reviel answered 5/6, 2013 at 19:10 Comment(1)
That doesn't really cut it... even on a localhost it mostly takes more than one tick between beforeunload and unload. Even a 500ms delay can be too short on a slow connection.Stutsman
P
6

Late to the party, but I found the following code (in TypeScript) to be a decent way to detect if the person clicked on 'Ok' on that confirmation dialogue window.

public listenToUnloadEvents(): void {

  window.addEventListener('beforeunload', (e) => {
    const confirmationMessage = '\o/';

    (e || window.event).returnValue = confirmationMessage;     // Gecko + IE
    return confirmationMessage;                                // Webkit, Safari, Chrome etc.
  });

  window.addEventListener('unload', () => {

    this.sendNotification(Action.LEFT)
  });
}

I'm not sure how much time you have to run code in the unload event, but in this instance, I am sending a notification through Socket.io, so it's very quick at completing.

As for detecting the cancel on that notification, as someone else mentioned, creating a global variable like let didEnterBeforeUnload = false could be set to true when the beforeunload event fires. After this, by creating the third event, like so (again, in TypeScript), you can infer the user pressing cancel

window.addEventListener('focus', (e) => {

  if (didEnterBeforeUnload) {
    console.log('pressed cancel')
  }

  didEnterBeforeUnload = false
});

As a side-note though, these events won't (iirc) fire unless you have interacted with the page. So make sure to click or tap into the page before trying to navigate away during your testing.

I hope this helps anyone else out there!

Padraic answered 4/9, 2018 at 11:53 Comment(1)
The workaround for detecting if the cancel button was pressed works for me. Thanks!Jeb

© 2022 - 2024 — McMap. All rights reserved.