Activating OnBeforeUnload ONLY when field values have changed

22,113

Solution 1

I had a similar requirement so came up with following jQuery script:

$(document).ready(function() {
    needToConfirm = false; 
    window.onbeforeunload = askConfirm;
});

function askConfirm() {
    if (needToConfirm) {
        // Put your custom message here 
        return "Your unsaved data will be lost."; 
    }
}

$("select,input,textarea").change(function() {
    needToConfirm = true;
});

The above code checks the needToConfirm variable, if its true then it will display warning message. Whenever input, select or textarea elements value is changed, needToConfirm variable is set to true.


PS: Firefox > 4 don't allow custom message for onbeforeunload.
Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=588292


UPDATE: If you are a performance freak, you will love @KyleMit's suggestion. He wrote a jQuery extension only() which will be executed only once for any element.

$.fn.only = function (events, callback) {
    //The handler is executed at most once for all elements for all event types.
    var $this = $(this).on(events, myCallback);
    function myCallback(e) {
        $this.off(events, myCallback);
        callback.call(this, e);
    }
    return this
};    

$(":input").only('change', function() {
    needToConfirm = true;
});

Solution 2

The following works well in jQuery:

var needToConfirm = false;

$("input,textarea").on("input", function() {
  needToConfirm = true;
});

$("select").change(function() {
  needToConfirm = true;
});

window.onbeforeunload = function(){        
  if(needToConfirm) {
    return "If you exit this page, your unsaved changes will be lost.";        
  }
}   

And if the user is submitting a form to save the changes, you might want to add this (change #mainForm to the ID of the form they're submitting):

$("#mainForm").submit(function() {
  needToConfirm = false;
});

Solution 3

We just use Window.onbeforeunload as our "changed" flag. Here's what we're doing, (using lowpro):

Event.addBehavior({
  "input[type=radio]:change,input[type=text]:change,input[type=checkbox]:change,select:change": function(ev) {
       window.onbeforeunload = confirmLeave;
  }
  ".button.submit-button:click": function(ev) {
       window.onbeforeunload = null;
  },
});


function confirmLeave(){
    return "Changes to this form have not been saved. If you leave, your changes will be lost."  
}

Solution 4

$(window).bind('beforeunload',function() {
 return "'Are you sure you want to leave the page. All data will be lost!";
});

$('#a_exit').live('click',function() {
    $(window).unbind('beforeunload');
});

Above works For me.

Solution 5

Try your logic in a different manner. Meaning, put the logic for checking the value of the input field in your onbeforeunload method.

window.onbeforeunload = function () { 
    if ($("#is_modified").val() == 'true') { 
        return "You have unsaved changes."; 
    } else { 
        return true; // I think true is the proper value here 
    } 
};
Share:
22,113

Related videos on Youtube

miCRoSCoPiC_eaRthLinG
Author by

miCRoSCoPiC_eaRthLinG

A raver at heart - the only way I can aptly describe me is a bouncing ball of sheer energy. Blame it all on my air sign - but I find it extremely difficult to affix myself a certain spot (apart from when I'm sitting in with my hi-tech paraphernalia) . Traveling's foremost on my itinerary. Photography comes only second to that.. and of course there's my computer - which is the very essential elixir of life for me & deserves a special mention. My free time's spent in mastering the art of spinning Fire-Pois as well as having fun with my other trip toys. If you've no clue as to what Pois are, check out this site: http://www.homeofpoi.com/ The roar of blazing fire rushing past your ears gives you the most natural high ever. Apart from that Meditation helps me a lot in the course of daily life. I envision myself retiring to a li'l recluse on some secluded white-sanded island surrounded by azure waters - someday in not-too-far future.. and rave like a mad cow till my last breath... ;)

Updated on July 09, 2022

Comments

  • miCRoSCoPiC_eaRthLinG
    miCRoSCoPiC_eaRthLinG almost 2 years

    What I'm trying to achieve is to Warn the user of unsaved changes if he/she tries to close a page or navigate away from it without saving first.

    I've managed to get the OnBeforeUnload() dialog to pop-up... but I don't want it to be displayed at all if the user hasn't modified any field values. For this, I'm using this hidden input field called is_modified that starts with a default value of false and flips to true when any field is edited.

    I tried to bind the change event to this is_modified field to try and detect for value change... and only then activate OnBeforeUnload.

    $( '#is_modified' ).change( function() {
        if( $( '#is_modified' ).val() == 'true' )
            window.onbeforeunload = function() { return "You have unsaved changes."; }
    });
    

    But from what I figure is that the change() event works only after these 3 steps - a field receives focus, a value is changed and the field looses focus. In case of the hidden input field, I'm not sure how this receiving and loosing focus part works! Hence, the onbeforeunload function is never being activated.

    Can anyone suggest a way to maintain a trigger over is_modified?

    Thanks.

  • orion
    orion almost 15 years
    "true" is not the proper value. In some browsers (At least Firefox, perhaps more) returning "null" will cancel the dialog. Howerver, in IE, I could not find a way to cancel the dialog from within the handler. The only thing that worked for me was to remove the handler entirely beforehand (ie, "window.beforeunload = null"), as in Bryan Larsen's answer.
  • Jordan S. Jones
    Jordan S. Jones almost 15 years
    Fair enough. Sadly, I didn't thoroughly test my solution before I answered. :(
  • Idris Mokhtarzada
    Idris Mokhtarzada over 13 years
    Apparently setting onbeforeunload=null fails in IE: bustedmug.blogspot.com/2007/01/…
  • Bryan Larsen
    Bryan Larsen about 13 years
    It seems this is an IE7-only bug -- it works fine in IE8, which is all I have to support, luckily!
  • Jonathan Kuhn
    Jonathan Kuhn about 13 years
    I know I'm a little late to the party, but I was just running into this. However in IE if the function returns undefined (or doesn't return anything), the dialog doesn't show (this also works in FF). I tried returning true/false/null and IE would just put "true"/"false"/"null" as the text in the dialog. No idea why. Hope this helps someone else.
  • marianobianchi
    marianobianchi almost 11 years
    It works like a charm. But there is a little problem: I can't get the message changed. I would like to write my own message like: "Are you crazy you want to go away?" but i couldn't get it to work...
  • marianobianchi
    marianobianchi almost 11 years
    Thanks for your answer, but i found that the problem was another. I'm using firefox and there is a feature that don't let change this message. I try it in chrome and it worked, but it won't work in firefox...
  • Ajinkya
    Ajinkya almost 11 years
    @marianobianchi Yes after FIrefox 4 custom message is not allowed for onbeforeunload bugzilla.mozilla.org/show_bug.cgi?id=588292. Will update my answer accordingly
  • KyleMit
    KyleMit over 9 years
    Couple Suggestions: You could simplify the change selector by using jQuery's ":input" selector. Also, you don't need to keep listening to and firing change events after the first event sets needToConfirm to true. .change() is just shorthand for .on('change'). Instead of on, you can use .one('change') so the event doesn't need to keep firing for subsequent changes.
  • Ajinkya
    Ajinkya over 9 years
    @KyleMit Yup. Good suggestions. Will update my answer
  • KyleMit
    KyleMit over 9 years
    While we're at it, if you're amenable to adding extension methods, I wrote a 5 line extension method called .only() that will only fire a single time as soon as it's called on any element. Whereas one "is executed at most once per element per event type." It's a little more code, but it's handy, cleaner, and less work to process. If you have a form with a lot of different fields that will keep firing, it could be helpful. Here's a demo in fiddle
  • Oscar Pérez
    Oscar Pérez over 8 years
    I confirm @JonathanKuhn comment on Safari 8.0.7
  • Darko
    Darko over 2 years
    This code worked for me, I just change last part so I dont need to write everitime diferent Id of #mainForm ` // Form Submit to not show warnings jQuery(document).on("submit", "form", function (event) { // disable warning needToConfirm = false; });`