Multiple submit buttons on HTML form – designate one button as default [duplicate]
Asked Answered
P

9

142

I have a form that has three submit buttons as follows:

<input type="submit" name="COMMAND" value="&lsaquo; Prev">
<input type="submit" name="COMMAND" value="Save">
<input type="reset"  name="NOTHING" value="Reset">
<input type="submit" name="COMMAND" value="Next &rsaquo;">
<input type="button" name="NOTHING" value="Skip &rsaquo;" onclick="location = 'yada-yada.asp';">

The row of buttons is a mix of submit, reset and JavaScript buttons. The order of buttons is subject to change, but in any case the save button remains between prev and next buttons.

The problem here is that when a user hits Enter to submit the form, the post variable "COMMAND" contains "Prev"; normal, as this is the first submit button on the form. I however want the "Next" button to be triggered when the user submits the form via the Enter button. It is kind of like setting it as the default submit button, even though there are other buttons before it.

Pseudohemophilia answered 26/12, 2009 at 11:58 Comment(3)
In case you (or anyone else) is interested, I had a similar issue, and used this (#12083183) css trick to place my main submit button at the top of the form, but display it at the bottom of the form, with the container being the only element that requires a fixed dimension (the padding-bottom for the height of the primary submit button, or containing element) so it can easily grow dynamically based on the form contentPantechnicon
necrothread answer: If you happen to be using ASP.NET WebForms on the server side, enclose in <ASP:Panel Defaultbutton="btnThatShouldBeDefault">. This automatically generates javascript that causes the correct button to be default depending on where the insertion caret is.Demurral
Possible duplicate of Multiple submit buttons in an HTML formNsf
W
82

My suggestion is don't fight this behaviour. You can effectively alter the order using floats. For example:

<p id="buttons">
<input type="submit" name="next" value="Next">
<input type="submit" name="prev" value="Previous">
</p>

with:

#buttons { overflow: hidden; }
#buttons input { float: right; }

will effectively reverse the order and thus the "Next" button will be the value triggered by hitting enter.

This kind of technique will cover many circumstances without having to resort to more hacky JavaScript methods.

Waterrepellent answered 26/12, 2009 at 12:35 Comment(5)
Any other possible "CSS" positioning trick?Pseudohemophilia
I managed to push the next button to the right by (1) floating it right (2) all other buttons floated left (3) all buttons displayed block (4) all buttons, including next button, specified in source order.Pseudohemophilia
Works great, thanks! I'd just add that if you want the button group to still float left, just enclose the "buttons" id element in a float left div, and then your buttons will be reordered with Next coming after Previous as desired, but the button group will remain floated left.Holtorf
Thanks, This solutio is great!!! I was thinking about some ugly javascript hack.Selfoperating
The primary problem with this solution is that it breaks tab index. Repositioning of buttons with CSS does not change their tabindex order. So pressing tab will not consistently go from top / bottom, left to right. See https://mcmap.net/q/159295/-multiple-submit-buttons-on-html-form-designate-one-button-as-default-duplicate for a solution that addresses this.Carpus
O
89

The first button is always the default; it can't be changed. Whilst you can try to fix it up with JavaScript, the form will behave unexpectedly in a browser without scripting, and there are some usability/accessibility corner cases to think about. For example, the code linked to by Zoran will accidentally submit the form on Enter press in a <input type="button">, which wouldn't normally happen, and won't catch IE's behaviour of submitting the form for Enter press on other non-field content in the form. So if you click on some text in a <p> in the form with that script and press Enter, the wrong button will be submitted... especially dangerous if, as given in that example, the real default button is ‘Delete’!

My advice would be to forget about using scripting hacks to reassign defaultness. Go with the flow of the browser and just put the default button first. If you can't hack the layout to give you the on-screen order you want, then you can do it by having a dummy invisible button first in the source, with the same name/value as the button you want to be default:

<input type="submit" class="defaultsink" name="COMMAND" value="Save" />

.defaultsink {
    position: absolute; left: -100%;
}

(note: positioning is used to push the button off-screen because display: none and visibility: hidden have browser-variable side-effects on whether the button is taken as default and whether it's submitted.)

Oleo answered 26/12, 2009 at 12:48 Comment(7)
Following your lead, I found the following works for me: <input type="submit" name="..." value="..." style="display:none;" /> placed just below the <form> tag, duplicating a visible button that appears later in the form.Photomicrograph
First button is default, but it can be changed :-). Use type=button for nondefault buttons and type=submit for the default one (example is given below: https://mcmap.net/q/159295/-multiple-submit-buttons-on-html-form-designate-one-button-as-default-duplicate)Franfranc
@GrahamKlyne - the display:none does not work consistently across today's browsers. See codepen.io/shanplourde/pen/pJYrJV for example.Carpus
@Franfranc + his comment upvoters: Nope, type=button will not submit the form, so won't solve OP's problem, according to @spikyjt's comment (somewhere above).Alcorn
@Alcorn It is written as "Set type=submit to the button you'd like to be default ..."; the role of other buttons is up to the UI creator. And the problem was to make not the first button to be default, but an another, which is solved by the trick. I had the same problem and the solution works for me nicely :-)Franfranc
@dmitry_romanov: Dima, it's about the other submit buttons, which won't work, not the default one, which would just fine. (Remember the OP: "multiple", "submit"). BTW, I also had the same problem -- not yours, but OP's, with multiple submit buttons, so your solution did not work (i.e. without the "divine intervention" you referred to... ;) ). This is what worked.Alcorn
@Sz.I see :-). Good to have your solution for the situations like the described one. Thanks!Franfranc
W
82

My suggestion is don't fight this behaviour. You can effectively alter the order using floats. For example:

<p id="buttons">
<input type="submit" name="next" value="Next">
<input type="submit" name="prev" value="Previous">
</p>

with:

#buttons { overflow: hidden; }
#buttons input { float: right; }

will effectively reverse the order and thus the "Next" button will be the value triggered by hitting enter.

This kind of technique will cover many circumstances without having to resort to more hacky JavaScript methods.

Waterrepellent answered 26/12, 2009 at 12:35 Comment(5)
Any other possible "CSS" positioning trick?Pseudohemophilia
I managed to push the next button to the right by (1) floating it right (2) all other buttons floated left (3) all buttons displayed block (4) all buttons, including next button, specified in source order.Pseudohemophilia
Works great, thanks! I'd just add that if you want the button group to still float left, just enclose the "buttons" id element in a float left div, and then your buttons will be reordered with Next coming after Previous as desired, but the button group will remain floated left.Holtorf
Thanks, This solutio is great!!! I was thinking about some ugly javascript hack.Selfoperating
The primary problem with this solution is that it breaks tab index. Repositioning of buttons with CSS does not change their tabindex order. So pressing tab will not consistently go from top / bottom, left to right. See https://mcmap.net/q/159295/-multiple-submit-buttons-on-html-form-designate-one-button-as-default-duplicate for a solution that addresses this.Carpus
F
38

Set type=submit to the button you'd like to be default and type=button to other buttons. Now in the form below you can hit Enter in any input fields, and the Render button will work (despite the fact it is the second button in the form).

Example:

    <button id='close_button' class='btn btn-success'
            type=button>
      <span class='glyphicon glyphicon-edit'> </span> Edit program
    </button>
    <button id='render_button' class='btn btn-primary'
            type=submit>             <!--  Here we use SUBMIT, not BUTTON -->
      <span class='glyphicon glyphicon-send'> </span> Render
    </button>

Tested in FF24 and Chrome 35.

Franfranc answered 16/6, 2014 at 13:54 Comment(1)
Except that type="button" does not submit the form. The requirement here is that the other buttons still submit the form, but are not default. Additional javascript will be required to make them submit the form, which means re-positioning with CSS is preferable.Altis
D
37

Quick'n'dirty you could create an hidden duplicate of the submit-button, which should be used, when pressing enter.

Example CSS

input.hidden {
    width: 0px;
    height: 0px;
    margin: 0px;
    padding: 0px;
    outline: none;
    border: 0px;
}

Example HTML

<input type="submit" name="next" value="Next" class="hidden" />
<input type="submit" name="prev" value="Previous" />
<input type="submit" name="next" value="Next" />

If someone now hits enter in your form, the (hidden) next-button will be used as submitter.

Tested on IE9, Firefox, Chrome and Opera

Deeply answered 22/1, 2013 at 16:44 Comment(6)
The only other suggestions that I have are to ensure that you're addressing accessibility issues, and tabindex issues. Since the button is technically not hidden, only practically, screen readers and assistive devices will identify the button. Also the button as-is is still tabbable. Setting tabindex="-1" corrects that.Carpus
To hide the button from assistive tools (screen readers) add role=none to its properties.Hoofbound
A simple 'display: none;' seems to work as well? This furthermore also addresses the screen reader issue.Prig
"display: none" didn't work for all browsers/browser-versions, that I tested.Deeply
Further to the above, using display: none works in Firefox and Chrome, but not Safari. For best cross-browser support, I used the following CSS: height: 0; visibility: hidden; with the following attributes: aria-hidden="true" tabindex="-1"Nanceenancey
@TomSpencer: Don't forget width: 0. But display: none should be supported by Safar: developer.mozilla.org/de/docs/Web/CSS/displayDeeply
L
28

If you're using jQuery, this solution from a comment made here is pretty slick:

$(function(){
    $('form').each(function () {
        var thisform = $(this);
        thisform.prepend(thisform.find('button.default').clone().css({
            position: 'absolute',
            left: '-999px',
            top: '-999px',
            height: 0,
            width: 0
        }));
    });
});

Just add class="default" to the button you want to be the default. It puts a hidden copy of that button right at the beginning of the form.

Labionasal answered 12/7, 2010 at 20:23 Comment(0)
C
5

I'm resurrecting this because I was researching a non-JavaScript way to do this. I wasn't into the key handlers, and the CSS positioning stuff was causing tab ordering to break since CSS repositioning doesn't change tab order.

My solution is based on the response at https://stackoverflow.com/a/9491141.

The solution source is below. tabindex is used to correct tab behaviour of the hidden button, as well as aria-hidden to avoid having the button read out by screen readers / identified by assistive devices.

<form method="post" action="">
  <button type="submit" name="useraction" value="2nd" class="default-button-handler" aria-hidden="true" tabindex="-1"></button>
  <div class="form-group">
    <label for="test-input">Focus into this input: </label>
    <input type="text" id="test-input" class="form-control" name="test-input" placeholder="Focus in here and press enter / go" />
  </div>

1st button in DOM 2nd button in DOM 3rd button in DOM

Essential CSS for this solution:

.default-button-handler {
  width: 0;
  height: 0;
  padding: 0;
  border: 0;
  margin: 0;
}
Carpus answered 10/8, 2015 at 4:41 Comment(1)
Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.Sawicki
L
1

Another solution, using jQuery:

$(document).ready(function() {
  $("input").keypress(function(e) {
    if (e.which == 13) {
      $('#submit').click();
      return false;
    }

    return true;
  });
});

This should work on the following forms, making "Update" the default action:

<form name="f" method="post" action="/action">
  <input type="text" name="text1" />
  <input type="submit" name="button2" value="Delete" />
  <input type="submit" name="button1" id="submit" value="Update" />
</form>

As well as:

<form name="f" method="post" action="/action">
  <input type="text" name="text1" />
  <button type="submit" name="button2">Delete</button>
  <button type="submit" name="button1" id="submit">Update</button>
</form>

This traps the Enter key only when an input field on the form has focus.

Lipoid answered 17/3, 2015 at 22:48 Comment(0)
A
0

You should not be using buttons of the same name. It's bad semantics. Instead, you should modify your backend to look for different name values being set:

<input type="submit" name="COMMAND_PREV" value="&lsaquo; Prev">
<input type="submit" name="COMMAND_SAVE" value="Save">
<input type="reset"  name="NOTHING" value="Reset">
<input type="submit" name="COMMAND_NEXT" value="Next &rsaquo;">
<input type="button" name="NOTHING" value="Skip &rsaquo;" onclick="window.location = 'yada-yada.asp';">

Since I don't know what language you are using on the backend, I'll give you some pseudocode:

if (input name COMMAND_PREV is set) {

} else if (input name COMMAND_SAVE is set) {

} else if (input name COMMENT_NEXT is set) {

}
Aurum answered 26/12, 2009 at 12:34 Comment(4)
+1 relying on the value of buttons to decide which was clicked is extremely fragile. Any little UI change or localisation work then requires the backed to be changed to detect it. Also with non-ASCII characters in there you'll need to be absolutely sure that your encodings are set correctly everywhere!Oleo
Umm... I can live with that but this still means "Prev" acts as the "Default" button.Pseudohemophilia
@Salman, you should use my suggestion in combination with the suggestion from @Waterrepellent regarding CSS positioning to ensure you properly declare your default button first.Aurum
This is a valid point, but it doesn't answer the question.Antagonistic
S
-1

bobince's solution has the downside of creating a button which can be Tab-d over, but otherwise unusable. This can create confusion for keyboard users.

A different solution is to use the little-known form attribute:

<form>
    <input name="data" value="Form data here">
    <input type="submit" name="do-secondary-action" form="form2" value="Do secondary action">
    <input type="submit" name="submit" value="Submit">
</form>

<form id="form2"></form>

This is standard HTML, however unfortunately not supported in Internet Explorer.

Sawicki answered 26/5, 2015 at 13:25 Comment(7)
The specification doesn't seem to indicate that setting a form owner will cause that button to act as the default button, have you confirmed? The owner attribute seems to exist to address nested HTML forms. Also, what would happen if multiple buttons had the same form attribute assigned?Carpus
IIRC the specification says that the default button is the first button in DOM order which is owned by the form. Multiple buttons still conform to that rule - they act as if they were part of the form as far as submitting forms is concerned (so the first one is the default).Sawicki
Right, but the form owner is implied as the current form. If you don't specify the form attribute, the owning form is implied as the first parent form of the button/input. In a single form scenario, your suggestion doesn't work since every submit button assumes the same form owner. You wouldn't be able to make the enter key submit the 2nd of 3 buttons on that form for example.Carpus
See codepen.io/shanplourde/pen/VLRrJw for a demonstration that confirms that the form owner is not a workable solution, since it would wind up submitting another form, rather than the DOM containing form of the button. Feel free to fork the codepen and revise it if you feel strongly that your solution is valid in some way.Carpus
Err, yes, of course it submits the owner form. I thought that was obvious. Not an issue with e.g. "Delete" or "Cancel" actions, you can use a hidden input to identify the item.Sawicki
Downvoting since the answer is not accomplishing what Salmon A asked. I'll remove downvote if you're able to validate your response.Carpus
"Validate your response"? Way to be mean. Technically, your answer doesn't answer the OP's request either, as it doesn't "designate one button as default" and instead introduces an invisible button. The disadvantage is that the button will be visible to CSS-unaware UAs, and it does not provide the visual feedback for default buttons.Sawicki

© 2022 - 2024 — McMap. All rights reserved.