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

331

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

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.

  • 1
    Можете ли вы привести пример вашего текущего кода и что он производит?
  • 0
    Оуэн прав. И причина этого заключается в безопасности. Предотвращение выгрузки страницы полезно в веб-формах и тому подобном, но злоумышленник может легко использовать ее, чтобы обмануть пользователя, чтобы он остался на странице. Вот почему веб-браузеры реализуют стандартное сообщение и имеют этот механизм для вставки пользовательского текста.
Показать ещё 4 комментария
Теги:
onbeforeunload

12 ответов

269
Лучший ответ

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

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

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

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

Проблема заключается в следующем:

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

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

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

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

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

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

  • 0
    Я использовал OnBeforeUnload для того, чтобы вернуть пользователя на страницу, вместо того, чтобы фактически позволить ему уйти - onunload происходит после уверенной выгрузки страницы? Кроме того, я не могу заставить вашу функцию onunload работать по какой-то причине?
  • 20
    Я обнаружил, что приведенный в конце пример JQuery не работает в Firefox. Вместо этого придерживайтесь простого способа: window.onbeforeunload = function () {...}
Показать ещё 8 комментариев
40

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

27

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

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

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

  • 0
    Интересно, что event.returnValue - единственный «одобренный» метод в IE. IE продолжает: «Значение этого свойства имеет приоритет над значениями, возвращаемыми функцией, например, с помощью оператора возврата Microsoft JScript». .. было бы неплохо увидеть гарантированную корреляцию между return (from event) и event.returnValue ..
18

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

Я использовал Boxy вместо стандартного jQuery Dialog, он доступен здесь: 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.';
    }
};

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

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

  • 0
    return 'Вы внесли некоторые изменения, которые вы можете сохранить.' не работал для меня. Я должен был сохранить сообщение в переменной сказать «warning_message», и я действительно возвратил warning_message. Тогда только у меня получалось!
  • 0
    Вы тестировали в IE, Chrome, Firefox?
9

1) Используйте onbeforeunload, а не onunload.

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

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

3

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

3

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

window.onbeforeunload = function(evt) {            
        //Your Extra Code
        return;
}
  • 3
    возвращение ноль будет препятствовать открытию диалога
  • 1
    return null НЕ помешает открытию диалога. Я попробовал это в Chrome, и это не так.
Показать ещё 2 комментария
3

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

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

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

window.close();
  • 0
    Вы можете использовать синхронный пост в функциях beforeunload и unload. Особенно, если вам нужны данные обратно с сервера. Любой асинхронный код в этих блоках может не завершиться к моменту выгрузки страницы.
3

Я столкнулся с той же проблемой, я был в порядке, чтобы получить свое собственное диалоговое окно с моим сообщением, но проблема, с которой я столкнулся, заключалась в следующем: 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

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

В конце концов, я получил это, чтобы игнорировать всплывающее окно firefox по умолчанию с помощью этого сайта: http://code-maven.com/prevent-leaving-the-page-using-plain-javascript. Он добавлен перед перенастройкой окна:

window.onbeforeunload = function() {
    if (data_needs_saving()) {
         return "";
    } else {
         return "";
    }
};
window.location.href = 'www.redirect here';
1
 <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

0

Как использовать специализированную версию команды "bind" "one". Когда обработчик события выполняется в первый раз, он автоматически удаляется как обработчик события.

$(window).one("beforeunload", BeforeUnload);
  • 0
    почти уверен, что это .on ("beforeunload"
  • 0
    @SergiuMindras нет, это .one() - прикрепляет прослушиватель событий для прослушивания события, которое происходит только один раз: «Присоединить обработчик к событию для элементов. Обработчик выполняется не более одного раза для каждого элемента для каждого типа события». api.jquery.com/one

Ещё вопросы

Сообщество Overcoder
Наверх
Меню