Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
412 views
in Technique[技术] by (71.8m points)

javascript - 在离开网页之前进行未保存的更改之前警告用户(Warn user before leaving web page with unsaved changes)

I have some pages with forms in my application.

(我的应用程序中有一些带有表单的页面。)

How can I secure the form in such a way that if someone navigates away or closes the browser tab, they should be prompted to to confirm they really want to leave the form with unsaved data?

(我如何以某种方式保护表单,如果有人导航或关闭浏览器选项卡,应该提示他们确认他们确实要保留未保存的数据?)

  ask by Khan translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Short, wrong answer:(简短错误的答案:)

You can do this by handling the beforeunload event and returning a non-null string :

(您可以通过处理beforeunload事件并返回一个非null字符串来做到这一点:)

window.addEventListener("beforeunload", function (e) {
    var confirmationMessage = 'It looks like you have been editing something. '
                            + 'If you leave before saving, your changes will be lost.';

    (e || window.event).returnValue = confirmationMessage; //Gecko + IE
    return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});

The problem with this approach is that submitting a form is also firing the unload event .

(这种方法的问题在于, 提交表单也会触发unload事件 。)

This is fixed easily by adding the a flag that you're submitting a form:

(通过添加要提交表单的标志,可以轻松解决此问题:)

var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

Then calling the setter when submitting:

(然后在提交时调用设置器:)

<form method="post" onsubmit="setFormSubmitting()">     
    <input type="submit" />
</form>

But read on...

(但是请继续阅读...)

Long, correct answer:(长而正确的答案:)

You also don't want to show this message when the user hasn't changed anything on your forms .

(当用户未更改表单上的任何内容时,您也不想显示此消息。)

One solution is to use the beforeunload event in combination with a "dirty" flag, which only triggers the prompt if it's really relevant.

(一种解决方案是将beforeunload事件与“脏”标志结合使用,该标志仅在确实相关时才触发提示。)

var isDirty = function() { return false; }

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting || !isDirty()) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

Now to implement the isDirty method, there are various approaches.

(现在要实现isDirty方法,有多种方法。)

You can use jQuery and form serialization , but this approach has some flaws.

(您可以使用jQuery和表单序列化 ,但是这种方法有一些缺陷。)

First you have to alter the code to work on any form ( $("form").each() will do), but the greatest problem is that jQuery's serialize() will only work on named, non-disabled elements, so changing any disabled or unnamed element will not trigger the dirty flag.

(首先,您必须更改代码以使用任何形式( $("form").each()都可以),但是最大的问题是jQuery的serialize()仅适用于命名的非禁用元素,因此更改任何禁用或未命名的元素都不会触发脏标志。)

There are workarounds for that , like making controls readonly instead of enabling, serializing and then disabling the controls again.

(有一些解决方法 ,例如将控件设为只读而不是启用,序列化然后再次禁用控件。)

So events seem the way to go.

(因此,事件似乎是路要走。)

You can try listening for keypresses .

(您可以尝试收听按键 。)

This event has a few issues:

(此事件有几个问题:)

  • Won't trigger on checkboxes, radio buttons, or other elements that are being altered through mouse input.

    (不会触发复选框,单选按钮或通过鼠标输入更改的其他元素。)

  • Will trigger for irrelevant keypresses like the Ctrl key.

    (将触发不相关的按键,例如Ctrl键。)

  • Won't trigger on values set through JavaScript code.

    (不会触发通过JavaScript代码设置的值。)

  • Won't trigger on cutting or pasting text through context menus.

    (通过上下文菜单剪切或粘贴文本不会触发。)

  • Won't work for virtual inputs like datepickers or checkbox/radiobutton beautifiers which save their value in a hidden input through JavaScript.

    (不适用于日期选择器或复选框/单选按钮美化器之类的虚拟输入,这些虚拟输入通过JavaScript将其值保存在隐藏的输入中。)

The change event also doesn't trigger on values set from JavaScript code , so also won't work for virtual inputs.

(change事件不会触发JavaScript代码设置的值 ,因此也不适用于虚拟输入。)

Binding the input event to all input s (and textarea s and select s) on your page won't work on older browsers and, like all event handling solutions mentioned above, doesn't support undo.

(input事件绑定到页面上的所有input s(以及textareaselect s) 在旧版浏览器上将不起作用,并且像上述所有事件处理解决方案一样,不支持撤消。)

When a user changes a textbox and then undoes that, or checks and unchecks a checkbox, the form is still considered dirty.

(当用户更改文本框然后撤消该文本框,或者选中并取消选中一个复选框时,该表单仍被认为是脏表单。)

And when you want to implement more behavior, like ignoring certain elements, you'll have even more work to do.

(当您想要实现更多的行为时,例如忽略某些元素,您将需要做更多的工作。)

Don't reinvent the wheel:(不要重新发明轮子:)

So before you think about implementing those solutions and all required workarounds, realize you're reinventing the wheel and you're prone to running into problems others have already solved for you.

(因此,在考虑实施这些解决方案和所有必需的变通办法之前,请先意识到自己正在重新发明轮子,并且容易遇到其他人已经为您解决的问题。)

If your application already uses jQuery, you may as well use tested, maintained code instead of rolling your own, and use a third-part library for all of this.

(如果您的应用程序已经使用jQuery,则最好使用经过测试,维护的代码,而不是滚动自己的代码,并为此使用第三方库。)

jQuery's Are You Sure?

(jQuery的确定吗?)

plugin works great, see their demo page .

(插件效果很好,请参见其演示页面 。)

It's as simple as this:

(就这么简单:)

<script src="jquery.are-you-sure.js"></script>

<script>
  $(function() {
    $('#myForm').areYouSure(
      {
        message: 'It looks like you have been editing something. '
               + 'If you leave before saving, your changes will be lost.'
      }
    );
  });

</script>

Custom messages not supported everywhere(各地都不支持自定义消息)

Do note that Firefox 4 didn't support custom messages in this dialog.

(请注意, Firefox 4在此对话框中不支持自定义消息。)

As of last month, Chrome 51 is being rolled out in which custom messages are also being removed .

(从上个月开始,Chrome 51即将推出,其中自定义消息也将被删除 。)

<

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...