input type="submit", onclick handler calls this.form.submit(), and returns no value

11,250

Solution 1

Gecko (Firefox) certainly detects multiple submissions and cancels older ones when new ones happen. See the mPendingSubmisson member in http://hg.mozilla.org/mozilla-central/file/c4abfca219e5/content/html/content/src/nsHTMLFormElement.h and the handling of it in http://hg.mozilla.org/mozilla-central/file/c4abfca219e5/content/html/content/src/nsHTMLFormElement.cpp (e.g. in nsHTMLFormElement::Submit and nsHTMLFormElement::PostHandleEvent (the latter being what gets called from the default action stuff for submit controls).

In terms of what the spec says, it's not clear to me that the spec is necessarily sane, but it lives at http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#concept-form-submit and suggests that both submissions would happen, but the later might effectively cancel the earlier because of internal details of the "navigate" algorithm. I filed https://www.w3.org/Bugs/Public/show_bug.cgi?id=20580 to sort the spec out.

Solution 2

This is w3 org recommendation that:

  • If a form contains more than one submit button, only the activated submit button is successful.

    Same is there with Submit Click and local JS form.Submit function , only the "submit" is activated not form.submit function. Because submit is primary and JS function is secondary..
    you can learn more here link
Share:
11,250

Related videos on Youtube

Hephaestus
Author by

Hephaestus

Updated on June 04, 2022

Comments

  • Hephaestus
    Hephaestus almost 2 years

    EDIT: Please read carefully all the way through the question before you consider answering it. I am not asking about the advisability of using an inline event handler in production code, nor am I asking about the best way to achieve the result promised by the article I reference. This is a question about Javascript semantics and browser implementation details, not about best coding practices.

    Sounds like a nightmare, right?

    Yet I found some online advice that advocates doing just such a thing to prevent double-submission of a form:

    <input type="submit" 
           onclick="this.disabled=true;
                    this.value='Sending, please wait...';
                    this.form.submit();" />
    

    Leaving aside any discussion of the evils of inline event handlers, the problems I see here are:

    1. The type of the tag is "submit", so submitting its containing form is its default behavior;
    2. The onclick handler explicitly submits the containing form;
    3. The onclick handler doesn't return false to prevent the default behavior (see 1).

    Intuitively, I would think that a click on this item would do exactly the opposite of what the article claims -- i.e., submit the form twice, once as a result of the explicit submit() call, and then once more as the unsuppressed default behavior of the "submit"-typed control.

    On the other hand, I wrote a tiny PHP script (below) and tried it out with both Firefox and Safari (at the moment my only conveniently available browsers), and it only writes a single log entry per click on the button:

    <html>
    <head></head>
    <body>
    <?php
      if (isset($_GET['action']) && $_GET['action'] == 'submit') {
        $s = 'Got form submission at ' . time();
        error_log($s);
        echo $s;
      }
      else {
    ?>
      <form action="http://localhost/~hephaestus/phptests/submittest.php?action=submit" 
            method="post">
        <input type="submit" 
               onclick="this.disabled=true;
                        this.value='Sending, please wait...';
                        this.form.submit();" />
      </form>
    <?php
      }
    ?>
    </body>
    </html>
    

    So are these two browsers actually doing the "right" thing (where "right" is defined in some document that I either haven't seen or haven't read closely enough) -- meaning that my analysis of the problems is incomplete or wrong?

    Or, is my analysis correct -- meaning that the observed single submissions are the result of the browser implementers putting in special-case logic, to save naive coders from themselves?

    UPDATE:

    In an effort to empirically test out the claim by @sourcecode that the form.submit() method is some sort of "second submit button" on a form, and is thus subject to the rule stated in section 17.13.2 of the HTML4 spec that there can only be one "successful" submit button, I made a few additions to my PHP test script:

    <?php
      if (isset($_GET['action']) && $_GET['action'] == 'submit') {
        $s = 'Got form submission at ' . time() . ', tellme = ' . $_POST['tellme'];
        error_log($s);
        echo $s;
      }
      else {
    ?>
      <form action="http://localhost/~hephaestus/phptests/submittest.php?action=submit" 
            method="post">
        <input type="hidden" id="tellme" name="tellme" value="0" />
        <input type="submit" 
               onclick="this.disabled=true;
                        this.value='Sending, please wait...';
                        this.form.submit();
                        document.getElementById('tellme')=1;" />
      </form>
    <?php
      }
    ?>
    

    In Firefox, this code produces the single error-log entry:

    Got form submission at timestamp, tellme = 1

    which does suggest that the method-invocation is somehow being superseded by the intrinsic event-driven behavior of the control.

    Furthermore, if I include an additional return false; after setting the value of tellme to 1 (thereby preventing the click event from propagating, and thus preventing the intrinsic behavior of the control), the single error-log entry is:

    Got form submission at timestamp, tellme = 0

    meaning that in this case, the submission was the result of the invocation of this.form.submit().

    On the other hand, when I try the same two variations in Safari, each of them gives me the same single error-log entry:

    Got form submission at timestamp, tellme = 0

    So in the case of Safari, the method invocation always takes precedence over the event-driven submission -- presumably because it happens earlier.

    That's. Just. Awesome. :-/

    Further update: I got a chance to test this on IE 8.0 on Windows NT 5.1.

    IE 8 mirrors the behavior of Safari, i.e., the form.submit() method always takes precedence over the even-driven submit.

    Although it's hardly relevant today, I also realized that I have an ancient IE 5.22 on an even more ancient PowerPC iMac running OS X 10.4.11. The interesting bit of historical trivia here is that IE5 works exactly opposite to the way IE8 works: the event-driven submit always supersedes the form.submit() method -- even when the click event has been inhibited from propagating by a return false; at the end of the onclick handler! (I haven't delved into whether this is a bug or a feature, though. I haven't yet -- and may never! -- run a test to determine whether it's botching the event inhibition, or trying to do something "smart".)

    Still, regardless of the inconsistencies, both of the IEs only do a single submission.

    My tentative (well, by now, actually pretty firm) conclusion is that the precise relationship between a "submit"-typed control and the DOM form.submit() method isn't well-defined, and that browser implementers, in the absence of any explicit guidance, generally do what they think best (see @Boris Zbarsky's answer, for example).

    At least in the cases of Firefox, Safari and IE, their implementers foresaw the possibility that both an event and a method call might compete to submit the same form, and took steps (albeit different ones -- pretty much running the gamut) to ensure that only one of them would succeed.

    (I'd still welcome additional answers from folks who know different browser internals well enough to comment, or who've loaded my simple PHP script using browsers other than those I've tested.)

    • elclanrs
      elclanrs over 11 years
      When inline JavaScript looks like that is time to think about separating logic and markup...
    • Hephaestus
      Hephaestus over 11 years
      Right, but you'll notice that I said "Leaving aside any discussion of the evils of inline event handlers..." This question is about something else altogether, i.e., Javascript semantics and browser implementation.
  • Hephaestus
    Hephaestus over 11 years
    However, my simple test shows that I get precisely the promised result (single submission only) without returning false or calling stopPropagation() -- the question is: WHY?
  • Hephaestus
    Hephaestus over 11 years
    Hmm... You might very well be right about the form.submit() method being superseded by the intrinsic action of the "successful" submit button -- but the W3C document you've cited doesn't provide a concrete statement that such is the case. If you can provide a reference to a document that specifically addresses this "primary/secondary" relationship that you're referring to between the intrinsic behavior of the control and the DOM element method, I just might accept your answer.
  • Hephaestus
    Hephaestus over 11 years
    Once again, I must point out that I'm not asking about the advisability of doing what the article suggests. I'm asking WHY it empirically works the way it does on the two browsers I've tested it with.
  • mplungjan
    mplungjan over 11 years
    I cannot tell you except I shudder at the code they presented
  • sourcecode
    sourcecode over 11 years
    primary events are what that invoke directly without using any JS, example- form submission on submit-button click , while secondary events are formed when the JS makes something to get execute like form.submit(), and W3C document has provided this concrete statement - under my given link(Successful controls - 2nd pt) And This primary/sec relationship is invented by me to just explain u....:)
  • Hephaestus
    Hephaestus over 11 years
    Likewise! :-) Certainly your "unobtrusive" style example is a superior way to organize the code, and I particularly like the wholesale replacement of the button with the "please wait" text.
  • Hephaestus
    Hephaestus over 11 years
    Sorry, I still don't quite buy it. Section 17.13.2 of that document only addresses controls, not DOM element methods. Bullet point 2 of section 17.13.2 only addresses submit buttons, not the form.submit() method. So while it might be reasonable to infer that DOM element methods fall under the same general rules as controls, it would still be nothing more than an inference until backed up by some explicit statement that addresses the relationship between controls and DOM element methods head-on.
  • Hephaestus
    Hephaestus over 11 years
    Good information here, thanks. It's somewhat telling that in the nsHTMLFormElement::Submit() method, where they check the mPendingSubmission member and clear it if it's already set, they have a comment that says "we emulate IE here" (a rather scary thought! :-), instead of something like "we implement requirement X of spec Y here." Thanks also for the pointer to the spec; I doubt I would have found it by myself. A pretty dense read, but good to know it's there when I'm ready for some more mental gymnastics.
  • Boris Zbarsky
    Boris Zbarsky over 11 years
    The code dates back to before any specs defined this behavior, so the relevant question was what behavior web sites relied on. And that was the IE behavior, of course; we're talking 10 years ago here.