在让用户将焦点转移到其他表单之前,检测表单是否有未保存的更改

时间:2016-09-30 23:18:22

标签: javascript jquery html

有没有办法检测用户是否在同一页面中从一个部分的内容更改为另一个部分?

我有一个带有多个按钮的页面(一旦你点击每个按钮就会打开一个表单/部分),当它们全部关闭时,我可以检测到用户正在使用按钮元素上的click事件更改为另一个表单。

在这种情况下,我的部分是在您单击页面中的每个按钮时加载的表单。纯jquery通过其中的ajax加载内容。

问题是所有部分都打开了。我需要检测用户何时在一个部分的内容之间进行了更改。

我必须警告用户在以前的表单中保存更改,因为系统超时不活动,如果用户没有保存他的数据,一旦用户从应用程序注销就会丢失。

该事件提示用户保存上一个表单的数据。

我能想到的唯一方法是使用鼠标事件,但这有时会令人沮丧。

解决

感谢DelightedD0D,我最终做了这个

此var保存以前的表格编号

var pendingForm = [];

触发可能警告的事件

//Pressing tab is reviewed if there are unsaved changes in the previous section.
$(document).keyup(function(eventTab) {
    var code = eventTab.keyCode || eventTab.which;
    if (code === 9) {
        checkPrevious(eventTab);
    }
});
//Clicking is reviewed if there are unsaved changes in the previous section
$(document).mouseup(function(eventMouse) {
    checkPrevious(eventMouse);
});

这里我们确定表单何时挂起或已更改

$('.formSection').on('keyup change', 'input, select, textarea', function() {
  $(this).closest('.formSection').addClass('pending');
  //We get the number of the form by the id
  var numForm = $(this).closest('.formSection').attr('id').substr(11, 2);
  if ( $.inArray(numForm , pendingForm) == -1 ) {
    pendingForm.push(numForm);
  }
});

//I have my own functions to save and cancel, but the idea is Save the data
//then find the formSection from previous form, remove pending class and
//remove number form from array of pending sections
$('.save').click(function() {
  //save data...
  var numForm = pendingForm.pop();
  $('#formSection'+numForm).removeClass('pending');
});

此功能会检查用户何时移动到另一个表单

function checkPrevious(e) {
    var $target = $(e.target);
    //If it is clicked somewhere within a form or a button that opens a section
    if ($target.closest('.formSection').length || $target.hasClass('btnSection')) {
        var isDisabled = false;
        if (pendingForm.length > 0) {
            prevForm = pendingForm.slice(-1).pop();
            //Every submit form button has an id with a consecutive number in my case
            //If disabled, that means it has errors in validation (Bootstrap)
            //**I have to improve this verification yet**
            isDisabled = $('#submitForm' + prevForm).is(':disabled');
        }

        // get any forms with changes that are not the current form or do not contain the clicked element
        var $otherFormsWithChanges = $('.pending').filter(function() {
            var $this = $(this);
            return $this.hasClass('pending') && (!$this.is($target) || $this.has($target).length != 0);
        });
        // if another form has a change, thow up a message
        // allow the user to go back to the form or ignore the changes
        if ($otherFormsWithChanges.length > 0 && $otherFormsWithChanges.has($target).length === 0 ) {
            var modalPrev = $('#modalPrev');
            if ( isDisabled == false ) {
                //If everything is ok, we can save
                modalPrev.find('.modal-content .modal-body').html("<p>You have unsaved changes. Do you want to save previous form?</p>");
                modalPrev.find(".btnSave").removeClass('hide');
            } else {
                modalPrev.find('.modal-content .modal-body').html("<p>You have some errors in your previous form.</p>");
                modalPrev.find(".btnSave").addClass('hide');
            }
            $('#modalPrev').modal('show');
        }
    }
}

我用两个按钮[Save]和[Cancel]显示一个模态而不是一个警告,每个按钮都有一个保存或关闭的功能,但是两个都从数组中删除了以前的部分,不再被认为了。

1 个答案:

答案 0 :(得分:1)

您可以通过在输入值更改时在表单上设置类,然后侦听文档的点击并检查与正在进行交互的表单之间的表单是否发生更改来执行此操作。如果有,则向用户显示消息。

这应该有效:

注意必须使用表单,只需将track-changes类添加到您已组合在一起的输入的某个父级

jsFiddle example

$(document).mouseup(function(e) { 
  var $target = $(e.target);   
  // get any forms with changes that are not the current form or do not contain the clicked element
  var $otherFormsWithChanges = $('.pending').filter(function() {
    var $this=$(this); 
    return $this.hasClass('pending') && (!$this.is($target) || $this.has($target).length !=0);
  }); 
  // if another form has a change, thow up a message
  // allow the user to go back to the form or ignore the changes
  if ($otherFormsWithChanges.length > 0 && $otherFormsWithChanges.has($target).length===0 ) { 
    var c = confirm("You have unsaved changes.\n\n Click cancel to go back to the unsaved form or OK to ignore");
    c ? $otherFormsWithChanges.removeClass('pending') : $otherFormsWithChanges.find('input, select, textarea').focus();  
  }
});

$('.track-changes').on('keyup change', 'input, select, textarea', function() {
  $(this).closest('.track-changes').addClass('pending'); 
});

$('.save').click(function() {
  // save data...
  $(this).closest('.track-changes').removeClass('pending'); 
});
form{
  padding:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>form 1</h4>
<form class="track-changes" has-changes="false" action="">
  <input type="text">
  some text
  <br>
  <button type="button" class="save">Save</button>
</form>

<h4>form 2</h4>
<form class="track-changes" has-changes="false" action="">
  <input type="text">
  some text
  <br>
  <button type="button" class="save">Save</button>
</form>

<h4>form 3</h4>
<form class="track-changes" has-changes="false" action="">
  <input type="text">
  some text
  <br>
  <button type="button" class="save">Save</button>
</form>