Как показать «Вы уверены, что хотите уйти с этой страницы?» когда изменения совершены?

267

Здесь, в stackoverflow, если вы начали вносить изменения, то вы пытаетесь отойти от страницы, появляется кнопка подтверждения javascript и спрашивает: «Вы уверены, что хотите отойти от этой страницы?» бле бла бло ...

Кто-нибудь реализовывал это раньше, как я могу отследить, что изменения были зафиксированы? Я полагаю, что мог бы сделать это сам, я пытаюсь изучить хорошие практики у вас, экспертов.

Я попробовал следующее, но все еще не работает:

<html>
<body>
    <p>Close the page to trigger the onunload event.</p>
    <script type="text/javascript">
        var changes = false;        
        window.onbeforeunload = function() {
            if (changes)
            {
                var message = "Are you sure you want to navigate away from this page?\n\nYou have started writing or editing a post.\n\nPress OK to continue or Cancel to stay on the current page.";
                if (confirm(message)) return true;
                else return false;
            }
        }
    </script>

    <input type='text' onchange='changes=true;'> </input>
</body>
</html>

Кто-нибудь может опубликовать пример?

Шимми Вайцхандлер
источник
3
Чтобы ваш пример работал, измените функцию на: myFunction () {window.onbeforeunload = "message"; } затем измените ввод: <input type = 'text' onchange = 'myFunction ();'> </ input>
Кейт,
Связанный: stackoverflow.com/q/821011/435605
АликЭльзин-килака

Ответы:

367

Обновление (2017)

Современные браузеры теперь рассматривают отображение собственного сообщения как угрозу безопасности, и поэтому оно было удалено из всех. Браузеры теперь отображают только общие сообщения. Поскольку нам больше не нужно беспокоиться об установке сообщения, это так просто:

// Enable navigation prompt
window.onbeforeunload = function() {
    return true;
};
// Remove navigation prompt
window.onbeforeunload = null;

Читайте ниже для поддержки устаревшего браузера.

Обновление (2013)

Оригинальный ответ подходит для IE6-8 и FX1-3.5 (к чему мы стремились в 2009 году, когда он был написан), но сейчас он устарел и не будет работать в большинстве современных браузеров - я оставил это ниже для справки.

window.onbeforeunloadНе рассматривается последовательно всеми браузерами. Это должна быть ссылка на функцию, а не строка (как указывалось в исходном ответе), но она будет работать в старых браузерах, потому что проверка для большинства из них заключается в том, назначено ли что-либо onbeforeunload(включая функцию, которая возвращает null).

Вы устанавливаете window.onbeforeunloadссылку на функцию, но в старых браузерах вы должны установить returnValueсобытие вместо того, чтобы просто возвращать строку:

var confirmOnPageExit = function (e) 
{
    // If we haven't been passed the event get the window.event
    e = e || window.event;

    var message = 'Any text will block the navigation and display a prompt';

    // For IE6-8 and Firefox prior to version 4
    if (e) 
    {
        e.returnValue = message;
    }

    // For Chrome, Safari, IE8+ and Opera 12+
    return message;
};

Вы не можете сделать это, чтобы confirmOnPageExitсделать проверку и вернуть ноль, если вы хотите, чтобы пользователь продолжил без сообщения. Вам все еще нужно удалить событие, чтобы надежно включить и выключить его:

// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;

// Turn it off - remove the function entirely
window.onbeforeunload = null;

Оригинальный ответ (работал в 2009 году)

Включить это:

window.onbeforeunload = "Are you sure you want to leave?";

Чтобы выключить это:

window.onbeforeunload = null;

Имейте в виду, что это ненормальное событие - вы не можете связать его стандартным способом.

Чтобы проверить значения? Это зависит от вашей структуры проверки.

В jQuery это может быть что-то вроде (очень простой пример):

$('input').change(function() {
    if( $(this).val() != "" )
        window.onbeforeunload = "Are you sure you want to leave?";
});
Кит
источник
4
Это было бы что-то вроде: $ ('input: text'). Change (function () {window.onbeforeunload = $ ('input: text [value! = ""]'). Length> 0? "Warning": null ;});
Кит
1
Для простой проверки, или вы можете добавить более сложную проверку для каждого изменения
Кит
1
Стоит отметить, что метод returnValue - единственный метод, указанный в стандарте, поэтому он предназначен не только для IE6-8, но и для всех совместимых со стандартами браузеров (в данном случае, за исключением Chrome, Safari и Opera).
rmcclellan
3
Чтобы остановить оповещение при отправке формы, я использовал $("#submit_button").click(function() { window.onbeforeunload = null; });. Первоначально я использовал событие onclick для кнопки, но, несмотря на то, что он не был так хорош, он также не работал с IE8.
Энди Беверли,
1
@ AlikElzin-килака, ты не можешь. Если вы хотите изменить всплывающий текст, вам нужно создать собственное всплывающее окно, но это не может блокировать window.onbeforeunloadсобытие.
Кит
38

onbeforeunloadMicrosoft-изма ближе всего мы должны стандартное решение, но имейте в виду , что поддержка браузера неравномерно; например, для Opera он работает только в версии 12 и более поздних (все еще в бета-версии на момент написания статьи).

Кроме того, для максимальной совместимости вам нужно сделать больше, чем просто вернуть строку, как описано в Mozilla Developer Network .

Пример. Определите следующие две функции для включения / отключения подсказки навигации (см. Пример MDN):

function enableBeforeUnload() {
    window.onbeforeunload = function (e) {
        return "Discard changes?";
    };
}
function disableBeforeUnload() {
    window.onbeforeunload = null;
}

Затем определите форму следующим образом:

<form method="POST" action="" onsubmit="disableBeforeUnload();">
    <textarea name="text"
              onchange="enableBeforeUnload();"
              onkeyup="enableBeforeUnload();">
    </textarea>
    <button type="submit">Save</button>
</form>

Таким образом, пользователь будет предупрежден о выходе из системы только в том случае, если он изменил текстовую область, и не будет запрашиваться при фактической отправке формы.

Сёрен Лёвборг
источник
1
Основанные на сайте Mozill, последние браузеры для настольных компьютеров теперь поддерживают его: developer.mozilla.org/en/DOM/window.onbeforeunload
Hengjie
Microsoft-изм это отличный термин.
Люк Тейлор
18

С JQuery это легко сделать. Так как вы можете привязать к наборам.

Этого недостаточно, чтобы выполнить onbeforeunload, вы хотите запускать навигацию, только если кто-то начал редактировать материал.

Сэм Шафран
источник
2
Кажется, не может попасть в сообщения в блоге @jonstjohn. Может быть, он будет приятелем и укажет нам правильное направление? : D
FLGMwt
14
=> 500 Внутренняя ошибка. Вот почему ссылки устарели на SO. Понижено, пока не исправлено.
Loïc
Эта веб-страница недоступна
Mateusz
2
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится.
августа
2
Оригинальная ссылка от Jon St John был сломан, поэтому я обновил его на Вайбак Machine вариант. Содержание ссылки можно найти скопированным на многих других сайтах, но я думаю, что было бы лучше "сохранить" тот, который добавил Сэм
Альваро Монторо
14

jquerys 'beforeunload' отлично работал для меня

$(window).bind('beforeunload', function(){
    if( $('input').val() !== '' ){
        return "It looks like you have input you haven't submitted."
    }
});
Девон Петиколас
источник
Привязка устарела, и в этом ответе можно увидеть более новую версию кода, подобную этой: stackoverflow.com/a/1889450/908677
Элайджа Лофгрен,
12

для новых людей, которые ищут простое решение, просто попробуйте Areyousure.js

lawphotog
источник
11

Это простой способ представить сообщение, если в форму введены какие-либо данные, и не показывать сообщение, если форма отправлена:

$(function () {
    $("input, textarea, select").on("input change", function() {
        window.onbeforeunload = window.onbeforeunload || function (e) {
            return "You have unsaved changes.  Do you want to leave this page and lose your changes?";
        };
    });
    $("form").on("submit", function() {
        window.onbeforeunload = null;
    });
})
Карл Дж
источник
8

Чтобы расширить на уже удивительный ответ Кита :

Пользовательские предупреждающие сообщения

Чтобы разрешить настраиваемые предупреждающие сообщения, вы можете заключить их в функцию, подобную этой:

function preventNavigation(message) {
    var confirmOnPageExit = function (e) {
        // If we haven't been passed the event get the window.event
        e = e || window.event;

        // For IE6-8 and Firefox prior to version 4
        if (e)
        {
            e.returnValue = message;
        }

        // For Chrome, Safari, IE8+ and Opera 12+
        return message;
    };
    window.onbeforeunload = confirmOnPageExit;
}

Затем просто вызовите эту функцию с вашим собственным сообщением:

preventNavigation("Baby, please don't go!!!");

Снова включить навигацию

Чтобы повторно включить навигацию, все , что вам нужно сделать , это установить window.onbeforeunloadв null. Вот она, заключенная в аккуратную маленькую функцию, которую можно вызывать где угодно:

function enableNavigation() {
    window.onbeforeunload = null;
}

Использование jQuery для привязки этого к элементам формы

При использовании jQuery это может быть легко привязано ко всем элементам формы следующим образом:

$("#yourForm :input").change(function() {
    preventNavigation("You have not saved the form. Any \
        changes will be lost if you leave this page.");
});

Затем, чтобы разрешить отправку формы:

$("#yourForm").on("submit", function(event) {
    enableNavigation();
});

Динамически модифицированные формы:

preventNavigation()и enableNavigation()может быть привязан к любым другим функциям при необходимости, например, к динамическому изменению формы или к нажатию кнопки, которая отправляет запрос AJAX. Я сделал это, добавив скрытый элемент ввода в форму:

<input id="dummy_input" type="hidden" />

Затем в любое время, когда я хочу запретить пользователю переходить, я запускаю изменения на этом входе, чтобы убедиться, что он preventNavigation()выполняется:

function somethingThatModifiesAFormDynamically() {

    // Do something that modifies a form

    // ...
    $("#dummy_input").trigger("change");
    // ...
}
Майк
источник
3

Вот попробуй это работает 100%

<html>
<body>
<script>
var warning = true;
window.onbeforeunload = function() {  
  if (warning) {  
    return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";  
    }  
}

$('form').submit(function() {
   window.onbeforeunload = null;
});
</script>
</body>
</html>
Брейдон
источник
3

В стандартных состояниях , что побуждение можно управлять путем отмены beforeunload события или установив возвращаемое значение значения ненулевого . В нем также говорится, что авторы должны использовать Event.preventDefault () вместо returnValue, и сообщение, отображаемое пользователю , не настраивается .

По состоянию на 69.0.3497.92 Chrome не соответствовал стандарту. Тем не менее, имеется отчет об ошибке , и проверка еще не завершена. Chrome требует, чтобы returnValue устанавливалось путем ссылки на объект события, а не на значение, возвращаемое обработчиком.

Автор несет ответственность за отслеживание внесения изменений; это можно сделать с помощью переменной или путем обеспечения того, что событие обрабатывается только при необходимости.

window.addEventListener('beforeunload', function (e) {
    // Cancel the event as stated by the standard.
    e.preventDefault();
    // Chrome requires returnValue to be set.
    e.returnValue = '';
});
    
window.location = 'about:blank';

Тревор Карджанис
источник
2

Когда пользователь начинает вносить изменения в форму, устанавливается логический флаг. Если пользователь затем пытается отойти от страницы, вы проверяете этот флаг в событии window.onunload . Если флаг установлен, вы показываете сообщение, возвращая его в виде строки. При возврате сообщения в виде строки появится диалоговое окно подтверждения, содержащее ваше сообщение.

Если вы используете ajax для фиксации изменений, вы можете установить флаг falseпосле того, как изменения были зафиксированы (т.е. в событии успеха ajax).

Киртан
источник
1

Вы можете добавить onchangeсобытие в текстовое поле (или любые другие поля), которое устанавливает переменную в JS. Когда пользователь пытается закрыть страницу (window.onunload), вы проверяете значение этой переменной и соответственно выводите предупреждение.

Макрам Салех
источник
1
Вы не можете сделать это - alertи confirmзаблокированы во время window.onbeforeunloadи window.onunload(по крайней мере, в версии Chrome на моем ПК, но, вероятно, также в каждом браузере, который когда-либо поддерживал эти обработчики).
Марк Амери
1

Основываясь на всех ответах в этой теме, я написал следующий код, и он работал для меня.

Если у вас есть только некоторые теги input / textarea, требующие проверки события onunload, вы можете назначить атрибуты данных HTML5 как data-onunload="true"

например,

<input type="text" data-onunload="true" />
<textarea data-onunload="true"></textarea>

и Javascript (jQuery) может выглядеть так:

$(document).ready(function(){
    window.onbeforeunload = function(e) {
        var returnFlag = false;
        $('textarea, input').each(function(){
            if($(this).attr('data-onunload') == 'true' && $(this).val() != '')
                returnFlag = true;
        });

        if(returnFlag)
            return "Sure you want to leave?";   
    };
});
Сагар Гала
источник
2
См. Также «По некоторым причинам браузеры на основе Webkit не следуют спецификации для диалогового окна» в документации до загрузки MDN .
Арджан
1

вот мой HTML

<!DOCTYPE HMTL>
<meta charset="UTF-8">
<html>
<head>
<title>Home</title>
<script type="text/javascript" src="script.js"></script>
</head>

 <body onload="myFunction()">
    <h1 id="belong">
        Welcome To My Home
    </h1>
    <p>
        <a id="replaceME" onclick="myFunction2(event)" href="https://www.ccis.edu">I am a student at Columbia College of Missouri.</a>
    </p>
</body>

И вот как я сделал нечто подобное в javaScript

var myGlobalNameHolder ="";

function myFunction(){
var myString = prompt("Enter a name", "Name Goes Here");
    myGlobalNameHolder = myString;
    if (myString != null) {
        document.getElementById("replaceME").innerHTML =
        "Hello " + myString + ". Welcome to my site";

        document.getElementById("belong").innerHTML =
        "A place you belong";
    }   
}

// create a function to pass our event too
function myFunction2(event) {   
// variable to make our event short and sweet
var x=window.onbeforeunload;
// logic to make the confirm and alert boxes
if (confirm("Are you sure you want to leave my page?") == true) {
    x = alert("Thank you " + myGlobalNameHolder + " for visiting!");
}
}
Джастин Стоун
источник
0

Это легко сделать, установив для ChangeFlag значение true для события onChange TextArea . Используйте JavaScript, чтобы показать диалоговое окно подтверждения на основе значения ChangeFlag . Откажитесь от формы и перейдите на запрашиваемую страницу, если подтвердите, вернет true, иначе ничего не делать .

simplyharsh
источник
-1

Для тега body есть параметр «onunload», из которого можно вызывать функции javascript. Если он возвращает false, он предотвращает навигацию.

stribika
источник
13
К счастью, это на самом деле не работает. В противном случае я бы не хотел посещать страницу, содержащую <body onunload="return false;">.
Сорен Левборг