【问题标题】:Confirm to leave the page when editing a form with jQuery使用 jQuery 编辑表单时确认离开页面
【发布时间】:2011-07-03 10:07:58
【问题描述】:

我正在编写一个表单,我需要一个像 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); 来禁用它。

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

拥有此代码,有人可以告诉我如何将其包含在我的网站上吗?

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

提前谢谢你!

【问题讨论】:

标签: jquery


【解决方案1】:

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

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

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

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

window.onbeforeunload = null;

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

【讨论】:

  • 但是如果我使用它,即使使用提交按钮提交表单也会显示该消息。我希望在离开页面而不提交时显示消息。
  • 使用 window.onbeforeunload = undefined;取消确认。它也适用于 IE。特别是你可以返回 undefined 以防你不需要显示消息(适用于 IE 和其他浏览器)
【解决方案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.
});

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

【讨论】:

  • 有时您通过 ajax 提交数据并且没有标签属性名称,在这种情况下使用 $(form).html()
  • 刚刚在考虑这个:)
  • 这是一个非常好的方法。我使用带有 $('form').each(...) 而不是 $('#form') 的循环,以防页面上有多个表单。我已经添加了我的替代方案作为另一个答案,因为它不是很明显。但所有的道具都归你所有!
  • 一段很棒的代码,谢谢!有什么方法可以自定义显示框中的文本吗?
  • 谢谢,但我不认为我们可以自定义浏览器的那些对象。
【解决方案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();
});

变化:

  1. 允许在没有确认的情况下提交表单。
  2. 适用于多个表单,使用 $('form').each(...)
  3. 不依赖于具有 id="form" 的表单
  4. 返回 '' 作为自定义确认消息,而不是在 Chrome 中显示“true”的 true。
  5. 对于困难的页面,可以告诉它忽略某些表单字段。
  6. 从负载处理程序的末尾运行它...似乎是个好主意。
  7. 它足够通用,因此我们可以在网站的每个页面上使用它。

它可能看起来过度设计,但这是我必须做的才能让它在真正的网络应用程序中正常工作。

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

【讨论】:

    【解决方案4】:

    基于 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;
        }
    });
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

    【讨论】:

      【解决方案5】:

      优秀山姆回答的小优化:

      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 上测试

      【讨论】:

        猜你喜欢
        • 2014-03-25
        • 2011-11-09
        • 2018-02-05
        • 2012-11-14
        • 2019-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-17
        相关资源
        最近更新 更多