Javascript 提醒表单中未保存的更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11844256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:20:09  来源:igfitidea点击:

Alert for unsaved changes in form

javascriptjquery

提问by user1181942

I want to write Jquery code in master file, so that if there if user changes page and there is any unsaved changes user should get alert. I got one answer from this: link

我想在主文件中编写 Jquery 代码,以便如果用户更改页面并且有任何未保存的更改用户应该收到警报。我从中得到了一个答案:链接

However in most solution I will have to write code on all pages. I want it to write only at one place so that everybody dont have to worry to write it in their modules. My code is like:

但是,在大多数解决方案中,我必须在所有页面上编写代码。我希望它只写在一个地方,这样每个人都不必担心在他们的模块中编写它。我的代码是这样的:

<script type="text/javascript">
    var isChange;
    $(document).ready(function () {
        $("input[type='text']").change(function () {
            isChange = true;
        })
    });
    $(window).unload(function () {
        if (isChange) {
            alert('Handler for .unload() called.');
        }
    });

</script>

But everytime i make changes in text boxes .change() event is not firing.

但是每次我在文本框中进行更改时,都不会触发 .change() 事件。

What can be wrong in the code?

代码中有什么问题?

EDIT: I changed .change() to .click and it is fired. i am using jquery 1.4.1..is it because of jquery version that change() is not working?

编辑:我将 .change() 更改为 .click 并被触发。我正在使用 jquery 1.4.1 ..是不是因为 jquery 版本的 change() 不起作用?

回答by AlphaMale

This is what i am using, Put all this code in a separate JS file and load it in your header file so you will not need to copy this again and again:

这就是我正在使用的,将所有这些代码放在一个单独的 JS 文件中并将其加载到您的头文件中,这样您就不需要一次又一次地复制它:

var unsaved = false;

$(":input").change(function(){ //triggers change in all input fields including text type
    unsaved = true;
});

function unloadPage(){ 
    if(unsaved){
        return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
    }
}

window.onbeforeunload = unloadPage;

EDIT for $ not found:

未找到 $ 的编辑:

This error can only be caused by one of three things:

此错误只能由以下三种情况之一引起:

  1. Your JavaScript file is not being properly loaded into your page
  2. You have a botched version of jQuery. This could happen because someone edited the core file, or a plugin may have overwritten the $ variable.
  3. You have JavaScript running before the page is fully loaded, and as such, before jQuery is fully loaded.
  1. 您的 JavaScript 文件未正确加载到您的页面中
  2. 你有一个拙劣的 jQuery 版本。这可能是因为有人编辑了核心文件,或者插件可能覆盖了 $ 变量。
  3. 您在页面完全加载之前运行 JavaScript,因此,在 jQuery 完全加载之前。

Make sure all JS code is being placed in this:

确保所有的 JS 代码都放在这个:

$(document).ready(function () {
  //place above code here
});

Edit for a Save/Send/Submit Button Exception

编辑保存/发送/提交按钮异常

$('#save').click(function() {
    unsaved = false;
});

Edit to work with dynamic inputs

编辑以使用动态输入

// Another way to bind the event
$(window).bind('beforeunload', function() {
    if(unsaved){
        return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
    }
});

// Monitor dynamic inputs
$(document).on('change', ':input', function(){ //triggers change in all input fields including text type
    unsaved = true;
});

Add the above code in your alert_unsaved_changes.js file.

在您的 alert_unsaved_changes.js 文件中添加上述代码。

Hope this helps.

希望这可以帮助。

回答by fabien-michel

A version that use serialization of the form :

使用表单序列化的版本:

Execute this code, when dom ready :

当dom准备好时执行此代码:

// Store form state at page load
var initial_form_state = $('#myform').serialize();

// Store form state after form submit
$('#myform').submit(function(){
  initial_form_state = $('#myform').serialize();
});

// Check form changes before leaving the page and warn user if needed
$(window).bind('beforeunload', function(e) {
  var form_state = $('#myform').serialize();
  if(initial_form_state != form_state){
    var message = "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
    e.returnValue = message; // Cross-browser compatibility (src: MDN)
    return message;
  }
});

If the user change a field then manually rollback, no warn is displayed

如果用户更改字段然后手动回滚,则不会显示警告

回答by WTK

changeevent is fired once the user blurs from input not on every single character inputed.

一旦用户从输入中模糊而不是在输入的每个字符上,就会触发change事件。

If you need it to be called every time something is changed (even if focus is still in that input field) you would have to rely on combination of keyupand bunch of events to keep track of pasting/cuting using mouse only.

如果您需要在每次更改某些内容时调用它(即使焦点仍在该输入字段中),您将不得不依赖keyup和一系列事件的组合来跟踪仅使用鼠标的粘贴/剪切。

P.S. I hope you're aware that your approach to detecting changes isn't the best one? If user input some text, leaves the field and then reverts the changes the script would still alert him about modified text.

PS 我希望你知道你检测变化的方法不是最好的方法吗?如果用户输入一些文本,离开该字段然后恢复更改,脚本仍会提醒他有关修改的文本。

回答by sedran

you should register events for not only inputs but also textareas, if you mean textarea with text box. You can use keyup for isChange, so that you don't wait for user to blur from this area.

如果您指的是带有文本框的 textarea,您不仅应该为输入注册事件,还应该为 textarea 注册事件。您可以将 keyup 用于 isChange,这样您就不必等待用户从该区域模糊。

$("input[type='text'], textarea").keyup(function () {
    isChange = true;
})

回答by Elias Van Ootegem

Why not simply bind the event to the changecallback?

为什么不简单地将事件绑定到change回调?

$(":input").change(function()
{
    $(window).unbind('unload').bind('unload',function()
    {
        alert('unsaved changes on the page');
    });
});

As an added bonus, you can use confirmand select the last element that triggered the change event:

作为额外的奖励,您可以使用confirm并选择触发更改事件的最后一个元素:

$(":input").change(function()
{
    $(window).unbind('unload').bind('unload',(function(elem)
    {//elem holds reference to changed element
        return function(e)
        {//get the event object:
            e = e || window.event;
            if (confirm('unsaved changes on the page\nDo you wish to save them first?'))
            {
                elem.focus();//select element
                return false;//in jQuery this stops the event from completeing
            }
        }
    }($(this)));//passed elem here, I passed it as a jQ object, so elem.focus() works
    //pass it as <this>, then you'll have to do $(elem).focus(); or write pure JS
});

If you have some save button, make sure that that unbinds the unload event, though:

如果您有一些保存按钮,请确保取消绑定卸载事件,但:

$('#save').click(function()
{
    $(window).unbind('unload');
    //rest of your code here
});

回答by Eric Anderson

This is really just a different version of @AlphaMale's answer but improved in a few ways:

这实际上只是@AlphaMale 答案的不同版本,但在几个方面有所改进:

# Message displayed to user. Depending on browser and if it is a turbolink,
# regular link or user-driven navigation this may or may not display.
msg = "This page is asking you to confirm that you want to leave - data you have entered may not be saved."

# Default state
unsaved = false

# Mark the page as having unsaved content
$(document).on 'change', 'form[method=post]:not([data-remote]) :input', -> unsaved = true

# A new page was loaded via Turbolinks, reset state
$(document).on 'page:change', -> setTimeout (-> unsaved = false), 10

# The user submitted the form (to save) so no need to ask them.
$(document).on 'submit', 'form[method=post]', ->
  unsaved = false
  return

# Confirm with user if they try to go elsewhere
$(window).bind 'beforeunload', -> return msg if unsaved

# If page about to change via Turbolinks also confirm with user
$(document).on 'page:before-change', (event) ->
  event.preventDefault() if unsaved && !confirm msg

This is better in the following ways:

这在以下方面更好:

  • It is coffeescript which IMHO automatically makes it better. :)
  • It is entirely based on event bubbling so dynamic content is automatically handled (@AlphaMale's update also has this).
  • It only operates on POST forms as GET forms do not have data we typically want to avoid loosing (i.e. GET forms tend to be search boxes and filtering criteria).
  • It doesn't need to be bound to a specific button for carrying out the save. Anytime the form is submitted we assume that submission is saving.
  • It is Turbolinkscompatible. If you don't need that just drop the two page:event bindings.
  • It is designed so that you can just include it with the rest of your JS and your entire site will be protected.
  • 恕我直言,它是咖啡脚本,它会自动使它变得更好。:)
  • 它完全基于事件冒泡,因此会自动处理动态内容(@AlphaMale 的更新也有这个)。
  • 它只在 POST 表单上运行,因为 GET 表单没有我们通常想要避免丢失的数据(即 GET 表单往往是搜索框和过滤条件)。
  • 它不需要绑定到执行保存的特定按钮。无论何时提交表单,我们都假定提交正在保存。
  • 它与Turbolinks兼容。如果您不需要,只需删除两个page:事件绑定。
  • 它的设计使您可以将它包含在 JS 的其余部分中,并且您的整个站点都将受到保护。

回答by Chalky

I use $('form').changeetc. function to set a dirty bit variable. Not suitable to catch all changes (as per previous answers), but catches all that I'm interested in, in my app.

我使用$('form').changeetc. 函数来设置一个脏位变量。不适合捕获所有更改(根据之前的答案),但会在我的应用中捕获所有我感兴趣的内容。