UPDATE: Please read the entire question carefully before you decide to answer it. I do not ask about the appropriateness of using the built-in event handler in the working code and I do not ask about the best way to achieve the result promised in the article to which I refer. This is a matter of Javascript semantics and browser implementation details, not coding best practices.
Sounds like a nightmare, right?
However, I found a few online tips that recommend doing just such a thing to prevent duplicate form submission:
<input type="submit" onclick="this.disabled=true; this.value='Sending, please wait...'; this.form.submit();" />
Leaving aside any discussion of the evil of the built-in event handlers, I see the following problems:
- The tag type is
"submit" so submitting a form containing it is its default behavior; - The
onclick handler explicitly submits the containing form; - The
onclick handler does not return false to prevent the default behavior (see 1).
Intuitively, I think that clicking on this element would do exactly the opposite of what the article claims - that is, submit the form twice, once as a result of an explicit call to submit() , and then again as an unsuppressed default value. "submit" -typed control behavior.
On the other hand, I wrote a tiny PHP script (below) and tested it both in Firefox and Safari (at the moment I have only available browsers), and it writes only one 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 these two browsers really do the “right” things (where the “right” ones are defined in some document that I either did not see or did not read carefully enough), which means that my problem analysis is incomplete or incorrect?
Or is my analysis correct - does this mean that the observed individual views are the result of browser developers using special case logic to save naive coders from themselves?
UPDATE:
In an attempt to empirically verify @sourcecode's assertion that the form.submit() method is a kind of “second submit button” on the form and thus obeys the rule specified in HTML4 section 17.13.2. To use only one “successful” submit button, I made several 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 creates a single entry in the error log:
Got a timestamp form, tellme = 1
which really assumes that the method call is somehow replaced by the internal event-driven behavior of the control.
Also, if I add an extra return false; after setting the tellme value to 1 (thereby preventing the propagation of the click event and thus preventing the control from behaving internally), the only error log entry will be:
Got the form at the timestamp, tellme = 0
This means that in this case, the view was the result of calling this.form.submit() .
On the other hand, when I try the same two options in Safari, each of them gives me the same error log entry:
Got the form at the timestamp, tellme = 0
So in the case of Safari, a method call always takes precedence over event-driven dispatch - perhaps because this happens earlier.
It. Just. Amazing .: - /
Further update: I got the opportunity to test this on IE 8.0 on Windows NT 5.1.
IE 8 reflects Safari behavior, i.e. The form.submit() method always takes precedence over even form.submit() .
Although this is hardly relevant today, I also realized that I have an ancient IE 5.22 on an even older PowerPC iMac running OS X 10.4.11. An interesting historical little thing here is that IE5 works in exactly the opposite of how IE8 works: event-driven dispatch always replaces the form.submit() method - even when the click event was forbidden to propagate with a return false; at the end of the onclick handler! (However, I did not delve into whether this was a mistake or a function. I have not yet carried out and, possibly, never!) I did not run a test to determine if this is an obstacle to blocking events or trying to do something “smart”. ".)
However, regardless of inconsistencies, both IEs only send one send.
My preliminary (well, at the moment, actually, pretty solid) conclusion is that the exact relationship between the submit -typed control and the DOM form.submit() method is not well-defined, and that browser implementations in lack of any clear directions, usually do what they consider best (see, for example, @Boris Zbarsky answer ).
At least in the cases of Firefox, Safari, and IE, their developers foresaw the possibility that both the event and the method call could compete for sending the same form, and took steps (albeit different - to a large extent using the gamma) to ensure that only one of them will succeed.
(I would still like to receive additional answers from people who know the various internal components of the browser well enough to comment, or who have downloaded my simple PHP script using browsers other than those I tested.)