Web Apps In The Browser - BeforeUnload
Written by Mike James   
Monday, 18 February 2013
Article Index
Web Apps In The Browser - BeforeUnload
Using beforeunload

One of the big problems with building a web application is keeping the browser from messing up your best efforts. You can see the browser as an enemy trying to enforce a more general behavior on your app. After all your web app just wants to do whatever you programmed it to but the browser wants to get on with browsing.

 

This article is one in a series on creating web apps:

 

Every browser comes with a standard user interface designed to let the user navigate web pages effectively. Of course once the user has loaded your web app the last thing you want them to do is navigate web pages when they really don't want to. For example if your app has a text editor and the user accidentally navigates away from the page by say pressing a short cut key then all their work is lost. This is not good and it is your web app that will be blamed for the loss.

There is a similar but usually less serious problem with respect to events. There are many events within a web page that the browser handles. For example, if you select an area or some text then the browser assumes that you are about to do a copy or a paste and so highlights the area. This is usually fine but if you are implementing a drag for some other purpose the highlighting can be misleading. The same sort of thing happens when browsers are running in a touch environment. Some gestures such as swipe and even tap are captured by the operating system via the browser. This can ruin your attempts at implementing a clever UI.

The problem is that the browser isn't always the best container for an app. The browser plays the role of the operating system for a web app but it is also an application in its own right. It is as if you had to create desktop apps within a word processor or a spreadsheet. The container for your app has its own UI and its own set of behaviors. If you want your app to behave more like an app then you have to gain control of these behaviors - and this is not easy.

Stay On The Page

When you first start thinking about this problem then the tendency is to think that the best solution is to disable all of the offending short cut keys and leave the ones that do no obvious harm. This can be done but exactly how to do it varies according to the browser and this makes it very difficult.

A more general approach to the problem is to intercept all of the intercept all of the keyboard and mouse clicks that are going to cause problems and handle them within the app. This can work but again there is the problem of which short cut keys are supported i.e. it depends on the browser.

When you start to analyze the harm done by the browser then the one big problem is when any UI action causes the user to navigate away from your app. Obviously you can't pin them down and lock them into staying on your page but you can make sure that they mean to leave.

So what we are going to do is leave all of the browser's UI alone and simply try to catch the error or leaving the page when it wasn't intended and to do this we need to make use of the beforeunload event. This is an HTML5 standard and browsers support it reasonably well but there are a few problems. In fact this very important event from the point of view of most web apps is a bit of a mess.

Notice that it isn't the same as the unload event which is widely supported. The beforeunload event occurs a the point that the browser is first notified that the user wants to leave the page. The page and its resources haven't been changed as yet and so the state is recoverable and if the user cancels the event the browser ignores the request and the page continues from where it was. The unload event happens after resources have been unloaded and before the new page starts loading. At the unload event the page state is not recoverable.

In other words, the beforeunload event is the only way of stopping the user leaving your page without loss of data.

The simplest way to intercept the user leaving the page is to define a handler for the beforeunload event directly. The HTML5 specification says that to give the user an opportunity to  cancel the event you have to set the returnValue property of the event object.

For example:

window.addEventListener("beforeunload",
  function (e) {
    var confirmationMessage = "My Message";
    e.returnValue=confirmationMessage;
  });

This event fires in nearly all situations where the user leaves a page on most browsers. However none of the big three modern browsers popup a dialog box in this case. They all ignore the returnValue.

If you change the final line to:

window.event.returnValue=confirmationMessage;

then IE does popup a dialog box - but not for the correct reason as window.event.returnValue is a Boolean.

To make the event handler work as we would like it to you can forget the HTML5 standard and simply return a non-empty string to provide the opportunity to cancel the page unload.

window.addEventListener("beforeunload",
  function (e) {
    var confirmationMessage = "My Message";
    return confirmationMessage;
  });

This in theory should also result in the browser displaying the text you supply but this doesn't always happen.

The latest version of Firefox (18) and the mobile version of Firefox does display a dialog box but it ignores your text:

 

firefox

 

The latest version of Chrome (24) and the mobile version of Chrome also displays a dialog box but this time it includes your text:

chrome1

 

As is usually the case the problem case is IE but the good news is that both IE9 and IE10 work in the same way as Chrome i.e. they display a dialog box with the message:

 

IE9

 

The big problem with IE is that whether or not this works depends on the display mode used for the page - it only works in IE9 or 10 standards mode. To be sure that you encounter IE9 in standards mode the page has to include the meta tag:

<meta http-equiv="X-UA-Compatible"
                           content="IE=9">

in the page header. In standards mode IE9 supports both addEventListener and the beforeunload event in the HTML5 standard way.

You can do the same job using jQuery:

$(window).on("beforeunload",
  function (e) {
   var confirmationMessage = "My Message"; 
   return confirmationMessage; 
});

 

This works in most browsers but  if you want to support earlier versions of IE, Firefox or Chrome then you are going to have to do some additional work. For example, in earlier versions of IE you need to use attachEvent or stick with jQuery. Earlier versions of IE also need you to set the window.event.returnValue. A reasonably good cross browser version is something like:

window.addEventListener("beforeunload",
function (e) {
 (e || window.event).returnValue = "text";  
 
return "text";
});

or better using jQuery:

$(window).on("beforeunload",
  function (e) {
  (e || window.event).returnValue="text";  
 
return "text";
});

Overall given that you are probably going to be needing HTM5 facilities for the rest of your app it is better to simply insist that the user has an up-to-date version of Firefox, Chrome or IE.

  



Last Updated ( Tuesday, 19 March 2013 )