Victor
Victor

Reputation: 297

jQuery autopostback problem

I am working on ASP.NET 3.5 website project and using jQuery to warn users if they modified a page and attempt to leave the page without saving, so doing something like this:

var warning = "Please save changes you made.";
var isDirty = false;

$(document).ready(function()
{

      $('input:text,input:checkbox,input:radio').bind('change', function()
      {

            isDirty = true;

            $('input[type=submit]').bind('click', function(e)
            {

                isDirty = false;
            });

            window.onbeforeunload = function()
            {

                if (isDirty)
                {

                    return warning;
                }
            }
        });
    });

It works fine, but when I make changes on a page and then select a different item in a dropdown on a page, which causes a post back, I get a warning, which I should not.Is it feasible to implement this feature in jQuery, i.e. give warning on really leaving page, but ignoring postbacks, and what changes to the script I need to make in that case?

Ok, I modified script slightly, created a hidden field to save dirty state between postbacks, so it looks like this:

 var warn_on_unload = "Leaving this page will cause any unsaved data to be lost.";
 var previouslyDirty = false;
 var isDirty = false;

 $(window).load(function()
 {

    previouslyDirty = $('#dirtyFlag').val() == '1';

 });

 $(window).unload(function()
 {

        $('#dirtyFlag').val(previouslyDirty ? '1' : '0');
 });

 $(document).ready(function()
 {

        $('input:checkbox,input:radio').one('change', function()
        {

            isDirty = true;

            previouslyDirty = true;

        });



        $('input:text, textarea').keydown(function()

        {

            isDirty = true;

            previouslyDirty = true;

        });

        $('form').submit(function(e)
        {

            isDirty = false;

            previouslyDirty = false;

        });

        $('select').bind('change', function(e)
        {

            isDirty = false;

            previouslyDirty = true;

        });

        window.onbeforeunload = function()
        {

            if (isDirty || previouslyDirty)
            {

                return warn_on_unload;

            }
        }

    });

Still behaves incorrectly after non-submitting postbacks, which it should allow them without a warning, but saving dirty state, so if I change dropdown, no problem on postback , but if I try to leave page after that, should get a warning. Also, need to take of care of submitting postbacks, i.e. saving buttons, obviously allowing them and clearing all dirty flags previously set.

Upvotes: 1

Views: 3826

Answers (3)

Lachlan Roche
Lachlan Roche

Reputation: 25956

Since we already have jQuery, we use it to detect whether the form has changed as show in the accepted answer to this question What is the easiest way to detect if at least one field has been changed on an HTML form?

Additionally, we know that webforms pages only have a single form. Webforms calls form.onsubmit() and form.submit() when handling a postback via a link.

To track the original serialized value across AutoPostBack events, store the serialized form data in a hidden field.

<asp:HiddenField id="serializedForm" runat="server" />

$(document).ready(function(){

    var theform = $('form');
    var serialized = theform.serialize();
    var previous = null;

    // track original serialized across postbacks
    var hidden = $('#<%# serializedForm.ClientID %>');
    if ('' == hidden.val()) {
        serialized = hidden.val();
    } else {
        hidden.val( serialized );
    }

    window.onbeforeunload = function(e) {
        if (serialized != theform.serialize()) {
            return "Are you sure you want to leave the page without saving?";
        }
    }

    // postback -> __doPostBack -> form.onsubmit -> here
    theform.submit(function(){
        // keep in case of validation fail
        previous = serialized;

        // prevent the onbeforeunload prompt
        serialized = theform.serialize();
    });

    // there might be ASP.NET validators
    if (typeof(ValidatorOnSubmit) == "function") {
        var asp_ValidatorOnSubmit = ValidatorOnSubmit;
        ValidatorOnSubmit = function() {
            var result = asp_ValidatorOnSubmit.apply( arguments );
            if (!result) {
                serialized = previous;
            }
            return result;
        }
    }

});

Upvotes: 2

Adhip Gupta
Adhip Gupta

Reputation: 7163

How about something like this?

$(window).unload(function(event)
{
  if (event.target.nodeName != "SELECT" && event.target.nodeName != "INPUT" ) {
    $('#dirtyFlag').val(previouslyDirty ? '1' : '0');
  }
});
​

If this does not work, can you tell me what's the event.target.nodeName called under various circumstances?

Upvotes: 0

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196177

Have you tried catching the submit event of the form ? (not the click of the submit button, but the actual submit)

maybe this would solve it ..

$('form').submit(function(){isDirty = false;});

unless the normal links also submit the form ...

Upvotes: 1

Related Questions