Search code examples
javascriptcross-browseronbeforeunload

How do I ask the user to confirm they want to leave the page?


I have a web site that contains several pages where the user can add and edit information. In order to provide a consistent UI, I have the following JavaScript function...

function setWindowBeforeUnload(changed) {
  $(window).on("beforeunload", function() {
    if (confirmLeave && changed && changed()) {
      return "You haven't saved the information. If you leave this page, the information will be lost.";
    }
  });
}

confirmLeave is a global variable that specifies if we are to ask them for confirmation before navigating away (which we don't if we are navigating to another page after a successful save). changed is a function that checks if the entity has changed.

This is called from a details page (say the customer page) as follows...

$(document).ready(function() {
  setWindowBeforeUnload(customerChanged);
});

function customerChanged() {
  // Checks the data and returns true or false as appropriate
}

This all worked fine until recently, when a change in Chrome broke it.

I have searched for hours, and found loads of people suggesting code like this...

addEventListener('beforeunload', function(event) {
  event.returnValue = 'You have unsaved changes.';
});

...which works fine as it is, except that it fires the warning whenever they leave the page, irrespective of whether or not the data has changed.

As soon as I try to add any logic (such as my checking code in the first sample), it doesn't work...

function setWindowBeforeUnload(changed) {
  addEventListener('beforeunload', function(event) {
    if (confirmLeave && changed && changed()) {
      event.returnValue = 'You have unsaved changes.';
    }
  });
}

With this code, I can navigate away from the page without getting a warning.

Is there any way to reproduce my original behaviour now?


Solution

  • You can use logic in the handler, you just can't have a custom message any more. See the code below. Use the "Run code snippet" to simulate navigation. Run the snippet, run it again no confirm. Toggle the button to "false" run the snippet and get a confirm.

    var test = true;
    
    function otherTest() {
      return true;
    }
    
    addEventListener('beforeunload', function(event) {
    if(!test || !otherTest()) {
      event.returnValue = 'You have unsaved changes.';
    }
      
    });
    
    document.getElementById('theButton').addEventListener('click', function(event) {
      test = !test;
      this.innerHTML = test.toString();
    });
    <p>Click the button to turn the confirm on and off</p>
    <button id="theButton">true</button>