How is the default submit button on an HTML form determined?
如果提交表单但未通过任何特定按钮提交,例如
- 通过按Enter
-
在JS中使用
HTMLFormElement.submit()
浏览器应如何确定按下多个提交按钮(如果有)中的哪个?
这在两个层次上很重要:
-
调用附加到提交按钮的
onclick 事件处理程序 - 数据发送回Web服务器
到目前为止,我的实验表明:
- 当按Enter时,Firefox,Opera和Safari使用表单中的第一个提交按钮
- 当按Enter时,IE会使用第一个提交按钮,或者根本不使用任何提交按钮,具体取决于我无法弄清楚的情况
- 所有这些浏览器都完全不使用JS提交
标准怎么说?
如果有帮助,这是我的测试代码(PHP仅与我的测试方法有关,与我的问题本身无关)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <!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" /> Test </head> <body> Get <dl> <?php foreach ($_GET as $k => $v) echo"<dt>$k</dt><dd>$v</dd>"; ?> </dl> Post <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> |
如果您通过Javascript(即
如果在非textarea字段中通过按Enter提交表单,则实际上取决于用户代理在此处确定所需内容。规范并没有说明在文本输入字段中使用Enter键提交表单的任何内容(如果您使用制表符选择按钮并使用空格或其他任何方式激活它,那么就不会有问题,因为明确使用了特定的提交按钮)。它说的是,当激活提交按钮时必须提交表格,甚至不需要输入例如文本输入将提交表格。
我相信Internet Explorer会选择源中最先出现的"提交"按钮;我觉得Firefox和Opera选择的TabIndex最低的按钮,如果没有其他定义,则退回到第一个定义的按钮。关于提交者是否具有非默认值属性IIRC,还存在一些复杂问题。
要解决的问题是,这里没有定义明确的标准,这完全取决于浏览器的想法-因此,无论您在做什么,都应尽可能避免依赖任何特定的行为。如果您真的必须知道,您可能可以找出各种浏览器版本的行为,但是当我前一段时间进行调查时,存在一些相当复杂的条件(当然,这些条件可能会随新的浏览器版本而改变),我建议您尽可能避免它!
HTML 4并未明确指出。当前的HTML5工作草案指定第一个提交按钮必须为默认按钮:
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 field is focused implicitly submits the form), then
doing so for a form whose default button has a defined
activation behavior must cause the user agent to
run synthetic click activation steps on that
default button.
安德烈兹(Andrezj)几乎完全钉住了……但这是一个简单的跨浏览器解决方案。
采取这样的形式:
1 2 3 4 5 6 7 8 | <form> <input/> <button type="submit" value="some non-default action"/> <button type="submit" value="another non-default action"/> <button type="submit" value="yet another non-default action"/> <button type="submit" value="default action"/> </form> |
并重构为:
1 2 3 4 5 6 7 8 9 10 11 12 | <form> <input/> <button style="overflow: visible !important; height: 0 !important; width: 0 !important; margin: 0 !important; border: 0 !important; padding: 0 !important; display: block !important;" type="submit" value="default action"/> <button type="submit" value="some non-default action"/> <button type="submit" value="another non-default action"/> <button type="submit" value="yet another non-default action"/> <button type="submit" value="still another non-default action"/> <button type="submit" value="default action"/> </form> |
由于W3C规范指示多个提交按钮有效,但是省略了有关用户代理应如何处理它们的指导,因此浏览器制造商可以按照自己的意愿实施。我发现他们要么在表单中提交第一个提交按钮,要么在当前具有焦点的表单字段之后提交下一个提交按钮。
不幸的是,只是添加了一种显示样式:无法使用,因为W3C规范指示应从用户互动中排除任何隐藏的元素。因此,将其隐藏在明显的地方!
上面是我最终投入生产的解决方案的示例。按下Enter键会触发默认表单提交是预期的行为,即使存在其他非默认值并且位于DOM中的默认提交按钮之前。与显式用户输入进行鼠标/键盘交互的奖励,同时避免了javascript处理程序。
注意:在表单上进行切换将不会显示任何视觉元素的焦点,但仍将导致选择不可见按钮。为避免此问题,只需相应地设置tabindex属性,然后在不可见的提交按钮上省略tabindex属性。虽然将这些样式提升为!似乎很不合适,但它们应防止任何框架或现有的按钮样式干扰此修复程序。另外,那些内联样式绝对是差劲的形式,但是我们在这里证明概念……不编写生产代码。
我认为如果有人想使用jQuery,这篇文章会有所帮助:
http://greatwebguy.com/programming/dom/default-html-button-submit-on-enter-with-jquery/
基本解决方案是:
1 2 3 4 5 6 7 8 9 10 | $(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; } }); }); |
我喜欢的另一个是:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; } }); }); |
现在可以使用
的HTML
1 2 3 4 5 6 7 8 9 10 11 | <form> My Form <label for="text">Input:</label> <input type="text" name="text" id="text"/> <!-- Put the elements in reverse order --> <button>Ok</button> <!-- our default action is first --> <button>Cancel</button> </form> |
的CSS
1 2 3 4 | .form-actions { display: flex; flex-direction: row-reverse; /* reverse the elements inside */ } |
讲解
使用弹性框,我们还可以通过使用CSS规则
演示版
http://codepen.io/Godwin/pen/rLVKjm
我有一个带有11个提交按钮的表单,当用户按下Enter键时,它将始终使用第一个提交按钮。我在其他地方读到,在表单上具有多个提交按钮不是一个好主意(坏习惯),而做到这一点的最佳方法是将您想要的按钮作为默认值,作为表单上唯一的提交按钮。其他按钮应设置为" TYPE = BUTTON",并添加一个onClick事件,该事件将使用Javascript调用您自己的提交例程。像这样的东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <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; } <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();"> |
在这里,button3是默认的,尽管您正在以编程方式提交带有其他按钮的表单,但是mjsubmit例程会对其进行验证。 HTH。
我在同一个问题上苦苦挣扎,因为我在提交按钮的中间有一个提交按钮,从该按钮将提交重定向到另一个页面,如下所示:
1 | <button type="submit" onclick="this.form.action = '#another_page'">More</button> |
当用户按下Enter键时,该按钮被单击,而不是另一个提交按钮。
因此,我通过创建带有多个提交按钮和不同可见性选项的from进行了一些原始测试,并通过onclick事件警报提示单击了哪个按钮:https://jsfiddle.net/aqfy51om/1/
我用于测试的浏览器和操作系统:
视窗
- 谷歌浏览器43(来谷歌:D)
- Mozilla Firefox 38
- Internet Explorer 11
- Opera 30.0
OSX
- 谷歌浏览器43
- Safari 7.1.6
尽管IE和Safari应用了可见性选项,但大多数浏览器还是单击了第一个按钮,而IE和Safari单击了第三个按钮,该按钮在"隐藏"容器中"可见":
1 | <button type="submit" class="btn btn-default" onclick="alert('Hidden submit button #3 was clicked');">Hidden submit button #3</button> |
所以我的建议是:
如果您的表单具有多个具有不同含义的提交按钮,则在表单的开头添加具有默认操作的提交按钮,即:
编辑
另一个选择可能是偏移按钮(仍在from的开头),
奇怪的是,无论是否可见,第一个按钮Enter总是转到第一个按钮,例如使用jquery
1 2 3 | <button type="submit" name="action" value="update">Update</button> <button type="submit" name="action" value="insert">Insert</button> <button type="submit" name="action" value="delete">Delete</button> |
并使用javascript代码:
1 2 | $("#formId button[type='submit'][name='action'][value!='insert']").hide().attr('disabled', 'disabled'); $("#formId button[type='submit'][name='action'][value='insert']").show().removeAttr('disabled'); |
当您在一个表单中有多个提交按钮并且用户按下ENTER键从文本字段中提交表单时,此代码将通过从按键事件中调用表单上的Submit事件来覆盖默认功能。这是该代码:
1 2 3 4 5 6 | $('form input').keypress(function(e){ if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){ $(e.target).closest('form').submit(); return false; } else return true; }); |
根据您的评论:
A consequence is that, if you have
multiple forms submitting to the same
script, you can't rely on submit
buttons to distinguish them.
我将
如果使用javascript提交:将提交事件添加到表单,而不是在按钮上单击事件。精明的用户不会经常触摸鼠标。
根据HTML 4规范:
If a form contains more than one submit button, only the activated
submit button is successful.
这意味着,如果给出了多个提交按钮,并且没有激活(单击)任何按钮,那么任何一个都不应该成功。
我认为这很有意义:
想象一下一个巨大的表单,其中包含多个提交按钮。顶部有一个"删除此记录"按钮,然后有很多输入,而底部有一个"更新此记录"按钮。当用户在表单底部的字段中单击Enter时,永远不会怀疑他从顶部隐式单击了"删除此记录"。
因此,我认为使用用户未定义(单击)的第一个或任何其他按钮不是一个好主意。
不过,浏览器当然会这样做。
我使用的另一种解决方案是在表单中仅包含一个按钮,然后伪造其他按钮。
这是一个例子:
1 2 3 4 5 6 | <form> <label for="amount">Amount of items</label> <input id="amount" type="text" name="amount" /> <span id="checkStock" class="buttonish">Check stock</span> <button type="submit" name="action" value="order">Place order</button> </form> |
然后,我将span元素设置为看起来像按钮的样式。 JS侦听器观察跨度并在单击后执行所需的操作。
不一定适合所有情况,但至少很容易做到。
我的食谱:
1 2 3 4 5 6 7 8 9 | <form> <input type=hidden name=action value=login><!-- the magic! --> <input type=text name=email> <input type=text name=password> <input type=submit name=action value=login> <input type=submit name=action value="forgot password"> </form> |
如果没有"单击"任何按钮,它将发送默认的隐藏字段。
如果单击它们,则它们具有首选项,并且其值已传递。
编辑:抱歉,在编写此答案时,我正在考虑一般意义上的提交按钮。下面的答案不是关于多个
要确定按下Enter键时按下的按钮,可以用
1 2 | <input type="button" value="Cancel" /> <input type="submit" value="Submit" /> |