Thursday, May 1, 2008

Warning the User About Prematurely Leaving a Web Page - Update

My earlier posting illustrated how one can easily trap the beforeunload event and decide whether to display a message to the user that exiting the page without first saving the data will result in all unsaved work being lost.

But then I discovered that it was not working properly on my web page. Whenever any of the command buttons - Add, Delete, Move, and Save - were pressed, beforeunload was fired and I would be warned about leaving the page.
This was most confusing because I knew I wasn't leaving the page! But I intuitively knew that there's always a logical explanation so it was just a matter to find it. As I frequently do, I posted a few messages on the ASP.Net Forums. A very bright developer from Portugal named Luis Abreu responded and provided me some sample code. I ran it and his code ran perfectly. So why on earth was mine not working?

On my page I added a simple button, like Luis had done, to force a partial page postback. Pressing it did NOT force the beforeunload event to fire! WTF?!?

I stared at my web page for some time and suddenly realized what the problem was. Those aforementioned command buttons are not sitting directly on the page but instead reside in a Draggable Panel. Also, the Move button causes a Modal Panel to appear. While both of these panels are technically "on the same page", from the perspective of beforeunload I suppose they are not.

So what to do? I thought about it for a second and realized that with each of these buttons I could use the local 'OnClientClick' event to temporarily disable the beforeunload check. With this goal in mind I added this JavaScript function:

function ToggleBeforeUnload(onOff)
{
if (onOff == true)
{
window.onbeforeunload = ConfirmExit; // Activate beforeunload event handler
}
else
{
window.onbeforeunload = null;
}
}


So now, when any of the buttons are pressed, the first thing that occurs is that the beforeunload handler is turned off. But it had to be reactivated. To accomplish this I added a call to this function at the end of each button's server-side method:

private void ToggleBeforeUnload(bool onOff)
{
ScriptManager.RegisterClientScriptBlock(this, typeof(Page), "toggleBeforeUnload", "ToggleBeforeUnload(" + onOff.ToString().ToLower() + ");", true);
}

It calls the same JavaScript function described earlier. And sure enough, it works perfectly!

Incidentally, blessed is the Internet for helping out developers! I distinctly remember the days when there was no Internet. I'm absolutely convinced that it has dramatically improved the productivity and learning curve of developers around the world.

1 comment: