I am coding a form and I need a function like stackoverflow have: \"You have started writing or editing a post.\".
I\'ve looked through the code of stackoverflow to
I made a general function for this based on Wasim's excellent answer:
var confirm_nav_ignore = [];
function confirm_nav() {
function save_form_state($form) {
var old_state = $form.serialize();
$form.data('old_state', old_state);
}
// On load, save form current state
$('form').each(function() {
save_form_state($(this));
});
// On submit, save form current state
$('form').submit(function() {
save_form_state($(this));
});
// strip fields that we should ignore
function strip(form_data) {
for (var i=0; i<confirm_nav_ignore.length; i++) {
var field = confirm_nav_ignore[i];
form_data = form_data.replace(new RegExp("\\b"+field+"=[^&]*"), '');
}
return form_data;
}
// Before unload, confirm navigation if any field has been edited
$(window).on('beforeunload', function(e) {
var rv;
$('form').each(function() {
var $form = $(this);
var old_state = strip($form.data('old_state'));
var new_state = strip($form.serialize());
if (new_state != old_state) {
rv = '';
}
});
return rv;
});
}
// I call it at the end of the on-load handler:
$(function() {
confirm_nav();
});
Changes:
It might look over-engineered, but that's what I had to do to make it work correctly in a real web app.
Thanks to Wasim, for the great idea to use JQuery $(form).serialize().
This is how in JQuery
$('#form').data('serialize',$('#form').serialize());
// On load save form current state
$(window).bind('beforeunload', function(e){
if($('#form').serialize()!=$('#form').data('serialize'))return true;
else e=null;
// i.e; if form state change show box not.
});
You can Google JQuery Form Serialize function, this will collect all form inputs and save it in array. I guess this explain is enough :)
You can do this using window.onbeforeunload like this:
window.onbeforeunload = function() {
return 'Are you sure you want to navigate away from this page?';
};
So in your code, you would put that inside the success
callback of your $.ajax
call.
To unset the confirmation, you can do this:
window.onbeforeunload = null;
Also, see this answer: How can I override the OnBeforeUnload dialog and replace it with my own?
small optimization of excellent Sam's answer:
var confirm_nav_ignore = [];
function confirm_nav() {
var $forms = $('form'); // if you need it add .filter('#your_form_id');
function save_form_state() {
var $form = $(this),
old_state = $form.serialize();
$form.data('old_state', old_state);
}
$forms
// On load, save form current state
.each(save_form_state)
// On submit, save form current state
.submit(save_form_state)
;
// strip fields that we should ignore
function strip(form_data) {
for (var i = 0; i < confirm_nav_ignore.length; i++) {
var field = confirm_nav_ignore[i];
form_data = form_data.replace(new RegExp("\\b" + field + "=[^&]*"), '');
}
return form_data;
}
// Before unload, confirm navigation if any field has been edited
$(window).on('beforeunload', function(e) {
var rv = undefined;
$forms.each(function() {
var $form = $(this);
var old_state = strip($form.data('old_state'));
var new_state = strip($form.serialize());
if (new_state !== old_state) {
e.preventDefault();
rv = '';
}
});
return rv;
});
}
// I call it at the end of the on-load handler:
$(confirm_nav);
tested on last chrome, firefox and safari
Based on Wasim A. answer. That code snipped looks great, but if I clicked to submit button I have an notification too. I think this is better:
$(document).ready(function() {
let form = $('#form');
form.data('serialize', form.serialize());
// if submit clicked - pass user to save form
form.find('submit').on('click', function () {
$(window).off('beforeunload');
});
});
// On load save form current state
$(window).bind('beforeunload', function(e){
let form = $('#form');
if(form.serialize() !== form.data('serialize')) {
return true;
} else {
// i.e; if form state change show box not.
e=null;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>