使用jQuery编辑表单时确认离开页面

时间:2011-02-24 09:16:17

标签: jquery

我正在编写表单,我需要像stackoverflow这样的函数:“你已经开始编写或编辑帖子。”。

我已经查看了stackoverflow的代码,看看他们是如何做到这一点的,但我根本没有把它应用到我的简单表单中。这就是他们对问题的看法.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);禁用它。

我的情况很简单。我有一个页面,我通过AJAX加载<form />,我想阻止加载此表单离开页面而不点击SUBMIT按钮,或者如果用户单击取消,表单被禁用,防止不会弹出窗口。

有了这段代码,有人能告诉我如何将它包含在我的网站上吗?

这是我加载表单的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;    
});

提前谢谢!

5 个答案:

答案 0 :(得分:25)

您可以使用window.onbeforeunload这样执行此操作:

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

因此,在您的代码中,您可以将其放在success来电的$.ajax回调中。

要取消确认,您可以这样做:

window.onbeforeunload = null;

此外,请参阅此答案:How can I override the OnBeforeUnload dialog and replace it with my own?

答案 1 :(得分:13)

这是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.
});

您可以使用Google JQuery Form Serialize功能,这将收集所有表单输入并将其保存在数组中。我想这个解释就足够了:))

答案 2 :(得分:2)

我根据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();
});

的变化:

  1. 允许在未经确认的情况下提交表单。
  2. 使用$('form')。each(...)
  3. 使用多种形式
  4. 不依赖于具有id =“form”的表单
  5. 返回''作为自定义确认消息,而不是在Chrome中显示“true”的true。
  6. 对于困难页面,可以告诉它忽略某些表单字段。
  7. 从加载处理程序的末尾运行它......似乎是一个好主意。
  8. 它足够通用,因此我们可以在网站的每个页面上使用它。
  9. 它可能看起来过于设计,但这是我必须做的才能使它在真实的网络应用程序中正常工作。

    感谢Wasim,因为使用JQuery $(form).serialize()的好主意。

答案 3 :(得分:0)

基于Wasim A.的答案。该代码片段看起来不错,但是如果我单击“提交”按钮,我也会收到一条通知。我认为这样更好:

$(document).ready(function() {
    let form = $('#form');
    form.data('serialize', form.serialize());
    
    // if submit clicked - pass user to save form
    form.find('submit').on('click', function () {
        $(window).off('beforeunload');
    });
});



  // On load save form current state

$(window).bind('beforeunload', function(e){
    let form = $('#form');
    if(form.serialize() !== form.data('serialize')) {
      return true;
    } else {
    // i.e; if form state change show box not.
      e=null;
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

答案 4 :(得分:0)

Sam的答案的小优化:

var confirm_nav_ignore = [];
function confirm_nav() {
    var $forms = $('form'); // if you need it add .filter('#your_form_id');

    function save_form_state() {
        var $form = $(this),
            old_state = $form.serialize();
        $form.data('old_state', old_state);
    }

    $forms
        // On load, save form current state
        .each(save_form_state)
        // On submit, save form current state
        .submit(save_form_state)
    ;

    // 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 = undefined;

        $forms.each(function() {
            var $form = $(this);
            var old_state = strip($form.data('old_state'));
            var new_state = strip($form.serialize());
            if (new_state !== old_state) {
                e.preventDefault();
                rv = '';
            }
        });

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

在最新的chrome,firefox和safari上进行了测试