Остановить загрузку страницы в обработчике события beforeunload
Перед тем, как пользователь переходит на страницу, код проверяет, редактировал ли он некоторые поля формы. Если он это сделал, я отображаю модальное окно с Yes
а также No
кнопок. Если он нажимает нет, модал должен закрыться, и пользователь остается в этом окне. Если да - сохранить изменения и выгрузить.
$(window).bind('beforeunload', function(){
// check if any field is dirty
if ($('div.form').dirtyForms('isDirty')) {
var modalParams = {
Content: 'You have some unsaved changes, proceed?'
OnSave: navigateAndSave,
OnCancel: cancelNavigate
}
ShowModal(modalParams);
}
})
function navigateAndSave() {
// Do stuff
};
function cancelNavigate() {
// Stop page from unloading and close the modal
};
Так что я могу сделать в cancelNavigate
остановить страницу от выгрузки?
3 ответа
Это возможно, но только если пользователь нажимает гиперссылку на странице. Если пользователь использует браузер для перехода от страницы, он получит диалоговое окно браузера по умолчанию, которое не имеет возможности сохранить.
Dirty Forms автоматически присоединяет (и удаляет обработчик) к beforeunload
событие, так что ваша попытка создать другой обработчик события, скорее всего, потерпит неудачу. Вы никогда не должны делать это при использовании грязных форм.
Вы не упомянули, какую модальную диалоговую среду вы хотели бы использовать, поэтому я просто покажу пример использования диалогового окна jQuery UI. Интеграция других диалоговых рамок аналогична. Для этого вы можете проверить исходный код существующих предварительно созданных диалогов.
Кроме того, ваш вариант использования немного ограничен. Что делать, если пользователь хочет отойти и игнорировать изменения? Я добавил пример, который включает дополнительную опцию, чтобы сделать это.
<html>
<head>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.ui/1.11.3/jquery-ui.min.css" />
</head>
<body>
<script type="text/javascript" src="//cdn.jsdelivr.net/g/jquery@1.11.3,jquery.ui@1.11.3,jquery.dirtyforms@2.0.0"></script>
<script type="text/javascript">
$(document).ready(function() {
// This is required by jQuery UI dialog
$('body').append('<div id="dirty-dialog" style="display:none;" />');
// This must be called before the first call to .dirtyForms
$(document).bind('bind.dirtyforms', function (ev, events) {
var originalOnRefireClick = events.onRefireClick;
events.onRefireClick = function (ev) {
if (saveForm) {
// TODO: Replace this with your AJAX function
// to save the form.
alert('saving form...');
}
originalOnRefireClick(ev);
};
});
// Flag indicating whether or not to save the form on close.
var saveForm = false;
$('.mainForm').dirtyForms({
dialog: {
// Custom properties to allow overriding later using
// the syntax $.DirtyForms.dialog.title = 'custom title';
title: 'Are you sure you want to do that?',
proceedAndSaveButtonText: 'Save Changes & Continue',
proceedAndCancelButtonText: 'Cancel Changes & Continue',
stayButtonText: 'Stay Here',
preMessageText: '<span class="ui-icon ui-icon-alert" style="float:left; margin:2px 7px 25px 0;"></span>',
postMessageText: '',
width: 650,
// Dirty Forms Methods
open: function (choice, message) {
$('#dirty-dialog').dialog({
open: function () {
// Set the focus on close button. This takes care of the
// default action by the Enter key, ensuring a stay choice
// is made by default.
$(this).parents('.ui-dialog')
.find('.ui-dialog-buttonpane button:eq(2)')
.focus();
},
// Whenever the dialog closes, we commit the choice
close: choice.commit,
title: this.title,
width: this.width,
modal: true,
buttons: [
{
text: this.proceedAndSaveButtonText,
click: function () {
// Indicate the choice is the proceed action
choice.proceed = true;
// Pass a custom flag to indicate to save the data first
// in the onRefireClick event
saveForm = true;
$(this).dialog('close');
}
},
{
text: this.proceedAndCancelButtonText,
click: function () {
// Indicate the choice is the proceed action
choice.proceed = true;
// Pass a custom flag to indicate not to save the data
// in the onRefireClick event
saveForm = false;
$(this).dialog('close');
}
},
{
text: this.stayButtonText,
click: function () {
// We don't need to take any action here because
// this will fire the close event handler and
// commit the choice (stay) for us automatically.
$(this).dialog('close');
}
}
]
});
// Inject the content of the dialog using jQuery .html() method.
$('#dirty-dialog').html(this.preMessageText + message + this.postMessageText);
},
close: function () {
// This is called by Dirty Forms when the
// Escape key is pressed, so we will close
// the dialog manually. This overrides the default
// Escape key behavior of jQuery UI, which would
// ordinarily not fire the close: event handler
// declared above.
$('#dirty-dialog').dialog('close');
}
}
});
});
</script>
Change one of the fields below, then click "Go to Google" to try to navigate away.
<form class="mainForm" action="jqueryui.html">
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="submit" value="Submit">
</form>
<a href="http://www.google.com/">Go to Google</a>
</body>
</html>
В примере используется привязка настраиваемого события для присоединения к onRefireClick
обработчик события, который запускается, когда choice.proceed = true
, но не когда это false
,
Это невозможно.
Вы можете показать текстовое сообщение вместе с возможностью продолжить на странице или уйти.
Пожалуйста, смотрите эту ссылку для получения дополнительной информации: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
window.onbeforeunload = funcRef
funcRef
является ссылкой на функцию или выражение функции.- Функция должна присвоить строковое значение
returnValue
собственностьEvent
объект и вернуть ту же строку.Пример:
window.onbeforeunload = function(e) { return 'Dialog text here.'; };
После того, как пользователь решит остаться на странице, вы можете показать свой модал, но я думаю, что это предложение будет побеждено в то время.
Как утверждают другие, вы можете перехватить навигацию, прослушивая щелчки и ключевые события в ссылках и формах на вашей странице, но это не позволит вам показывать какие-либо диалоги, когда пользователь пытается ввести URL-адрес вручную, закрыть вкладку, закрыть нажмите кнопку перезагрузки, назад или вперед и т. д.
beforeunload
Событие предназначено для защиты пользователей от вредоносных скриптов.
Если это разрешено, кто-то может заблокировать ваш браузер на нужной странице, не позволяя вам перемещаться или закрывать окно.
Редактировать.:
Мне удалось показать диалоговое окно подтверждения, которое работает почти так же, как вы хотите, прикрепив к 2 событиям beforeunload
а также unload
, Он работает в Internet Explorer 11, Firefox 40 и Safari 5.1 для Windows (что я могу подтвердить прямо сейчас):
var alreadyTriggered = false;
function onQuit() {
if (alreadyTriggered) return true;
alreadyTriggered = true;
if (confirm('Sure?')) {
alert('OK');
} else {
alert('Cancel');
}
}
window.onbeforeunload = onQuit;
window.onunload = onQuit;
You can <a href="javascript: location.reload();">reload the page</a> to test it here.
Это зависит от разрыва в цикле событий JS, вызванного диалоговым окном подтверждения, и невозможно выполнить эту работу с пользовательскими диалоговыми окнами, поскольку страница изменится или закроется, прежде чем пользователи получат возможность взаимодействовать с ней.
По-прежнему нет способа избежать изменения или закрытия страницы, а также способа заставить это работать в Chrome. Это также не будет работать в Firefox, если событие не было вызвано взаимодействием с пользователем.
Я полагаю, что вам просто нужно вызвать предотвратительный дефолт по событию.
$(window).bind('beforeunload', function(e){
// check if any field is dirty
if ($('div.form').dirtyForms('isDirty')) {
var modalParams = {
Content: 'You have some unsaved changes, proceed?'
OnSave: navigateAndSave,
OnCancel: e.preventDefault();
}
ShowModal(modalParams);
}
})
function navigateAndSave() {
// Do stuff
};