Run Javascript code only if 'beforeunload' function returns true

darkpbj picture darkpbj · Apr 3, 2013 · Viewed 9k times · Source

I'm using JQuery to capture the unload event when a user navigates away from a page. This works just fine, but I have data that needs to be saved only in the event that the user really wants to leave.

Here's my catch-22. If I save the code too early and the user doesn't want to leave, I've spoiled the state of the web service backing the code.

Therefore I need to accomplish the near insurmountable task of executing code only if the 'beforeunload' dialog returns true.

$(window).on('beforeunload', function(e) {
    var info = * some info to save the current page state *
    return 'Are you sure you want to navigate away from the Test Runner?';

    //unreachable place where I wish I could ajax 'info' back to safety
});

This code as is will pop up a dialog that asks 'Are you sure you want to navigate away from the Test Runner?' and if the user clicks cancel will prevent the user from leaving the page.

Here is another thought:

$(window).on('onunload', function(e) {
    var info = * some info to save the current page state *
    var r=confirm('Are you sure you want to stop the Test Runner?');
    if(r==true)
    {
        //place where I wish I could ajax 'info' back to safety
        return 'leaving'
    }
    else
        return 'leaving unsaved';
});

This second method will not prevent the user from leaving either way, but in one case will execute some save code first, and in the other will boot them back out into cold. The issue with this approach is that most browsers (rightfully) prevent confirm boxes from launching in the window.onunload state thanks to years of 90's web developers blindsiding poor dial-up web surfers with it.

A disclaimer: I'm well aware that we in the web developer community strongly discourage preventing the user from leaving a page and executing code in the background as they try to do it. When I see questions like, "How do I prevent a user from leaving my really awesome website" my knee-jerk reaction is typically, "don't do it!" That said this is different. This is a specialized page for a particular client and we need this as a panic-prevention measure. I'm one of the good guys, I promise. I'm one you.

Answer

metadings picture metadings · Apr 3, 2013

Try to use both events. What you need is a shared variable in the same scope, not to say global variable. onbeforeunload will be fired before the dialog appears. onunload will only be fired if the user clicked to escape the window/tab.

// Use a variable in the same scope of both events:
var savedState;

$(window).on('beforeunload', function(e) {

  savedState = "what the user currently made";

  return "Sure U are?";
});

$(window).on('unload', function(e) {

  // user didn't save!!
  // your auto-save function:
  auto_save(savedState);

  // browser leaves this tab.
});

As a scope, I mean something like (function () { })(); or any else (constructor or functional) function.