最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - How to javascript submit in the presence of an input id equal to 'submit' - Stack Overflow

programmeradmin2浏览0评论

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: / (Here's the behavior if there's no <input id="submit">: /

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).

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/q68ky/ (Here's the behavior if there's no <input id="submit">: http://jsfiddle/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).

Share Improve this question edited Dec 16, 2010 at 20:29 Yahel asked Dec 16, 2010 at 20:23 YahelYahel 37.3k23 gold badges106 silver badges154 bronze badges 3
  • I know an ideal world, I should never create id="submit" on an input form, but I can't guarantee that it won't exist. – Yahel Commented Dec 16, 2010 at 20:25
  • 1 @ys, you do understand that this code will result in an endless loop right ? – Gabriele Petrioli Commented Dec 16, 2010 at 20:47
  • @Gaby no, form.submit() is triggering submit on the DOM element, not the jQuery element. if it was $(form).submit(); you'd be right, and I'd need to unbind the jQuery handler, like here: jsfiddle/LKUhV. Also, as you see on the original jsfiddle, it doesn't result in an infinite loop of alert() being triggered. – Yahel Commented Dec 16, 2010 at 20:49
Add a ment  | 

5 Answers 5

Reset to default 4

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/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.

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

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./ticket/1414

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).

The error occurs if a form element's name or id is 'submit'. It looks like it's an issue with jQuery.

发布评论

评论列表(0)

  1. 暂无评论