问题
I've been binding submit events to forms, and ensuring that they do not break the form, using jQuery like this:
jQuery('form').submit(function(e){
var form = this;
e.preventDefault();
alert('1');
setTimeout(function() {
alert('2');
form.submit();
}, 1000);
});
This is all good and well, except, if for some reason a front end developer gave a child input of this form an id of ="submit", this breaks, as form.submit()
throws a JavaScript error (In Chrome, 'Uncaught TypeError: Property 'submit' of object # is not a function').
You can see an example of that happening here: http://jsfiddle.net/q68ky/ (Here's the behavior if there's no <input id="submit">
: http://jsfiddle.net/JpXzL/
Now, I know I can prevent this from binding on forms that have children with an id of 'submit' with jQuery('form').not(:has('#submit')).submit()
, and the form will process just fine, but my binding will never fire for those forms.
So, the question: How can I safely bind this jQuery function to all forms, including those with <input id="submit">
?
EDIT: Worth noting that this problem doesn't go away if I unbind the submit handler and then trigger a jQuery submit on jQuery(form)
.
回答1:
The only way I can think of:
(function () {
var method;
window.submit = function (theForm) {
if (!method) {
method = document.createElement("form").submit;
}
method.call(theForm);
};
}());
Then call submit(theFormYouWantToSubmit)
.
You can see it in action here: http://jsfiddle.net/q68ky/2/
Edit: To provide some explanation as to what this does....
This method creates a new form element (document.createElement("form")
), and stores a reference to the "submit" attribute of it (method = document.createElement("form").submit
). Because this is a newly created form element, with no child nodes, we can guarantee that the "submit" attribute is actually the "submit" method we need, rather than a child node with an id/name of "submit".
We then use the call method (part of Function.prototype
), which sets the context of the submit
method to the form we want to submit, rather than the window
object, which is what it would otherwise be on.
The rest of the gubbins in the snippet caches the submit
method, so that all of this (albeit small) overhead does not take place every time you want to submit the form, and captures the cached method in a local scope, instead of holding it in the global scope and polluting the global namespace.
回答2:
As this is actually a non-jQuery problem, here is a non-jQuery solution:
HTMLFormElement.prototype.submit.call(form);
DEMO
Reference: HTMLFormElement
Update: Access to the DOM prototypes is only possible in IE8+. (and that is probably the reason why jQuery does not use it).
@Matt's answer instead should work in any browser
回答3:
In addition the problem I identified in my other answer, there is an open jQuery bug exacerbating the issue:
.SUBMIT() CAN FAIL IF SOMETHING HAS ID="SUBMIT"
If an element with an ID of submit exists in a form, .submit() can fail. It's important that this function (in particular) work correctly.
http://bugs.jquery.com/ticket/1414
回答4:
Instead of form.submit();
, you need
$(form).submit();
This is because form
is just the bare DOM element, while $(form)
is the jQuery object. Calling form.submit()
is trying to access the submit
property of form
. Since it doesn't have one, it's defaulting to the old-school behavior of getting the child element whose id
is submit
(hence the "is not a function" error).
回答5:
The error occurs if a form element's name or id is 'submit'. It looks like it's an issue with jQuery.
来源:https://stackoverflow.com/questions/4465028/how-to-javascript-submit-in-the-presence-of-an-input-id-equal-to-submit