window.onbeforeunload - показывать предупреждение только при отсутствии формы
Я использую window.onbeforeunload, чтобы пользователь не перемещался после изменения значений в форме. Это работает нормально, за исключением того, что оно также показывает предупреждение, когда пользователь отправляет форму (не желателен).
Как я могу это сделать, не показывая предупреждение при отправке формы?
Текущий код:
var formHasChanged = false;
$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) {
formHasChanged = true;
});
$(document).ready(function () {
window.onbeforeunload = function (e) {
if (formHasChanged) {
var message = "You have not saved your changes.", e = e || window.event;
if (e) {
e.returnValue = message;
}
return message;
}
}
});
Ответы
Ответ 1
Использование формы submit для установки флага может сработать для вас.
var formHasChanged = false;
var submitted = false;
$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) {
formHasChanged = true;
});
$(document).ready(function () {
window.onbeforeunload = function (e) {
if (formHasChanged && !submitted) {
var message = "You have not saved your changes.", e = e || window.event;
if (e) {
e.returnValue = message;
}
return message;
}
}
$("form").submit(function() {
submitted = true;
});
});
Ответ 2
вы можете использовать.on() для привязки onbeforeunload и затем использовать.off(), чтобы отвязать его при отправке формы
$(document).ready(function () {
// Warning
$(window).on('beforeunload', function(){
return "Any changes will be lost";
});
// Form Submit
$(document).on("submit", "form", function(event){
// disable warning
$(window).off('beforeunload');
});
}
Ответ 3
Вы можете обработать событие submit(), которое будет происходить только для отправки вашей формы.
В этом случае установите для переменной флага formHasChanged
значение false, чтобы разрешить выгрузку. Кроме того, просто предложение, но поскольку назначение переменной этого флага изменилось, вы можете захотеть переименовать его как "warnBeforeUnload",
$(document).submit(function(){
warnBeforeUnload = false;
});
Ответ 4
Я искал лучшее решение этого. Мы хотим просто исключить один или несколько триггеров из создания нашего "Вы уверены"? диалоговое окно. Поэтому мы не должны создавать все больше и больше обходных решений для все большего количества побочных эффектов. Что делать, если форма отправляется без click
кнопки отправки? Что делать, если наш обработчик isDirty
удаляет статус isDirty
но затем форма-submit блокируется впоследствии? Конечно, мы можем изменить поведение наших триггеров, но правильным местом будет логика обработки диалога. Привязка к форме submit
событие вместо привязки к кнопки отправки click
событие является преимуществом ответов в этой теме выше некоторых других я видел раньше, но это ИМХО просто исправляет неправильный подход.
После некоторого копания в событии события onbeforeunload
я обнаружил свойство .target.activeElement
, которое содержит элемент, который инициировал событие изначально. Итак, yay, это кнопка или ссылка или все, что мы нажали (или вообще ничего, если сам браузер не прошел). Наш "Ты уверен?" диалоговая логика затем сводится к следующим двум компонентам:
-
isDirty
обработка формы:
$('form.pleaseSave').on('change', function() {
$(this).addClass('isDirty');
});
-
"Ты уверен?" диалоговая логика:
$(window).on('beforeunload', function(event) {
// if form is dirty and trigger doesn't have a ignorePleaseSave class
if ($('form.pleaseSave').hasClass('isDirty')
&& !$(event.target.activeElement).hasClass('ignorePleaseSave')) {
return "Are you sure?"
}
// special hint: returning nothing doesn't summon a dialog box
});
Это просто так. Обходных решений не требуется. Просто дайте триггеры (submit и другие кнопки действий) класс ignorePleaseSave
и форму, которую мы хотим получить, чтобы диалог был применен к классу pleaseSave
. Все остальные причины для разгрузки страницы вызывают наш "Ты уверен?" Диалог.
PS Я использую jQuery здесь, но я думаю, что свойство .target.activeElement
также доступно в обычном JavaScript.