Предупреждение о несохраненных изменениях в форме


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

однако в большинстве решений мне придется писать код на всех страницах. Я хочу, чтобы он писал только в одном месте, так что всем не нужно беспокоиться, чтобы написать его в своих модулях. Мой код выглядит так:

<script type="text/javascript">
    var isChange;
    $(document).ready(function () {
        $("input[type='text']").change(function () {
            isChange = true;
        })
    });
    $(window).unload(function () {
        if (isChange) {
            alert('Handler for .unload() called.');
        }
    });

</script>

но каждый раз, когда я делаю изменения в текстовых полях .событие change() не является обжиг.

что может быть не так в коде?

изменить: Я изменился .изменить () на .нажмите, и он выстрелил. я использую jquery 1.4.1..is это из-за версии jquery, которая change() не работает?

7   51  

7 ответов:

вот что я использую, поместите весь этот код в отдельный js-файл и загрузите его в свой файл заголовка, чтобы вам не нужно было копировать это снова и снова:

var unsaved = false;

$(":input").change(function(){ //trigers change in all input fields including text type
    unsaved = true;
});

function unloadPage(){ 
    if(unsaved){
        return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
    }
}

window.onbeforeunload = unloadPage;

EDIT for $ not found:

эта ошибка может быть вызвана одной из трех вещей:

  1. ваш файл JavaScript не загружается правильно на вашу страницу
  2. у вас есть неудачная версия jQuery. Это может произойти, потому что кто-то отредактировал основной файл, или плагин, возможно, перезаписал $ переменная.
  3. у вас есть JavaScript, работающий до полной загрузки страницы, и как таковой, до полной загрузки jQuery.

убедитесь, что весь код js помещается в это:

$(document).ready(function () {
  //place above code here
});

редактировать для исключения кнопки Сохранить / отправить / отправить

$('#save').click(function() {
    unsaved = false;
});

изменить для работы с динамическими входами

// Another way to bind the event
$(window).bind('beforeunload', function() {
    if(unsaved){
        return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
    }
});

// Monitor dynamic inputs
$(document).on('change', ':input', function(){ //triggers change in all input fields including text type
    unsaved = true;
});

добавить выше код в вашем alert_unsaved_changes.js файл.

надеюсь, что это помогает.

версия, которая использует сериализацию формы:

выполнить этот код, когда dom готов:

// Store form state at page load
var initial_form_state = $('#myform').serialize();

// Store form state after form submit
$('#myform').submit(function(){
  initial_form_state = $('#myform').serialize();
});

// Check form changes before leaving the page and warn user if needed
$(window).bind('beforeunload', function(e) {
  var form_state = $('#myform').serialize();
  if(initial_form_state != form_state){
    var message = "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
    e.returnValue = message; // Cross-browser compatibility (src: MDN)
    return message;
  }
});

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

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

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

С. П. Я надеюсь, вы знаете, что ваш подход к обнаружению изменений не является лучшим? Если пользователь вводит некоторые текст, покидает поле, а затем возвращает изменения скрипт будет по-прежнему предупреждать его об измененном тексте.

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

$("input[type='text'], textarea").keyup(function () {
    isChange = true;
})

почему бы просто не привязать событие к change обратного вызова?

$(":input").change(function()
{
    $(window).unbind('unload').bind('unload',function()
    {
        alert('unsaved changes on the page');
    });
});

в качестве дополнительного бонуса, вы можете использовать confirm и выберите последний элемент, который вызвал событие change:

$(":input").change(function()
{
    $(window).unbind('unload').bind('unload',(function(elem)
    {//elem holds reference to changed element
        return function(e)
        {//get the event object:
            e = e || window.event;
            if (confirm('unsaved changes on the page\nDo you wish to save them first?'))
            {
                elem.focus();//select element
                return false;//in jQuery this stops the event from completeing
            }
        }
    }($(this)));//passed elem here, I passed it as a jQ object, so elem.focus() works
    //pass it as <this>, then you'll have to do $(elem).focus(); or write pure JS
});

если у вас есть кнопка Сохранить, убедитесь, что это развязывает событие выгрузки, хотя:

$('#save').click(function()
{
    $(window).unbind('unload');
    //rest of your code here
});

это действительно просто другая версия ответа @AlphaMale, но улучшенная несколькими способами:

# Message displayed to user. Depending on browser and if it is a turbolink,
# regular link or user-driven navigation this may or may not display.
msg = "This page is asking you to confirm that you want to leave - data you have entered may not be saved."

# Default state
unsaved = false

# Mark the page as having unsaved content
$(document).on 'change', 'form[method=post]:not([data-remote]) :input', -> unsaved = true

# A new page was loaded via Turbolinks, reset state
$(document).on 'page:change', -> setTimeout (-> unsaved = false), 10

# The user submitted the form (to save) so no need to ask them.
$(document).on 'submit', 'form[method=post]', ->
  unsaved = false
  return

# Confirm with user if they try to go elsewhere
$(window).bind 'beforeunload', -> return msg if unsaved

# If page about to change via Turbolinks also confirm with user
$(document).on 'page:before-change', (event) ->
  event.preventDefault() if unsaved && !confirm msg

это лучше в следующих отношениях:

  • это coffeescript, который IMHO автоматически делает его лучше. :)
  • он полностью основан на событийном пузырении, поэтому динамический контент автоматически обрабатывается (обновление@AlphaMale также имеет это).
  • он работает только на POST формы, как получить формы не имеют данных, которые мы обычно хотим избежать потеря (т. е. формы GET, как правило, являются полями поиска и критериями фильтрации).
  • он не должен быть привязан к определенной кнопке для проведения спасти. Каждый раз, когда форма представляется мы предполагаем, что представление является сохранением.
  • это Turbolinks совместимость. Если вам это не нужно, просто отбросьте два page: Привязок событий.
  • он предназначен, так что вы можете просто включить его с остальной частью вашего JS и весь ваш сайт будет защищенный.

Я использую $('form').change etc. функция для установки грязной битовой переменной. Не подходит, чтобы поймать все изменения (согласно предыдущим ответам), но ловит все, что меня интересует, в моем приложении.