“未保存数据”的客户端/JS 框架 保护?

发布于 2024-07-05 21:00:55 字数 265 浏览 13 评论 0原文

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

我知道我必须做的事情的基础知识——事实上,我确信这些年来我已经完成了这一切(绑定到 onbeforeunload、跟踪页面的“脏”状态等...... )但是在我再次开始编码之前,是否有人对已经存在的库(免费或其他)有一些建议可以提供帮助?

We have a typical web application that is essentially a data entry application with lots of screens some of which have some degree of complexity. We need to provide that standard capability on making sure if the user forgets to click the "Save" button before navigating away or closing their browser they get a warning and can cancel (but only when there is unsaved or dirty data).

I know the basics of what I've got to do-- in fact I'm sure I've done it all before over the years (tie in to onbeforeunload, track the "dirty" state of the page, etc...) but before I embark on coding this YET AGAIN, does anyone have some suggestions for libraries already out there (free or otherwise) that will help out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

最好是你 2024-07-12 21:00:55

一个难题:

/**
 * 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 的事件注册。

One piece of the puzzle:

/**
 * 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;
}

And another:

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.";
    }
};

Wrap it all up, and what do you get?

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.");

You'll probably also want to change the registration of the beforeunload event handler to use LIBRARY_OF_CHOICE's event registration.

迷你仙 2024-07-12 21:00:55

如果您使用 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() 调用。

If you use jQuery, here's an easy trick:

$('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.';");
});

But just remember, if you have a condition where you redirect from this page, or you want to permit a successful form post, you need to do this before that redirect or submit event like so:

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

...or you'll get yourself in a loop where it keeps asking you the prompt.

In my case, I had a big app and I was doing location.href redirects in Javascript, as well as form posting, and then some AJAX submits that then come back with a success response inline in the page. In any of those conditions, I had to capture that event and use the removeAttr() call.

锦欢 2024-07-12 21:00:55

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

I've created a jQuery plug-in which can be used to implement a warn-on-unsaved-changes feature for web applications. It supports postbacks. It also includes a link to information on how to normalize behavior of the onbeforeunload event of Internet Explorer.

记忆で 2024-07-12 21:00:55

我对此页面上列出的 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() });
});

I made one more slight improvement to the jQuery implementations listed on this page. My implementation will handle if you have client-side ASP.NET page validation enabled and being used on a page.

It avoids the "error" of clearing the onBeforeLeave function when the page doesn't actually post on click due to a validation failure. Simply use the no-warn-validate class on buttons/links that cause validation. It still has the no-warn class to use on controls that have CausesValidation=false (e.g. a "Save as Draft" button). This pattern could probably be used for other validation frameworks other than ASP.NET, so I post here for reference.

 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() });
});
小傻瓜 2024-07-12 21:00:55

除了兰斯的回答之外,我刚刚花了一个下午的时间试图运行这个片段。
首先,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' 选择器,而不是枚举所有输入类型。 严格来说有点矫枉过正,但我​​认为这很酷:-)

Additional to Lance's answer, I just spent an afternoon trying to get this snippet running.
Firstly, jquery 1.4 seems to have bugs with binding the change event (as of Feb '10). jQuery 1.3 is OK.
Secondly, I can't get jquery to bind the onbeforeunload/beforeunload (I suspect IE7, which I'm using). I've tried different selectors, ("body"), (window). I've tried '.bind', '.attr'.
Reverting to pure js worked (I also saw a few similar posts on SO about this problem):

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

Note I've also used the ':input' selector rather than enumerating all the input types. Strictly overkill, but I thought it was cool :-)

我也只是我 2024-07-12 21:00:55

想要稍微扩展 Volmike 优秀的 jQuery 代码。

因此,通过这个,我们有一个非常非常酷和优雅的机制来实现通过在保存之前远离更新的数据来防止意外数据丢失的目标 - 即。 更新页面上的字段,然后单击按钮、链接甚至浏览器中的后退按钮,然后单击“保存”按钮。

您唯一需要做的就是向所有回发到网站的控件(尤其是“保存”按钮)添加一个“noWarn”类标记,这些控件要么保存,要么不删除任何更新的数据。

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

惊人的! 沃洛迈克干得好!

只需要 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'); });

});

Wanted to expand slightly on Volomike excellent jQuery code.

So with this, we have a very very cool and elegant mechanism to accomplish the objective of preventing inadvertent data loss through navigating away from updated data prior to saving – ie. updated field on a page, then click on a button, link or even the back button in the browser before clicking the Save button.

The only thing you need to do is add a “noWarn” class tag to all controls ( especially Save buttons ) that do a post back to the website, that either save or do not remove any updated data.

If the control causes the page to lose data, ie. navigates to the next page or clears the data – you do not need to do anything, as the scripts will automatically show the warning message.

Awesome! Well done Volomike!

Simply have the jQuery code as follows:

$(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'); });

});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文