用于"未保存的数据"保护的Client / JS框架?

时间:2020-03-06 14:47:35  来源:igfitidea点击:

我们有一个典型的Web应用程序,它本质上是一个具有许多屏幕的数据输入应用程序,其中一些屏幕具有一定程度的复杂性。我们需要提供标准功能,以确保用户在离开或者关闭浏览器之前忘记单击"保存"按钮时,他们会得到警告并可以取消(但仅当有未保存或者不干净的数据时)。

我知道我必须做的事情的基础-实际上,我敢肯定,这些年来我已经做完了所有事情(请绑定到onbeforeunload,跟踪页面的"脏"状态等)。但是在我开始编写此代码之前,是否有人对已经存在的库(免费的或者其他的)提出一些建议,这些建议会有所帮助?

解决方案

难题之一:

/**
 * Determines if a form is dirty by comparing the current value of each element
 * with its default value.
 *
 * @param {Form} form the form to be checked.
 * @return {Boolean} <code>true</code> if the form is dirty, <code>false</code>
 *                   otherwise.
 */
function formIsDirty(form)
{
    for (var i = 0; i < form.elements.length; i++)
    {
        var element = form.elements[i];
        var type = element.type;
        if (type == "checkbox" || type == "radio")
        {
            if (element.checked != element.defaultChecked)
            {
                return true;
            }
        }
        else if (type == "hidden" || type == "password" || type == "text" ||
                 type == "textarea")
        {
            if (element.value != element.defaultValue)
            {
                return true;
            }
        }
        else if (type == "select-one" || type == "select-multiple")
        {
            for (var j = 0; j < element.options.length; j++)
            {
                if (element.options[j].selected !=
                    element.options[j].defaultSelected)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

还有一个:

window.onbeforeunload = function(e)
{
    e = e || window.event;  
    if (formIsDirty(document.forms["someFormOfInterest"]))
    {
        // For IE and Firefox
        if (e)
        {
            e.returnValue = "You have unsaved changes.";
        }
        // For Safari
        return "You have unsaved changes.";
    }
};

全部包起来,我们会得到什么?

var confirmExitIfModified = (function()
{
    function formIsDirty(form)
    {
        // ...as above
    }

    return function(form, message)
    {
        window.onbeforeunload = function(e)
        {
            e = e || window.event;
            if (formIsDirty(document.forms[form]))
            {
                // For IE and Firefox
                if (e)
                {
                    e.returnValue = message;
                }
                // For Safari
                return message;
            }
        };
    };
})();

confirmExitIfModified("someForm", "You have unsaved changes.");

我们可能还希望将beforeunload事件处理程序的注册更改为使用`LIBRARY_OF_CHOICE'的事件注册。

如果我们使用jQuery,这是一个简单的技巧:

$('input:text,input:checkbox,input:radio,textarea,select').one('change',function() {
  $('BODY').attr('onbeforeunload',"return 'Leaving this page will cause any unsaved data to be lost.';");
});

但是请记住,如果我们有从此页面重定向的条件,或者想要允许成功的表单发布,则需要在重定向或者提交事件之前执行此操作,如下所示:

$('BODY').removeAttr('onbeforeunload');

...否则我们会陷入循环,不断询问提示。

就我而言,我有一个大应用程序,当时我正在使用Javascript进行location.href重定向以及表单发布,然后提交了一些AJAX,然后在页面中内联成功响应。在任何这些情况下,我都必须捕获该事件并使用removeAttr()调用。

想要在Volomike出色的jQuery代码上稍作扩展。

因此,有了这个非常非常酷而优雅的机制,可以通过在保存之前导航到更新后的数据来实现防止意外数据丢失的目的。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。吗?页面上的"更新"字段,然后在单击"保存"按钮之前,在浏览器中单击按钮,链接甚至后退按钮。

我们唯一需要做的就是将noWarn类标签添加到所有张贴回网站的控件(尤其是"保存"按钮)上,该控件可以保存或者不删除任何更新的数据。

如果控件导致页面丢失数据,即。导航到下一页或者清除不需要执行任何操作的数据,因为脚本将自动显示警告消息。

惊人的!做得好Volomike!

只需使用以下jQuery代码即可:

$(document).ready(function() {

    //----------------------------------------------------------------------
    // Don't allow us to navigate away from a page on which we're changed
    //  values on any control without a warning message.  Need to class our 
    //  save buttons, links, etc so they can do a save without the message - 
    //  ie. CssClass="noWarn"
    //----------------------------------------------------------------------
    $('input:text,input:checkbox,input:radio,textarea,select').one('change', function() {
        $('BODY').attr('onbeforeunload',
        "return 'Leaving this page will cause any unsaved data to be lost.';");
    });

    $('.noWarn').click(function() { $('BODY').removeAttr('onbeforeunload'); });

});

除了Lance的答案,我只是花了一个下午来尝试使此代码段运行。
首先,jQuery 1.4似乎存在绑定更改事件的错误(截至2010年2月)。 jQuery 1.3可以。
其次,我无法让jquery绑定onbeforeunload / beforeunload(我怀疑我正在使用IE7)。我尝试了不同的选择器,(" body"),(窗口)。我已经尝试过" .bind","。attr"。
恢复为纯js可行(关于此问题,我在SO上也看到了一些类似的帖子):

$(document).ready(function() {
    $(":input").one("change", function() {
        window.onbeforeunload = function() { return 'You will lose data changes.'; }
    });
    $('.noWarn').click(function() { window.onbeforeunload = null; });
});

注意我还使用了':input'选择器,而不是列举所有输入类型。严格的矫kill过正,但我​​认为这很酷:-)

我对该页面上列出的jQuery实现进行了另一项小幅改进。如果启用了客户端ASP.NET页面验证并在页面上使用它,我的实现将进行处理。

当由于验证失败而导致页面未实际单击时,它避免了清除onBeforeLeave函数的"错误"。只需在导致验证的按钮/链接上使用no-warn-validate类即可。它仍然具有" no-warn"类,可用于具有" CausesValidation = false"的控件(例如,"另存为草稿"按钮)。该模式可能会用于ASP.NET以外的其他验证框架,因此我在此处发布以供参考。

function removeCheck() { window.onbeforeunload = null; }

$(document).ready(function() {
    //-----------------------------------------------------------------------------------------
    // Don't allow navigating away from page if changes to form are made. Save buttons, links,
    // etc, can be given "no-warn" or "no-warn-validate" css class to prevent warning on submit.
    // "no-warn-validate" inputs/links will only remove warning after successful validation
    //-----------------------------------------------------------------------------------------
    $(':input').one('change', function() {
        window.onbeforeunload = function() {
            return 'Leaving this page will cause edits to be lost.';
        }
    });

    $('.no-warn-validate').click(function() {
        if (Page_ClientValidate == null || Page_ClientValidate()) { removeCheck(); }
    });

    $('.no-warn').click(function() { removeCheck() });
});

我创建了一个jQuery插件,可用于为Web应用程序实现未保存更改警告。它支持回发。它还包括指向有关如何规范Internet Explorer的onbeforeunload事件行为的信息的链接。