Запретить переход с веб-страницы с помощью JavaScript

129

Как предотвратить переход с веб-страницы с помощью JavaScript?

Энтузиаст программного обеспечения
источник
Что заставляет эту страницу уйти?
Нияз
9
Согласно вопросу, JavaScript заставляет его уйти ...
Shog9,
@ Shog9 это могло быть закрытие вкладки заставляет его уйти. Мой указательный палец сделал это ...
Боб Штайн

Ответы:

159

Использование onunloadпозволяет отображать сообщения, но не прерывает навигацию (потому что уже слишком поздно). Однако использование onbeforeunloadприведет к прерыванию навигации:

window.onbeforeunload = function() {
  return "";
}

Примечание. Возвращается пустая строка, поскольку новые браузеры предоставляют сообщение типа «Любые несохраненные изменения будут потеряны», которое нельзя изменить.

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

window.onbeforeunload = function() {
  return "Are you sure you want to navigate away?";
}
Джимми Р. Хаутс
источник
11
Браузер отобразит соответствующее приглашение. Просто используйтеwindow.onbeforeunload = function() { return ""; }
КИМ Тэгён
Но этого мало. А как насчет элементов управления внутри формы? Они тоже запускают это.
Fandango68
1
Современные браузеры не позволяют отображать настраиваемое сообщение в командной строке, так как этим злоупотребляли фишеры и т.п.
Flimm 03
Спасибо @Flimm, я обновил ответ, теперь он актуален для текущих браузеров.
Джимми Р.
@Flimm Я хочу обновить онлайн-статус пользователя, когда онлайн-пользователи закрывают вкладку или браузер. Я использовал код в решении, но он не сработал. Есть ли решение для этого?
Насимба,
23

В отличие от других методов, представленных здесь, этот фрагмент кода не заставит браузер отображать предупреждение, спрашивающее пользователя, хочет ли он уйти; вместо этого он использует четную природу DOM для перенаправления обратно на текущую страницу (и, таким образом, отмены навигации), прежде чем браузер получит возможность выгрузить ее из памяти.

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

(function () {
    var location = window.document.location;

    var preventNavigation = function () {
        var originalHashValue = location.hash;

        window.setTimeout(function () {
            location.hash = 'preventNavigation' + ~~ (9999 * Math.random());
            location.hash = originalHashValue;
        }, 0);
    };

    window.addEventListener('beforeunload', preventNavigation, false);
    window.addEventListener('unload', preventNavigation, false);
})();

Отказ от ответственности: вы никогда не должны этого делать. Если на странице есть код блокировки фреймов, пожалуйста, уважайте пожелания автора.

anarchocurious
источник
как показать модальный, если пользователь хочет закрыть браузер (нажмите закрыть)? Это реально?
15

В итоге я получил немного другую версию:

var dirty = false;
window.onbeforeunload = function() {
    return dirty ? "If you leave this page you will lose your unsaved changes." : null;
}

В другом месте я устанавливаю флаг dirty на true, когда форма загрязняется (или я иным образом хочу предотвратить уход). Это позволяет мне легко контролировать, получает ли пользователь запрос подтверждения навигации.

С текстом в выбранном ответе вы увидите повторяющиеся запросы:

введите описание изображения здесь

Опасность
источник
3
В IE, если значение dirty равно false, будет показана строка «null». Просто заключите его в оператор if. См .: stackoverflow.com/questions/11793996/…
Якоб ван Линген
Согласен @JacobvanLingen, это был бы лучший ответ здесь и на три других вопроса, если бы он заканчивался undefinedвместо нуля. (1) это условно (2) в нем упоминается «грязная» самая распространенная законная причина, препятствующая перемещению, и (3) есть снимок экрана.
Bob Stein
Будет ли это работать во всех браузерах, если оно заканчивается на undefined, а не на null?
Danger
9

Эквивалент более современным и совместимым с браузером способом с использованием современных API addEventListener.

window.addEventListener('beforeunload', (event) => {
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = '';
});

Источник: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload

Пол Вебер
источник
1
Не забывайте правильно использовать заглавные буквыevent.returnValue
Flimm
7

В примере Аймана, возвращая false, вы предотвращаете закрытие окна / вкладки браузера.

window.onunload = function () {
  alert('You are trying to leave.');
  return false;
}
Габор
источник
2
Если только браузер не Opera, который пропускает событие onunload, если вкладка / окно / программа закрываются.
Powerlord
5

Эквивалент принятому ответу в jQuery 1.11:

$(window).on("beforeunload", function () {
    return "Please don't leave me!";
});

Пример JSFiddle

В ответе altCognito используется unloadсобытие, которое происходит слишком поздно, чтобы JavaScript не смог прервать навигацию.

BoffinBrain
источник
3

Используйте onunload .

Для jQuery, я думаю, это работает так:

$(window).unload(function() { 
  alert("Unloading"); 
  return falseIfYouWantToButBeCareful();
});
CGP
источник
К сожалению, возврат false не отменит выгрузку - unloadсобытие срабатывает, когда пользователь покидает страницу, в отличие от того, beforeunloadкоторое срабатывает незадолго до этого (и может быть отменено)
Джимбо
@altCognito: Вы дали мне хорошую идею с помощью falseIfYouWantToButBeCareful (). Теперь я могу избежать всплывающего окна по умолчанию, создаваемого IE или FF. Но для хрома не работает. Заглядывая в это.
user367134 09
3

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

В Chrome текст, отображаемый после настраиваемого сообщения: «Вы уверены, что хотите покинуть эту страницу?». В firefox он вообще не отображает наше собственное сообщение об ошибке (но по-прежнему отображает диалоговое окно).

Более подходящим сообщением об ошибке может быть:

window.onbeforeunload = function() {
    return "If you leave this page, you will lose any unsaved changes.";
}

Или стиль stackoverflow: «Вы начали писать или редактировать сообщение».

Кертис Яллоп
источник
2

Если вы ловите кнопку браузера назад / вперед и не хотите уходить, вы можете использовать:

window.addEventListener('popstate', function() {
    if (window.location.origin !== 'http://example.com') {
        // Do something if not your domain
    } else if (window.location.href === 'http://example.com/sign-in/step-1') {
        window.history.go(2); // Skip the already-signed-in pages if the forward button was clicked
    } else if (window.location.href === 'http://example.com/sign-in/step-2') {
        window.history.go(-2); // Skip the already-signed-in pages if the back button was clicked
    } else {
        // Let it do its thing
    }
});

В противном случае вы можете использовать событие beforeunload , но сообщение может работать или не работать в разных браузерах и требует возврата чего-то, что вызывает встроенное приглашение.

немного меньше
источник