Активация OnBeforeUnload ТОЛЬКО при изменении значений поля - PullRequest
21 голосов
/ 29 мая 2009

Я пытаюсь добиться того, чтобы предупредить пользователя о несохраненных изменениях, если он / она пытается закрыть страницу или отойти от нее, не сохранив сначала.

Мне удалось заставить всплывающее диалоговое окно OnBeforeUnload() ... но я не хочу, чтобы оно вообще отображалось, если пользователь не изменил значения полей. Для этого я использую это скрытое поле ввода с именем is_modified , которое начинается со значения по умолчанию false и переходит на true при редактировании любого поля.

Я попытался привязать событие change к этому полю is_modified, чтобы попытаться обнаружить изменение значения ... и только затем активировать OnBeforeUnload.

$( '#is_modified' ).change( function() {
    if( $( '#is_modified' ).val() == 'true' )
        window.onbeforeunload = function() { return "You have unsaved changes."; }
});

Но из того, что я считаю, событие change() работает только после этих 3 шагов - поле получает фокус, значение изменяется, и поле теряет фокус. В случае скрытого поля ввода, я не уверен, как работает эта часть приема и потери фокуса! Следовательно, функция onbeforeunload никогда не активируется.

Может кто-нибудь предложить способ поддержания триггера над is_modified?

Спасибо.

Ответы [ 7 ]

31 голосов
/ 05 июля 2011

У меня было похожее требование, поэтому я предложил следующий скрипт jQuery:

$(document).ready(function() {
    needToConfirm = false; 
    window.onbeforeunload = askConfirm;
});

function askConfirm() {
    if (needToConfirm) {
        // Put your custom message here 
        return "Your unsaved data will be lost."; 
    }
}

$("select,input,textarea").change(function() {
    needToConfirm = true;
});

Приведенный выше код проверяет переменную needToConfirm, если она true, то будет отображаться предупреждение. При изменении значения элементов input, select или textarea переменная needToConfirm устанавливается на true.


PS: Firefox> 4 не разрешать настраиваемое сообщение для onbeforeunload.
Справка: https://bugzilla.mozilla.org/show_bug.cgi?id=588292


ОБНОВЛЕНИЕ: Если вы фанат производительности, вам понравится предложение @ KyleMit . Он написал расширение jQuery only(), которое будет выполнено только один раз для любого элемента.

$.fn.only = function (events, callback) {
    //The handler is executed at most once for all elements for all event types.
    var $this = $(this).on(events, myCallback);
    function myCallback(e) {
        $this.off(events, myCallback);
        callback.call(this, e);
    }
    return this
};    

$(":input").only('change', function() {
    needToConfirm = true;
});
7 голосов
/ 18 июня 2009

Мы просто используем Window.onbeforeunload в качестве нашего «измененного» флага. Вот что мы делаем (используя lowpro):

Event.addBehavior({
  "input[type=radio]:change,input[type=text]:change,input[type=checkbox]:change,select:change": function(ev) {
       window.onbeforeunload = confirmLeave;
  }
  ".button.submit-button:click": function(ev) {
       window.onbeforeunload = null;
  },
});


function confirmLeave(){
    return "Changes to this form have not been saved. If you leave, your changes will be lost."  
}
5 голосов
/ 25 мая 2013

В jQuery хорошо работает:

var needToConfirm = false;

$("input,textarea").on("input", function() {
  needToConfirm = true;
});

$("select").change(function() {
  needToConfirm = true;
});

window.onbeforeunload = function(){        
  if(needToConfirm) {
    return "If you exit this page, your unsaved changes will be lost.";        
  }
}   

И если пользователь отправляет форму для сохранения изменений, вы можете добавить это (измените #mainForm на идентификатор формы, которую он отправляет):

$("#mainForm").submit(function() {
  needToConfirm = false;
});
3 голосов
/ 10 мая 2014
$(window).bind('beforeunload',function() {
 return "'Are you sure you want to leave the page. All data will be lost!";
});

$('#a_exit').live('click',function() {
    $(window).unbind('beforeunload');
});

выше работает для меня.

1 голос
/ 29 мая 2009

Попробуйте свою логику по-другому. Смысл, поместите логику для проверки значения поля ввода в ваш onbeforeunload метод.

window.onbeforeunload = function () { 
    if ($("#is_modified").val() == 'true') { 
        return "You have unsaved changes."; 
    } else { 
        return true; // I think true is the proper value here 
    } 
};
0 голосов
/ 06 июня 2011

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

0 голосов
/ 29 мая 2009

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

...