The way I've done this is to use javascript to store the initial values of inputs when the page loads. Then I have a beforeunload handler that checks to see if any of the inputs have a different value than when the page was loaded. If any inputs are changed, it prompts the user to confirm that they want to leave the page, canceling the action if they cancel. In my submit logic, I set a flag that keeps the beforeunload check from happening so a submit doesn't get the prompt.
I suspect there is a jQuery plugin to do this, but I haven't implemented this since I started using jQuery. My earlier code used Prototype.
Edit: Couldn't find a jQuery plugin, but I could have just missed it. Here's a sample of how I might do it. Obviously, there's more that could be done. Note I wasn't able to get it to work with pure jQuery -- not sure exactly why, the popup would appear twice.
This should work with all input elements. You might want to change it to ignore/handle buttons, though. I only adjusted it to ignore a submit button (so it can post back without the popup). If other button types can cause a page unload, you may need to address that.
var CheckOnClose = function() {
this.initialize();
}
CheckOnClose.prototype = {
submitting: false,
initialize: function() {
var that = this;
window.onbeforeunload = function() { return that.checkLeavePage(); }
},
isChanged: function() {
var changed = false;
$('input:not(:submit)').each( function() {
var iv = $(this).data('initialValue');
if ($(this).val() != iv) {
changed = true;
return false;
}
});
return changed;
},
setSubmitting: function() {
this.submitting = true;
},
checkLeavePage: function() {
if (!this.submitting && this.isChanged()) {
return 'You have some unsaved changes.';
}
}
}
var checker = new CheckOnClose();
$(document).ready(function() {
$(':input:not(:submit)').each( function() {
$(this).data('initialValue',$(this).val() );
});
$(':submit').click( function() {
checker.setSubmitting();
});
});