简体   繁体   English

通过javascript跟踪表单中的更改的最佳方法是什么?

[英]What is the best way to track changes in a form via javascript?

I'd like to track changes in inputs in a form via javascript. 我想通过javascript跟踪表单中输入的变化。 My intent is (but not limited) to 我的意图是(但不限于)

  • enable "save" button only when something has changed 只有在某些内容发生变化时才启用“保存”按钮
  • alert if the user wants to close the page and something is not saved 如果用户想要关闭页面并且未保存某些内容则发出警报

Ideas? 想法?

Loop through all the input elements, and put an onchange handler on each. 遍历所有输入元素,并在每个元素上放置一个onchange处理程序。 When that fires, set a flag which lets you know the form has changed. 当它触发时,设置一个标志,让您知道表单已更改。 A basic version of that would be very easy to set up, but wouldn't be smart enough to recognize if someone changed an input from "a" to "b" and then back to "a". 它的基本版本很容易设置,但是如果有人将输入从“a”更改为“b”然后再返回“a”,则不足以识别。 If it were important to catch that case, then it'd still be possible, but would take a bit more work. 如果抓住那个案件很重要,那么它仍然是可能的,但需要更多的工作。

Here's a basic example in jQuery: 这是jQuery中的一个基本示例:

$("#myForm")
    .on("input", function() {
        // do whatever you need to do when something's changed.
        // perhaps set up an onExit function on the window
        $('#saveButton').show();
    })
;

Text form elements in JS expose a .value property and a .defaultValue property, so you can easily implement something like: JS中的文本表单元素公开了.value属性和.defaultValue属性,因此您可以轻松实现以下内容:

function formChanged(form) {
  for (var i = 0; i < form.elements.length; i++) {
      if(form.elements[i].value != form.elements[i].defaultValue) return(true);
  }
  return(false);
}

For checkboxes and radio buttons see whether element.checked != element.defaultChecked , and for HTML <select /> elements you'll need to loop over the select.options array and check for each option whether selected == defaultSelected . 对于复选框和单选按钮,查看element.checked != element.defaultChecked ,对于HTML <select />元素,您需要循环遍历select.options数组并检查每个选项是否为selected == defaultSelected

You might want to look at using a framework like jQuery to attach handlers to the onchange event of each individual form element. 您可能希望使用类似jQuery的框架来将处理程序附加到每个单独表单元素的onchange事件。 These handlers can call your formChanged() code and modify the enabled property of your "save" button, and/or attach/detach an event handler for the document body's beforeunload event. 这些处理程序可以调用formChanged()代码并修改“save”按钮的enabled属性,和/或附加/分离文档正文的beforeunload事件的事件处理程序。

Try 尝试

function isModifiedForm(form){
  var __clone = $(form).clone();
  __clone[0].reset();
  return $(form).serialize() == $(__clone).serialize();
}

Hope its helps )) 希望它的帮助))

Here's a javascript & jquery method for detecting form changes that is simple. 这是一个用于检测表单更改的javascript和jquery方法,这很简单。 It disables the submit button until changes are made. 它会禁用提交按钮,直到进行更改。 It detects attempts to leave the page by means other than submitting the form. 它通过提交表单以外的方式检测离开页面的尝试。 It accounts for "undos" by the user, it is encapsulated within a function for ease of application, and it doesn't misfire on submit. 它由用户解释“撤消”,它被封装在一个功能中以便于应用,并且在提交时不会失败。 Just call the function and pass the ID of your form. 只需调用该函数并传递表单的ID即可。

This function serializes the form once when the page is loaded, and again before the user leaves the page. 此功能在加载页面时将表单序列化一次,并在用户离开页面之前再次序列化表单。 If the two form states are different, the prompt is shown. 如果两个表单状态不同,则会显示提示。

Try it out: http://jsfiddle.net/skibulk/ev5rE/ 尝试一下: http//jsfiddle.net/skibulk/ev5rE/

function formUnloadPrompt(formSelector) {
    var formA = $(formSelector).serialize(), formB, formSubmit = false;

    // Detect Form Submit
    $(formSelector).submit( function(){
        formSubmit = true;
    });

    // Handle Form Unload    
    window.onbeforeunload = function(){
        if (formSubmit) return;
        formB = $(formSelector).serialize();
        if (formA != formB) return "Your changes have not been saved.";
    };

    // Enable & Disable Submit Button
    var formToggleSubmit = function(){
        formB = $(formSelector).serialize();
        $(formSelector+' [type="submit"]').attr( "disabled", formA == formB);
    };

    formToggleSubmit();
    $(formSelector).change(formToggleSubmit);
    $(formSelector).keyup(formToggleSubmit);
}



// Call function on DOM Ready:

$(function(){
    formUnloadPrompt('form');
});

If your using a web app framework (rails, ASP.NET, Cake, symfony), there should be packages for ajax validation, 如果您使用的是Web应用程序框架(rails,ASP.NET,Cake,symfony),那么应该有用于ajax验证的软件包,

http://webtecker.com/2008/03/17/list-of-ajax-form-validators/ http://webtecker.com/2008/03/17/list-of-ajax-form-validators/

and some wrapper on onbeforeunload() to warn users taht are about to close the form: 和onbeforeunload()上的一些包装器警告用户taht即将关闭表单:

http://pragmatig.wordpress.com/2008/03/03/protecting-userdata-from-beeing-lost-with-jquery/ Detecting Unsaved Changes http://pragmatig.wordpress.com/2008/03/03/protecting-userdata-from-beeing-lost-with-jquery/ 检测未保存的更改

I answered a question like this on Ars Technica, but the question was framed such that the changes needed to be detected even if the user does not blur a text field (in which case the change event never fires). 我在Ars Technica上回答了类似这样的问题,但是这个问题被设置为即使用户没有模糊文本字段也需要检测到更改(在这种情况下,更改事件永远不会触发)。 I came up with a comprehensive script which: 我想出了一个全面的脚本:

  1. enables submit and reset buttons if field values change 如果字段值更改,则启用提交和重置按钮
  2. disables submit and reset buttons if the form is reset 如果重置表单,则禁用提交和重置按钮
  3. interrupts leaving the page if form data has changed and not been submitted 如果表单数据已更改且未提交,则中断离开页面
  4. supports IE 6+, Firefox 2+, Safari 3+ (and presumably Opera but I did not test) 支持IE 6 +,Firefox 2 +,Safari 3+(可能是Opera但我没有测试)

This script depends on Prototype but could be easily adapted to another library or to stand alone. 这个脚本取决于Prototype,但可以很容易地适应另一个库或独立。

$(document).observe('dom:loaded', function(e) {
    var browser = {
        trident: !!document.all && !window.opera,
        webkit: (!(!!document.all && !window.opera) && !document.doctype) ||
            (!!window.devicePixelRatio && !!window.getMatchedCSSRules)
    };

    // Select form elements that won't bubble up delegated events (eg. onchange)
    var inputs = $('form_id').select('select, input[type="radio"], input[type="checkbox"]');

    $('form_id').observe('submit', function(e) {
        // Don't bother submitting if form not modified
        if(!$('form_id').hasClassName('modified')) {
            e.stop();
            return false;
        }
        $('form_id').addClassName('saving');
    });

    var change = function(e) {
        // Paste event fires before content has been pasted
        if(e && e.type && e.type == 'paste') {
            arguments.callee.defer();
            return false;
        }

        // Check if event actually results in changed data
        if(!e || e.type != 'change') {
            var modified = false;
            $('form_id').getElements().each(function(element) {
                if(element.tagName.match(/^textarea$/i)) {
                    if($F(element) != element.defaultValue) {
                        modified = true;
                    }
                    return;
                } else if(element.tagName.match(/^input$/i)) {
                    if(element.type.match(/^(text|hidden)$/i) && $F(element) != element.defaultValue) {
                        modified = true;
                    } else if(element.type.match(/^(checkbox|radio)$/i) && element.checked != element.defaultChecked) {
                        modified = true;
                    }
                }
            });
            if(!modified) {
                return false;
            }
        }

        // Mark form as modified
        $('form_id').addClassName('modified');

        // Enable submit/reset buttons
        $('reset_button_id').removeAttribute('disabled');
        $('submit_button_id').removeAttribute('disabled');

        // Remove event handlers as they're no longer needed
        if(browser.trident) {
            $('form_id').stopObserving('keyup', change);
            $('form_id').stopObserving('paste', change);
        } else {
            $('form_id').stopObserving('input', change);
        }
        if(browser.webkit) {
            $$('#form_id textarea').invoke('stopObserving', 'keyup', change);
            $$('#form_id textarea').invoke('stopObserving', 'paste', change);
        }
        inputs.invoke('stopObserving', 'change', arguments.callee);
    };

    $('form_id').observe('reset', function(e) {
        // Unset form modified, restart modified check...
        $('reset_button_id').writeAttribute('disabled', true);
        $('submit_button_id').writeAttribute('disabled', true);
        $('form_id').removeClassName('modified');
        startObservers();
    });

    var startObservers = (function(e) {
        if(browser.trident) {
            $('form_id').observe('keyup', change);
            $('form_id').observe('paste', change);
        } else {
            $('form_id').observe('input', change);
        }
        // Webkit apparently doesn't fire oninput in textareas
        if(browser.webkit) {
            $$('#form_id textarea').invoke('observe', 'keyup', change);
            $$('#form_id textarea').invoke('observe', 'paste', change);
        }
        inputs.invoke('observe', 'change', change);
        return arguments.callee;
    })();

    window.onbeforeunload = function(e) {
        if($('form_id').hasClassName('modified') && !$('form_id').hasClassName('saving')) {
            return 'You have unsaved content, would you really like to leave the page? All your changes will be lost.';
        }
    };

});

I've used dirtyforms.js. 我用过dirtyforms.js。 Works well for me. 对我来说效果很好。

http://mal.co.nz/code/jquery-dirty-forms/ http://mal.co.nz/code/jquery-dirty-forms/

To alert the user before closing, use unbeforeunload: 要在关闭之前提醒用户,请使用unbeforeunload:

window.onbeforeunload = function() {
   return "You are about to lose your form data.";
};

I would store each fields value in a variable when the page loads, then compare those values when the user unloads the page. 我会在页面加载时将每个字段值存储在变量中,然后在用户卸载页面时比较这些值。 If any differences are detected you will know what to save and better yet, be able to specifically tell the user what data will not be saved if they exit. 如果检测到任何差异,您将知道要保存的内容并且更好,能够专门告诉用户退出时不会保存哪些数据。

// this example uses the prototype library
// also, it's not very efficient, I just threw it together
var valuesAtLoad = [];
var valuesOnCheck = [];
var isDirty = false;
var names = [];
Event.observe(window, 'load', function() {
    $$('.field').each(function(i) {
        valuesAtLoad.push($F(i));
    });
});

var checkValues = function() {
    var changes = [];
    valuesOnCheck = [];
    $$('.field').each(function(i) {
        valuesOnCheck.push($F(i));
    });

    for(var i = 0; i <= valuesOnCheck.length - 1; i++ ) {
        var source = valuesOnCheck[i];
        var compare = valuesAtLoad[i];
        if( source !== compare ) {
            changes.push($$('.field')[i]);
        }
    }

    return changes.length > 0 ? changes : [];
};

setInterval(function() { names = checkValues().pluck('id'); isDirty = names.length > 0; }, 100);

// notify the user when they exit
Event.observe(window, 'beforeunload', function(e) {
     e.returnValue = isDirty ? "you have changed the following fields: \r\n" + names + "\r\n these changes will be lost if you exit. Are you sure you want to continue?" : true;
});

如果您愿意使用jQuery,请参阅我的回答类似的问题: 禁用提交按钮,除非原始表单数据已更改

Attach an event handler to each form input/select/textarea's onchange event. 将事件处理程序附加到每个表单输入/ select / textarea的onchange事件。 Setting a variable to tell you if you should enable the "save" button. 设置变量以告诉您是否应启用“保存”按钮。 Create an onunload hander that checks for a dirty form too, and when the form is submitted reset the variable: 创建一个onunload hander来检查脏表单,并在提交表单时重置变量:

window.onunload = checkUnsavedPage;
var isDirty = false;
var formElements = //Get a reference to all form elements
for(var i = 0; len = formElements.length; i++) {
    //Add onchange event to each element to call formChanged()
}

function formChanged(event) {
    isDirty = false;
    document.getElementById("savebtn").disabled = "";
}

function checkUnsavedPage() {
    if (isDirty) {
        var isSure = confirm("you sure?");  
        if (!isSure) {
            event.preventDefault();
        }
    }
}

Here's a full implementation of Dylan Beattie's suggestion : 以下是Dylan Beattie建议的全面实施:

Client/JS Framework for "Unsaved Data" Protection? “未保存数据”保护的客户端/ JS框架?

You shouldn't need to store initial values to determine if the form has changed, unless you're populating it dynamically on the client side (although, even then, you could still set up the default properties on the form elements). 您不需要存储初始值来确定表单是否已更改,除非您在客户端动态填充它(尽管如此,您仍然可以在表单元素上设置default属性)。

I had the same challenge and i was thinking of a common solution. 我遇到了同样的挑战,我正在考虑一个共同的解决方案。 The code below is not perfect, its from initial r&d. 下面的代码并不完美,它来自最初的研发。 Following are the steps I used: 以下是我使用的步骤:

1) Move the following JS to a another file (say changeFramework.js) 1)将以下JS移动到另一个文件(比如changeFramework.js)

2) Include it in your project by importing it 2)通过导入将其包含在项目中

3) In your html page, whichever control needs monitoring, add the class "monitorChange" 3)在你的html页面中,无论哪个控件都需要监控,添加类“monitorChange”

4) The global variable 'hasChanged' will tell, if there is any change in the page you working on. 4)全局变量'hasChanged'将告诉您,如果您正在处理的页面有任何变化。

<script type="text/javascript" id="MonitorChangeFramework">
// MONITOR CHANGE FRAMEWORK
// ALL ELEMENTS WITH CLASS ".monitorChange" WILL BE REGISTERED FOR CHANGE
// ON CHANGE IT WILL RAISE A FLAG
var hasChanged;

function MonitorChange() {
    hasChanged = false;
    $(".monitorChange").change(function () {
        hasChanged = true;
    });
}

Following are the controls where I used this framework: 以下是我使用此框架的控件:

<textarea class="monitorChange" rows="5" cols="10" id="testArea"></textarea></br>
        <div id="divDrinks">
            <input type="checkbox" class="chb monitorChange" value="Tea" />Tea </br>
            <input type="checkbox" class="chb monitorChange" value="Milk" checked='checked' />Milk</br>
            <input type="checkbox" class="chb monitorChange" value="Coffee" />Coffee </br>
        </div>
        <select id="comboCar" class="monitorChange">
            <option value="volvo">Volvo</option>
            <option value="saab">Saab</option>
            <option value="mercedes">Mercedes</option>
            <option value="audi">Audi</option>
        </select>
        <button id="testButton">
            test</button><a onclick="NavigateTo()">next >>> </a>

I believe there can be huge improvement in this framework. 我相信这个框架可以有很大的改进。 Comment/Changes/feedbacks are welcome. 欢迎提出意见/变更/反馈。 :) :)

I did some Cross Browser Testing. 我做了一些跨浏览器测试。

On Chrome and Safari this is nice: 在Chrome和Safari上这很不错:

<form onchange="validate()">
...
</form>

For Firefox + Chrome/Safari I go with this: 对于Firefox + Chrome / Safari,我这样做:

<form onkeydown="validate()">
    ...
    <input type="checkbox" onchange="validate()">
</form>

Items like checkboxes or radiobuttons need an own onchange event listener. 复选框或单选按钮等项目需要一个自己的onchange事件监听器。

You can also check out this jQuery plugin I built at jQuery track changes in forms plugin 您还可以查看我在jQuery跟踪表单插件中更改的jQuery插件

See the demo here and download the JS here 请在此处查看演示并在此处下载JS

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在MongoDB中跟踪文档属性更改的最佳方法是什么? - What is the best way to keep track of changes of a document's property in MongoDB? 跟踪大型输入形式中的更改的最快方法(Javascript / jQuery) - Fastest (Javascript/jQuery) way to track changes in a large input form 进行原型制作时跟踪javascript对象引用的最佳方法是什么 - What the best way to keep track of a javascript object reference when prototyping React 跟踪对象数组更改的最佳方式 - React best way to track changes to an array of objects 通过 JavaScript 检查网站是否启动的最佳方法是什么 - What's the best way to check if a website is up or not via JavaScript 通过javascript修改网址的最佳方法是什么? - What's the best way to amend a url via javascript? 通过Javascript检查加载控制状态的最佳方法是什么 - What is the best way to check control state on load via Javascript 在Aframe中跟踪传送位置的最佳方法是什么? - What is the best way to track teleport position in Aframe? 跟踪Java中方法调用的最佳方法 - The best way to track method invocation in Javascript 将 django 表单数据传递给 javascript ajax 调用的最佳方法是什么? - What is the best way to pass django form data to javascript ajax call?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM