How is the default submit button on an HTML form determined?

Viewed 209987

If a form is submitted but not by any specific button, such as

  • by pressing Enter
  • using HTMLFormElement.submit() in JS

how is a browser supposed to determine which of multiple submit buttons, if any, to use as the one pressed?

This is significant on two levels:

  • calling an onclick event handler attached to a submit button
  • the data sent back to the web server

My experiments so far have shown that:

  • when pressing Enter, Firefox, Opera and Safari use the first submit button in the form
  • when pressing Enter, IE uses either the first submit button or none at all depending on conditions I haven't been able to figure out
  • all these browsers use none at all for a JS submit

What does the standard say?

If it would help, here's my test code (the PHP is relevant only to my method of testing, not to my question itself)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test</title>
</head>

<body>

<h1>Get</h1>
<dl>
<?php foreach ($_GET as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
</dl>

<h1>Post</h1>
<dl>
<?php foreach ($_POST as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
</dl>

<form name="theForm" method="<?php echo isset($_GET['method']) ? $_GET['method'] : 'get'; ?>" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
    <input type="text" name="method" />
    <input type="submit" name="action" value="Button 1" onclick="alert('Button 1'); return true" />
    <input type="text" name="stuff" />
    <input type="submit" name="action" value="Button 2" onclick="alert('Button 2'); return true" />
    <input type="button" value="submit" onclick="document.theForm.submit();" />
</form>

</body></html>
15 Answers

If you submit the form via JavaScript (i.e., formElement.submit() or anything equivalent), then none of the submit buttons are considered successful and none of their values are included in the submitted data. (Note that if you submit the form by using submitElement.click() then the submit that you had a reference to is considered active; this doesn't really fall under the remit of your question since here the submit button is unambiguous but I thought I'd include it for people who read the first part and wonder how to make a submit button successful via JavaScript form submission. Of course, the form's onsubmit handlers will still fire this way whereas they wouldn't via form.submit() so that's another kettle of fish...)

If the form is submitted by hitting Enter while in a non-textarea field, then it's actually down to the user agent to decide what it wants here. The specifications don't say anything about submitting a form using the Enter key while in a text entry field (if you tab to a button and activate it using space or whatever, then there's no problem as that specific submit button is unambiguously used). All it says is that a form must be submitted when a submit button is activated. It's not even a requirement that hitting Enter in e.g. a text input will submit the form.

I believe that Internet Explorer chooses the submit button that appears first in the source; I have a feeling that Firefox and Opera choose the button with the lowest tabindex, falling back to the first defined if nothing else is defined. There's also some complications regarding whether the submits have a non-default value attribute IIRC.

The point to take away is that there is no defined standard for what happens here and it's entirely at the whim of the browser - so as far as possible in whatever you're doing, try to avoid relying on any particular behaviour. If you really must know, you can probably find out the behaviour of the various browser versions, but when I investigated this a while back there were some quite convoluted conditions (which of course are subject to change with new browser versions) and I'd advise you to avoid it if possible!

HTML 4 does not make it explicit. HTML 5 specifies that the first submit button must be the default:

4.10.21.2 Implicit submission

A form element's default button is the first submit button in tree order whose form owner is that form element.

If the user agent supports letting the user submit a form implicitly (for example, on some platforms hitting the "enter" key while a text control is focused implicitly submits the form), then doing so for a form, whose default button has activation behavior and is not disabled, must cause the user agent to fire a click event at that default button.

If you want to influence which one is "first" while maintaining the visual order then there are a couple of approaches you could take.

An off-screen, unfocusable button.

.hidden-default {
    position: absolute;
    left: -9999px;
}
<form>
  <input name="text">
  <button name="submit" value="wanted" class="hidden-default" tabindex="-1"></button>
  <button name="submit" value="not wanted">Not the default</button>
  <button name="submit" value="wanted">Looks like the default</button>
</form>

Flexbox order:

.ordering {
    display: inline-flex;
}

.ordering button {
    order: 2;
}

.ordering button + button {
    order: 1;
}
<form>
  <input name="text">
  <div class="ordering">
    <button name="submit" value="wanted">First in document order</button>
    <button name="submit" value="not wanted">Second in document order</button>
  </div>
</form>

I think this post would help if someone wants to do it with jQuery:

http://greatwebguy.com/programming/dom/default-html-button-submit-on-enter-with-jquery/

The basic solution is:

$(function() {
    $("form input").keypress(function (e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        $('input[type=submit].default').click();
        return false;
    }
    else {
        return true;
    }
    });
});

And another I liked was:

jQuery(document).ready(function() {
    $("form input, form select").live('keypress', function (e) {
        if ($(this).parents('form').find('button[type=submit].default, input[type=submit].default').length <= 0)
            return true;

        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
            $(this).parents('form').find('button[type=submit].default, input[type=submit].default').click();
            return false;
        }
        else {
            return true;
        }
    });
});

I had a form with 11 submit buttons on it, and it would always use the first submit button when the user pressed Enter. I read elsewhere that it is not a good idea (bad practice) to have more than one submit button on a form, and the best way to do this is have the button you want as default, as the only submit button on the form. The other buttons should be made into "TYPE=BUTTON" and an onClick event added that calls your own submit routine in JavaScript. Something like this:

<SCRIPT Language="JavaScript">
function validform()
{
  // Do whatever you need to validate the form, and return true or false accordingly
}

function mjsubmit()
{
  if (validform()) { document.form1.submit(); return true;}
  return false;
}
</SCRIPT>
<INPUT TYPE=BUTTON NAME="button1" VALUE="button1" onClick="document.form1.submitvalue='button1'; return mjsubmit();">
<INPUT TYPE=BUTTON NAME="button2" VALUE="button2" onClick="document.form1.submitvalue='button2'; return mjsubmit();">
<INPUT TYPE=SUBMIT NAME="button3" VALUE="button3" onClick="document.form1.submitvalue='button3'; return validform();">
<INPUT TYPE=BUTTON NAME="button4" VALUE="button4" onClick="document.form1.submitvalue='button4'; return mjsubmit();">

Here, button3 is the default, and although you are programmatically submitting the form with the other buttons, the mjsubmit routine validates them.

<form onsubmit="alert('submit');return false;">
    <input name="username">
    <input name="password" type="password">
    <button onclick="if(document.activeElement === this){alert('button 1');}else{default_submit.click();}return false;">button 1</button>
    <button onclick="if(document.activeElement === this){alert('button 2');}else{default_submit.click();}return false;">button 2</button>
    <input id="default_submit" type="submit">
</form>

If you press Enter from text input, then the button will not become focused. Then we ignore this click and click the default submit instead, but if you click the button by mouse, it will be focused, then we apply this click.

Demo: https://codepen.io/remon-reffat/pen/mdRaXbp

From your comments:

A consequence is that, if you have multiple forms submitting to the same script, you can't rely on submit buttons to distinguish them.

I drop an <input type="hidden" value="form_name" /> into each form.

If submitting with JavaScript: add submit events to forms, not click events to their buttons. Savvy users don't touch their mouse very often.

Related