Do You Want to Save Your Changes?

Posted on June 18, 2004

Web apps are great, but they have interface problems. A Web-based interface is just never going to be as rich as a traditional client-server app. Spolsky alluded to this in a post I made yesterday. HTML can really go just so far before you run into limitations. Here’s a big one:

That’s a pretty common dialogue box, but very hard to do on the Web. Picture this:

Joe User has just spent 20 minutes in the article editing interface of your Web-based content management app. He’s worked over this article until it’s just perfect, laboring intensively over every word. Then he accidentally hits Refresh and it’s all gone. Joe is not happy.

That’s the problem with Web forms – there’s no real way to stop the user from screwing themselves this way.

After they start work on the form content, they can (1) click a link and navigate away from the page, (2) press the Reset button on the form (never put these on your forms – think about it: when was the last time you used one), (3) close the browser, (4) refresh the page, etc. There’s any number of things they can do to wipe out their form data, and it’s very hard to stop them. I know this because I tried...

I set out this morning to try and minimize these risks in an app I’m developing. I come away from this process pretty convinced that it’s not practical. Here’s what I tried to do:

In my page, I bound a JavaScript function to the unload event:

window.onunload = warn_if_form_dirty;

This means the “warnifform_dirty” function will run whenever the current page leaves the browser window for any reason. Note that you can’t stop the event – the page is leaving no matter what, but you can do a few things before it goes. (If you could actually stop the page from unloading, then pop-up advertisers would have a field day with it.)

I also set two variables:

form_dirty = false;
warn_onunload = true;

The first variable indicates whether or not the form data is “dirty” – whether it’s been changed since they loaded the page. The second variable indicates whether or not we should warn them that they’re going to lose their data. When should we NOT warn them? When they submit the form. Remember that the unload event fires whenever the page unloads, even if it’s because they submit, in which case they WANT it to unload.

I added this to all my form fields:

onchange="form_dirty=true;"

So whenever a form field changes, the “dirty” switch is flipped. And I added this to my FORM tag:

onsubmit="warn_onunload=false;"

Because, remember, if they submit the form, I don’t want to warn them. In this case the unload event is fine.

Then I wrote the actual function that will run when they attempt to navigate away from the page while the form is dirty:

function warn_if_form_dirty()
{
 if(warn_onunload == true && form_dirty == true)
 {
 alert('WARNING: You have chosen to navigate away from this page.  You have UNSAVED CHANGES in this form.  If you want to save these changes, click the Back button on your browser to return to your changes and press the "Save" button.');
 }
}

So, the system works something like this:

  1. User loads the page and starts working. “form_dirty” is false, because no changes have been made. “warn_onunload” is true because we want to warn them.

  2. User changes some form data. When this happens “form_dirty” is now true because they have done some work and are at risk of losing it.

  3. User accidentally hits the Refresh button (stupid user...). The onunload event fires, the “warn_if_form_dirty” function runs. It finds that both “form_dirty” and “warn_onunload” are true, so it pops the warning.

The warning, for its part, basically says, “you may have screwed up, and here’s how to fix it if you want.” Remember that I can’t stop the event. It would be nice if I could, but the potential for abuse is huge, so you can’t. All I can do is tell them what they did, and how to fix it.

The problem: the advice isn’t always true.

It would be nice if you could always hit Back and get back to your data, but this turned out to be a lie. I tried it on a number of machines here in the office, and whether or not this is true depends on the browser and on the cache settings.

It seemed to work on Mozilla and Firefox all the time, but IE was fussy. For some people it worked, but for others, IE pulled the page fresh every time. It didn’t work more often than it did.

So I come away from his experiment thinking that fighting this scenario is a losing battle. If you’re on an intranet, and everyone is using IE with loose security, you could conceivably do some ActiveX mojo to head it off, but that isn’t an option for me.

A possible solution: browser developers should build this functionality into the browser. They should detect whenever a user (not script) has changed form data and warn the user if they try to unload the page. Let the user choose to continue or cancel the unload.

If anyone else has thoughts on theories on this subject, I’d love to hear them.

This is item #318 in a sequence of 357 items.

You can use your left/right arrow keys or swipe left/right to navigate