Как я могу переопределить диалог OnBeforeUnload и заменить его своим собственным? - PullRequest
331 голосов
/ 10 ноября 2008

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

window.onbeforeunload=handler

Это работает, но вызывает диалоговое окно по умолчанию с раздражающим стандартным сообщением, которое оборачивает мой собственный текст. Мне нужно либо полностью заменить стандартное сообщение, чтобы мой текст был чистым, либо (что еще лучше) заменить весь диалог модальным диалогом с использованием jQuery.

Пока что мне не удалось, и я не нашел никого другого, кто, кажется, имеет ответ. Это вообще возможно?

Javascript на моей странице:

<script type="text/javascript">   
   window.onbeforeunload=closeIt;
</script>

Функция closeIt ():

function closeIt()
{
  if (changes == "true" || files == "true")
  {
      return "Here you can append a custom message to the default dialog.";
  }
}

Используя jQuery и jqModal, я пробовал подобные вещи (используя пользовательский диалог подтверждения):

$(window).beforeunload(function() {
        confirm('new message: ' + this.href + ' !', this.href);
        return false;
    });

, который также не работает - я не могу привязаться к событию beforeunload.

Ответы [ 10 ]

290 голосов
/ 10 ноября 2008

Вы не можете изменить диалог по умолчанию для onbeforeunload, поэтому лучше всего работать с ним.

window.onbeforeunload = function() {
    return 'You have unsaved changes!';
}

Вот ссылка на это от Microsoft:

Когда строка присваивается свойству returnValue файла window.event, появляется диалоговое окно, которое дает пользователям возможность остаться на текущей странице и сохранить назначенную ей строку. Оператор по умолчанию, который появляется в диалоговом окне «Вы уверены, что хотите отойти от этой страницы? ... Нажмите OK, чтобы продолжить, или Отмена, чтобы остаться на текущей странице.», Нельзя удалить или изменить.

Кажется, проблема в следующем:

  1. Когда вызывается onbeforeunload, возвращаемое значение обработчика будет приниматься как window.event.returnValue.
  2. Затем он будет анализировать возвращаемое значение как строку (если оно не равно нулю).
  3. Так как false анализируется как строка, появится диалоговое окно, которое затем передаст соответствующий true / false.

В результате, кажется, нет способа присвоить false для onbeforeunload, чтобы предотвратить его от диалога по умолчанию.

Дополнительные примечания по jQuery:

  • Установка события в jQuery может быть проблематичной, так как это позволяет происходить и другим onbeforeunload событиям. Если вы хотите, чтобы произошло событие unload, я бы использовал для этого обычный старый JavaScript.
  • jQuery не имеет ярлыка для onbeforeunload, поэтому вам придется использовать общий синтаксис bind.

    $(window).bind('beforeunload', function() {} );
    

Редактировать 09/04/2018 : пользовательские сообщения в диалоговых окнах onbeforeunload устарели начиная с chrome-51 (ср .: примечание к выпуску )

27 голосов
/ 14 февраля 2011

Что сработало для меня, используя jQuery и протестировано в IE8, Chrome и Firefox, так это:

$(window).bind("beforeunload",function(event) {
    if(hasChanged) return "You have unsaved changes";
});

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

20 голосов
/ 12 июля 2012

Хотя в некоторых случаях вы ничего не можете сделать с этим ящиком, вы можете перехватить кого-нибудь, щелкнув по ссылке. Для меня это стоило усилий для большинства сценариев, и как запасной вариант, я оставил событие unload.

Я использовал Boxy вместо стандартного диалога jQuery, он доступен здесь: http://onehackoranother.com/projects/jquery/boxy/

$(':input').change(function() {
    if(!is_dirty){
        // When the user changes a field on this page, set our is_dirty flag.
        is_dirty = true;
    }
});

$('a').mousedown(function(e) {
    if(is_dirty) {
        // if the user navigates away from this page via an anchor link, 
        //    popup a new boxy confirmation.
        answer = Boxy.confirm("You have made some changes which you might want to save.");
    }
});

window.onbeforeunload = function() {
if((is_dirty)&&(!answer)){
            // call this if the box wasn't shown.
    return 'You have made some changes which you might want to save.';
    }
};

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

Я вырезал код, поэтому он может не работать как есть.

9 голосов
/ 19 сентября 2012

1) Использование перед загрузкой, а не загрузкой.

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

3) Если вы используете onbeforeunload, вы можете запустить ajax-вызов в своем обработчике unbeforeunload, чтобы привести в порядок сервер, но он должен быть синхронным, и вам придется ждать и обрабатывать ответ в своем обработчике onbeforeunload (все еще соблюдая условие (2) выше). Я делаю это, и это отлично работает. Если вы делаете синхронный вызов ajax, все задерживается до тех пор, пока ответ не вернется. Если вы делаете асинхронный ответ, думая, что вам не нужен ответ от сервера, выгрузка страницы продолжается, и ваш процесс ajax прерывается этим процессом - включая удаленный скрипт, если он выполняется.

4 голосов
/ 21 февраля 2013

Попробуйте разместить return; вместо сообщения ... это работает в большинстве браузеров для меня. (Это действительно только предотвращает подарки от диалога)

window.onbeforeunload = function(evt) {            
        //Your Extra Code
        return;
}
3 голосов
/ 31 мая 2017

Это не может быть сделано в Chrome сейчас, чтобы избежать спама, см. javascript onbeforeunload, не показывающий пользовательское сообщение для получения более подробной информации.

3 голосов
/ 03 марта 2012

Вы можете определить, какая кнопка (ок или отмена) нажата пользователем, потому что функция onunload вызывается только тогда, когда пользователь выбирает покинуть страницу. Хотя в этой функции возможности ограничены, потому что DOM рушится. Вы можете запустить javascript, но ajax POST ничего не делает, поэтому вы не можете использовать этот метод для автоматического выхода из системы. Но для этого есть решение. Window.open ('logout.php') выполняется в функции onunload, поэтому пользователь выходит из системы с открытием нового окна.

function onunload = (){
    window.open('logout.php');
}

Этот код вызывается, когда пользователь покидает страницу или закрывает активное окно, и пользователь выходит из системы с помощью logout.php. Новое окно закрывается сразу после выхода php из кода:

window.close();
3 голосов
/ 10 июня 2011

Я столкнулся с той же проблемой, я был в порядке, чтобы получить свое собственное диалоговое окно с моим сообщением, но проблема, с которой я столкнулся, была: 1) Он давал сообщение на всех навигациях, я хочу это только для близкого щелчка. 2) с моим собственным подтверждением, если пользователь выбирает «Отмена», оно по-прежнему отображает диалоговое окно браузера по умолчанию.

Ниже приведен код решения, который я нашел и написал на своей главной странице.

function closeMe(evt) {
    if (typeof evt == 'undefined') {
        evt = window.event; }
    if (evt && evt.clientX >= (window.event.screenX - 150) &&
        evt.clientY >= -150 && evt.clientY <= 0) {
        return "Do you want to log out of your current session?";
    }
}
window.onbeforeunload = closeMe;
1 голос
/ 16 марта 2012
 <script type="text/javascript">
        window.onbeforeunload = function(evt) {
            var message = 'Are you sure you want to leave?';
            if (typeof evt == 'undefined') {
                evt = window.event;
            }       
            if (evt) {
                evt.returnValue = message;
            }
            return message;
        } 
    </script>

см. http://www.codeprojectdownload.com

1 голос
/ 20 августа 2010

Как насчет использования специализированной версии команды «связать» «один». Как только обработчик событий выполняется в первый раз, он автоматически удаляется как обработчик событий.

$(window).one("beforeunload", BeforeUnload);
...