Подтвердить, чтобы оставить страницу при редактировании формы с помощью jQuery

Я кодирую форму, и мне нужна функция типа stackoverflow: "Вы начали писать или редактировать сообщение".

Я просмотрел код stackoverflow, чтобы посмотреть, как они это делают, но я не понимаю, как это применимо к моей простой форме. Это то, что у них есть на question.js:

function initNavPrevention(b) {
    if (b.which == "undefined") {
        return
    }
    var a = $("#wmd-input");
    a.unbind("keypress", initNavPrevention);
    setConfirmUnload("You have started writing or editing a post.", a)
}

Одна из функций запускает это (я не знаю, что такое c):

if (c) {
    e.keypress(initNavPrevention)
}

И, наконец, они могут setConfirmUnload(null); отключить его.

Мой случай прост. У меня есть страница, где я загружаю <form /> через AJAX, и я хочу предотвратить загрузку этой формы, чтобы оставить страницу без нажатия кнопки SUBMIT или если пользователь нажмет кнопку CANCEL, форма отключена и предупреждение не будет всплывать.

Имея этот код, может кто-нибудь сказать мне, как я могу включить его на свой сайт?

Это моя функция AJAX для загрузки формы:

$("#projects_historics_edit_part_1").click(function(){
    $("#ajax-loader").fadeIn('normal');

    $.ajax({
        url: BASE_URL + 'projects/ajax/get_historics_edit_part_1/' + PROJECT_ID,
        type: "POST",
        success: function(data) {
            $("div#projects_historics_part_1").html(data);

            $("#client").autocomplete(client_autcomplete_options);

            var inicofin = $("#initdate, #findate").datepicker(initdate_datepicker_options);
        }
    });

    $("#ajax-loader").fadeOut("normal");

    return false;    
});

Заранее благодарю вас!

Ответ 1

Вы можете сделать это, используя window.onbeforeunload следующим образом:

window.onbeforeunload = function() {
    return 'Are you sure you want to navigate away from this page?';
};

Таким образом, в вашем коде вы поместили бы это внутри обратного вызова success вашего вызова $.ajax.

Чтобы отменить подтверждение, вы можете сделать это:

window.onbeforeunload = null;

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

Ответ 2

Вот как в JQuery

$('#form').data('serialize',$('#form').serialize());
  // On load save form current state

$(window).bind('beforeunload', function(e){
    if($('#form').serialize()!=$('#form').data('serialize'))return true;
    else e=null;
    // i.e; if form state change show box not.
});

Функция JQuery Form Serialize Google может собирать все входы форм и сохранять их в массиве. Я думаю, этого объяснения достаточно:)

Ответ 3

Я сделал общую функцию для этого на основе превосходного ответа Wasim:

var confirm_nav_ignore = [];
function confirm_nav() {
    function save_form_state($form) {
        var old_state = $form.serialize();
        $form.data('old_state', old_state);
    }

    // On load, save form current state
    $('form').each(function() {
        save_form_state($(this));
    });

    // On submit, save form current state
    $('form').submit(function() {
        save_form_state($(this));
    });

    // strip fields that we should ignore
    function strip(form_data) {
        for (var i=0; i<confirm_nav_ignore.length; i++) {
            var field = confirm_nav_ignore[i];
            form_data = form_data.replace(new RegExp("\\b"+field+"=[^&]*"), '');
        }   
        return form_data;
    }

    // Before unload, confirm navigation if any field has been edited
    $(window).on('beforeunload', function(e) {
        var rv;
        $('form').each(function() {
            var $form = $(this);
            var old_state = strip($form.data('old_state'));
            var new_state = strip($form.serialize());
            if (new_state != old_state) {
                rv = '';
            }   
        }); 
        return rv;
    }); 
}

// I call it at the end of the on-load handler:
$(function() {
    confirm_nav();
});

Изменения:

  • Позволяет отправить форму без подтверждения.
  • Работает с несколькими формами, используя $('form'). each (...)
  • Не зависит от формы, имеющей id = "form"
  • Возвращает '' как пользовательское подтверждающее сообщение, а не true, которое отображает "true" в Chrome.
  • Для сложных страниц может быть сказано игнорировать определенные поля формы.
  • Запустите его с конца обработчика on-load... кажется хорошей идеей.
  • Это достаточно общее, поэтому мы можем использовать его на каждой странице сайта.

Он может выглядеть более-спроектированным, но это то, что я должен был сделать, чтобы он работал правильно в реальном веб-приложении.

Благодаря Wasim, за отличную идею использовать JQuery $(form).serialize().