Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Navigating Away from a Page that has Changes, in ASP.NET

0.00/5 (No votes)
9 May 2008 1  
Notifying a user when leaving a Web page that has modifications
Navigate away from a page with changes.

Introduction

This code enables a Web page to notify users that they are leaving a page that they have made modifications to. Why is this useful? Well, the previous sentence says it all. We want to notify the user that they have made modifications to a page and ask them if they really want to leave the page. It is assumed that you are familiar with JavaScript, DOM Events, and ASP.NET 1.x or higher. The included project is in Visual Studio 2005.

Background

The idea of notifying users that they are leaving a page that has been modified is not new. There are plenty of sites that explain this process via client-scripting of the onbeforeunload body event. This article takes that client-side scripting and ties it into the ASP.NET client-side framework.

Using the Code

The core of this article is quite simple. JavaScript does all the magic. All we need to do is tie this JavaScript magic into the ASP.NET client-side submission model. So, as you can see, in the JavaScript object, MySuperDuper, there is a method called checkForChanges(). This method gets attached when the script loads the onbeforeunload event of the body tag. Why did I call it MySuperDuper? No reason at all. I thought it sounded geeky cool if such a thing exists.

// Register the event.
window.onbeforeunload = function() {
     return MySuperDuper.checkForChanges();
}

Here's the full client-side code:

// This script works in Internet Explorer 6+, FireFox and Safari.
// I believe Opera might handle it too, but I did not test.
var MySuperDuper = new function() {
    // Internal reference to the class
    // to avoid the "this" pointer issue
    // when dealing with events.
    var    var _this = this;

    //you can declare this if you want, but I don't see the point.
    //this.globalChange = undefined;

    // Determines whether or not a form is being saved.
    this.saving;

    // Message to display.
    this.navigateAwayMessage = "You have made some changes which" +
                               " will be lost if you leave this page. " +
                               "Do you want to leave this page?";

    // Verify if any changes were made. If there
    // have been changes and the form is not being saved,
    // alert the user that they are about to leave
    // a page where they have made edits.
    this.checkForChanges = function() {
        if (!_this.saving && typeof(_this.globalChange) !=
                   "undefined" && _this.globalChange)
        {
            if(document.all && event)
                event.returnValue = _this.navigateAwayMessage;
            else
                return _this.navigateAwayMessage;
        }
    }
}

// Register the event.
window.onbeforeunload = function() {
    return MySuperDuper.checkForChanges();
}

Here's the server-side code to incorporate the JavaScript magic. In my project, I put this in a BasePage class so that it can be reused in all pages in which you might want to have this functionality. We could have a boolean property on the base page to turn all this functionality on and off as well. For simplicity's sake, I have left something like that out.

ClientScript.RegisterOnSubmitStatement(typeof(BasePage),
             "saving", "MySuperDuper.saving = true;");

Now for your control, simply update the MySuperDuper.globalChange variable to true. I've used it on a regular HTML text input for simplicity, but you could do this with a server-side control like an <asp:TextBox id="myTextBox" runat="server" /> by adding an attribute in the code file like this:

myTextBox.attributes.Add("onchange", "MySuperDuper.globalChange = true;");

You could also get the ClientID property and render some JavaScript that attaches a DOM event to do this update as well. There's many ways to slice it.

<!--
    We would just need to handle any event for changes in our controls.
    This can be done inline like below or attached. I leave it up to you.
 -->
 <input onchange="MySuperDuper.globalChange = true;" type="text" />

Also, after getting some feedback from crashedapp (see below), he offered his suggestion to check if there have been changes. Thanks for the feedback. So say crashedapp had his own way of checking for changes, he could just override my method MySuperDuper.checkForChanges like this:

function yourCustomFunction()
{
    // ... mind blowing code here
    // return true or false    
}

MySuperDuper.checkForChanges = yourCustomFunction

Points of Interest

It has been tested on Internet Explorer 6+, FireFox, and Safari for Windows. Internet Explorer and FireFox handle navigating away from a page as does Safari, but when you close the browser window and changes have been made, only FireFox and Internet Explorer fire the onbeforeunload event. Safari just closes the page without notifying you. This appears to be how Safari is designed. Also, this doesn't work in Opera (client-side part). I can't remember if it supports onbeforeunload or not. Maybe check out this Web site if you really need to get it working in Opera.

This will also work with AJAX. All that you need to manage is when a partial render has come back to the client, you just need to reset MySuperDuper.globalChange to false. You can do so using the PageRequestManager, Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler) or if you are using a PageMethod or custom AJAX, just add the code to reset MySuperDuper.globalChange. to false. For more information on PageRequestManager, check out this Web site.

History

  • 6th May, 2008: Initial post
  • 7th May, 2008: Article content updated

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here