所有表单上的 JavaScript 提交事件

JavaScript submit event on all forms?

本文关键字:JavaScript 提交 事件 表单      更新时间:2023-09-26

我试图捕获给定页面上所有表单上的提交事件(这是动态的)

到目前为止我得到了什么:

/**
* Capture form submits
*/
function addEvent(evnt, elem, func) {
    if (elem.addEventListener) {  // W3C DOM
        elem.addEventListener(evnt,func,false);
    } else if (elem.attachEvent) { // IE DOM
        elem.attachEvent("on"+evnt, func);
    } else { // No much to do
        elem[evnt] = func;
    }
}
var formsCollection = document.forms;
for(var i=0;i<formsCollection.length;i++) {
    //alert(formsCollection[i]);
    var form = document.forms[i];
    addEvent('submit', form, function(e) {
        var validated = true;
        // do form validation
        alert(i);
        if (!validated) {
            e.preventDefault();
        }
        return validated;
    });        
}

问题是这只捕获了最后一种形式。

有什么想法吗?

那里有几个问题。

最主要的是事件处理程序的所有副本都关闭在同一个i变量上。他们可以访问变量,而不是创建时变量的副本。所以他们都看到了循环结束后i。(更多:闭包并不复杂

通常的解决方法是有一个处理程序生成器函数:

for(var i=0;i<formsCollection.length;i++) {
    //alert(formsCollection[i]);
    var form = document.forms[i];
    addEvent('submit', form, makeHandler(form));
}
function makeHandler(form) {
    return function(e) {
        var validated = true;
        // do form validation using `form`
        if (!validated) {
            e.preventDefault();
        }
    };
}

第二个问题是您的addEvent无法正确处理旧版本的 IE。具体来说,您的处理程序依赖于能够调用e.preventDefault()(如果该函数不存在,则会引发异常),但这在您使用 attachEvent 时获得的事件对象上不存在。您也无法确保处理程序甚至具有事件对象,因为使用 attachEvent 的 IE 不会将事件对象作为参数传递;它是一个全局变量。

要解决此问题,您可以处理事件对象并提供preventDefault

function addEvent(evnt, elem, func) {
    if (elem.addEventListener) {  // W3C DOM
        elem.addEventListener(evnt,func,false);
    } else if (elem.attachEvent) { // IE DOM
        elem.attachEvent("on"+evnt, function(e) {
            e = e || window.event; // It won't be there, but just in case
            if (!e.preventDefault) {
                e.preventDefault = preventDefaultOnIE;
            }
            func.call(this, e);
        });
    } else { // No much to do    // <== I recommend throwing an exception here
        elem[evnt] = func;       //     or something, since your script won't work correctly
    }
}
function preventDefaultOnIE() {
    this.returnValue = false;
}

如果你想更彻底并且也有 stopPropagation ,请与上述preventDefault大致相同,并使用:

function stopPropagationOnIE() {
    this.cancelBubble = true;
}

你可能想考虑一些更简单的东西。提交事件(实际上是大多数事件)冒泡,这意味着您可以在 DOM 树中进一步处理它们,因此使用更少的事件处理程序。

例如:

addEvent('submit',document.body,function(e) {
    e = e || window.event;
    var form = e.srcElement || e.target; // cross-browser solution
    var validated = true;
    // do form validation
    alert("I am form number "+(function() {
        // the following is extreme hax, do NOT use this outside of testing!
        var forms = document.getElementsByTagName('form'), l = forms.length, i;
        for( i=0; i<l; i++) {
            if( form == forms[i]) return (i+1)+" of "+l;
        }
    })());
    if( !validated && e.preventDefault) e.preventDefault();
    return validated;
});