1

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

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

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

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

有任何想法吗?

4

2 回答 2

2

那里有几个问题。

主要的一个是事件处理程序的所有副本都关闭在同一个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. 您也不能确保处理程序甚至具有事件对象,因为 IE usingattachEvent不会将事件对象作为参数传递;它是一个全局变量。

要解决这个问题,您可以处理事件对象并提供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;
}
于 2013-11-07T17:26:18.587 回答
0

您可能想考虑一些更简单的东西。提交事件(实际上是大多数事件)冒泡,这意味着您可以在 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;
});
于 2013-11-07T17:26:55.430 回答