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:
window.onunload = warn_if_form_dirty;
This means the
warn_if_form_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:
So whenever a form field changes, the “dirty” switch is flipped. And I added this to my FORM tag:
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:
if(warn_onunload == true && form_dirty == true)
So, the system works something like this:
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.
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.
User accidentally hits the Refresh button (stupid user…). The
onunload event fires, the
warn_if_form_dirty function runs. It finds that both
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.