如何确定HTML表单上的默认提交按钮?


210

如果提交表单但未通过任何特定按钮提交,例如

  • 通过按 Enter
  • HTMLFormElement.submit()在JS中使用

浏览器应如何确定按下多个提交按钮(如果有)中的哪个?

这在两个层次上很重要:

  • 调用onclick附加到提交按钮的事件处理程序
  • 数据发送回Web服务器

到目前为止,我的实验表明:

  • 按下时Enter,Firefox,Opera和Safari使用表单中的第一个提交按钮
  • 按下时Enter,IE会使用第一个“提交”按钮,或者根本不使用任何按钮,具体取决于我无法弄清楚的情况
  • 所有这些浏览器都完全不使用JS提交

标准怎么说?

如果有帮助,这是我的测试代码(PHP仅与我的测试方法有关,与我的问题本身无关)

<!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>

Answers:


115

如果您通过Javascript(即提交表单formElement.submit()或任何等价物),然后的提交按钮被认为是成功的,没有它们的值都包含在提交的数据。(请注意,如果您使用提交表单,submitElement.click()那么您所引用的提交就被认为是活动的;这并不属于您所提问题的范围,因为这里的提交按钮是明确的,但我想我应该将其包括在内对于阅读了第一部分的人并想知道如何通过JS表单提交成功完成一个提交按钮的人。当然,表单的onsubmit处理程序仍会以这种方式触发,而他们不会通过,form.submit()因此这是又一锅鱼...)

如果在非textarea字段中通过按Enter提交表单,则实际上取决于用户代理在此处确定所需内容。该规范不说有关使用输入在文本输入字段键的同时提交表单什么(如果你标签的按钮,使用空间或任何激活它,然后还有为特定的提交按钮是没有问题的明确使用)。它只是说,当激活提交按钮时,必须提交表单,甚至不需要输入例如文本输入即可提交表单。

我相信Internet Explorer会选择源中最先出现的“提交”按钮;我觉得Firefox和Opera选择的TabIndex最低的按钮,如果没有其他定义,则退回到第一个定义的按钮。关于提交者是否具有非默认值属性IIRC,还存在一些复杂问题。

要解决的问题是,这里没有定义明确的标准,这完全取决于浏览器的想法-因此,无论您在做什么,都应尽可能避免依赖任何特定的行为。如果您真的必须知道,您可能可以找出各种浏览器版本的行为,但是当我前一段时间进行调查时,存在一些相当复杂的条件(当然,这些条件可能会随新的浏览器版本而改变),我建议您尽可能避免它!


1
关于第2段:我的基本问题是,在任何规范中是否存在任何内容,例如“如果浏览器提供了任何不指定提交控件的提交表单的方式...”的效果。但是我从大卫的答复中得知没有。我对IE的观点是有时按Enter提交表单,并且未设置任何提交按钮。结果是,如果您有多个表单提交到同一脚本,则不能依靠提交按钮来区分它们。这是我正在研究的项目。
斯图尔特

1
第一段非常有用的括号部分-谢谢。
rbassett

63

HTML 4并未明确指出。当前的HTML5工作草案指定第一个Submit按钮必须为默认按钮

一个form元素的默认按钮是第一个提交按钮树形结构顺序,其所属表单form元素。

如果用户代理支持让用户隐式提交表单(例如,在某些平台上,当文本字段被隐式聚焦时,按下“ enter”键则提交表单),则对默认按钮具有定义的 激活的表单执行此操作行为必须导致用户代理 在该默认按钮运行综合点击激活步骤


好的,这就是应该做的。我可以用吗?
Pacerier,2014年

我很高兴看到HTML5中的“隐式提交”。
克林特·帕克

61

安德烈兹(Andrezj)几乎完全钉住了……但这是一个简单的跨浏览器解决方案。

采取这样的形式:

<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>

并重构为:

<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属性。虽然将这些样式提升为!似乎很不合适,但它们防止任何框架或现有的按钮样式干扰此修复程序。另外,那些内联样式绝对是差劲的形式,但是我们在这里证明概念……不编写生产代码。


5
谢谢。偶然发现显示屏:也没问题。除了最小化按钮之外,您还可以通过将其替代来将其移出页面<div style="position: fixed; left: -1000px; top: -1000px />。还要注意的一件事:使用CSS最小化或将按钮从页面流中移开可能会带来WAI问题,因为屏幕阅读器仍会看到默认按钮。
Stefan Haberl 2012年

2
谢谢@詹姆斯,这个详细的答案。
弥敦道

1
这对我有用,谢谢。我必须为按钮边框添加此内容:无;使其彻底消失
-Macumbaomuerte

4
您可以将隐藏按钮的tabindex属性设置为-1
tvanc

2
<input/>是为了什么
Sz。

16

我认为如果有人想使用jQuery,这篇文章会有所帮助:

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

基本解决方案是:

$(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;
    }
    });
});

我喜欢的另一个是:

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;
}
});
}); 

jQuery.Event始终具有其.wich属性。同样,也无需回退到DOM .keyCode(或.charCode就此而言)。
Arjan

这里有关jQuery的另一个问题是不必要的双重查询。由于不需要返回true,因此,jQuery版本变得非常清晰,并且在整合Arjan之前建议的缩减方面也很短。
soletan 2012年

我使用keydown而不是keypress(避免等待keyup),并且将其添加e.preventDefault();到此函数的开头,以避免执行“真实的”默认按钮。真的很好。
马特·罗伊

6

我有一个带有11个提交按钮的表单,当用户按下Enter键时,它将始终使用第一个提交按钮。我在其他地方读到,在表单上具有多个提交按钮不是一个好主意(坏习惯),而做到这一点的最佳方法是将您想要的按钮作为默认值,作为表单上唯一的提交按钮。其他按钮应设置为“ TYPE = BUTTON”,并添加一个onClick事件,该事件将使用Javascript调用您自己的提交例程。像这样的东西:

<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();">

在这里,button3是默认的,尽管您正在以编程方式提交带有其他按钮的表单,但是mjsubmit例程会对其进行验证。HTH。


19
馊主意。您的表单在禁用JS的情况下无法使用。JS应该被简单地使用。
BalusC 2010年

7
很少有浏览器默认情况下会关闭JS,即使是iPod上的浏览器也是如此!在我引用的表单上,关闭JS会使它无用!很大程度上取决于JS的运行。
图形图片2010年

7
不管是否默认关闭,禁用JS的人都不必为了解决这种愚蠢的小问题而将其打开。
斯图尔特

2
什么样的表格有11个提交按钮?(好奇心

2
我看到验证非侵入式Javascript的最大原因是,侵入式 Javascript往往比较笨拙。我不确定如何限定我的想法,但是当我看到页面完全依赖JS时,我也打赌我可以用DOM做一些棘手的事情,并在服务器上做一些意想不到的事情。
萨曼莎·布兰纳姆

6

现在可以使用flexbox以下方法解决:

的HTML

<form>
    <h1>My Form</h1>
    <label for="text">Input:</label>
    <input type="text" name="text" id="text"/>

    <!-- Put the elements in reverse order -->
    <div class="form-actions">
        <button>Ok</button> <!-- our default action is first -->
        <button>Cancel</button>
    </div>
</form>

的CSS

.form-actions {
    display: flex;
    flex-direction: row-reverse; /* reverse the elements inside */
}

说明
使用flex框,我们还可以display: flex通过使用CSS规则来反转使用的容器中元素的顺序flex-direction: row-reverse。这不需要CSS或隐藏元素。对于不支持flexbox的较旧的浏览器,它们仍然可以获得可行的解决方案,但是这些元素将不会逆转。

演示
http://codepen.io/Godwin/pen/rLVKjm


2

我在同一个问题上苦苦挣扎,因为我在提交按钮的中间有一个提交按钮,从该按钮将提交重定向到另一个页面,如下所示:

<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
  • 歌剧30.0

OSX

  • 谷歌浏览器43
  • Safari 7.1.6

尽管IE和Safari应用了可见性选项,但大多数浏览器还是单击了第一个按钮,而IE和Safari单击了第三个按钮,该按钮在“隐藏”容器中“可见”:

<div style="width: 0; height: 0; overflow: hidden;">
    <button type="submit" class="btn btn-default" onclick="alert('Hidden submit button #3 was clicked');">Hidden submit button #3</button>
</div>

所以我的建议是:

如果您的表单具有多个具有不同含义的提交按钮,则在表单的开头添加具有默认操作的提交按钮,即:

  1. 完全可见
  2. 用一个容器包装 style="width: 0; height: 0; overflow: hidden;"

编辑 另一个选择可能是偏移按钮(仍在from的开头)style="position: absolute; left: -9999px; top: -9999px;",只是在IE中尝试过-工作,但我不知道它还能搞乱什么,例如打印。


1

根据您的评论:

结果是,如果您有多个表单提交到同一脚本,则不能依靠提交按钮来区分它们。

我掉了 <input type="hidden" value="form_name" />放入每种表格中。

如果使用javascript提交:将提交事件添加到表单,而不是单击事件到其按钮。精明的用户不会经常触摸鼠标。


确实,但是这引出了这个问题:stackoverflow.com/questions/541869/…–
斯图尔特

1

当您在一个表单中有多个提交按钮并且用户按下ENTER键从文本字段中提交表单时,此代码将通过从按键事件中调用表单上的Submit事件来覆盖默认功能。这是该代码:

$('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;

});

简单并解决了问题
toddmo

1

奇怪的是,无论是否可见,第一个按钮Enter总是转到第一个按钮,例如使用jquery show/hide()。添加属性会.attr('disabled', 'disabled')阻止完全接收Enter提交按钮。例如,在记录对话框中调整“ 插入/编辑+删除”按钮的可见性时,就会出现问题。我发现插入菜单前的编辑功能不那么扎实

<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代码:

$("#formId button[type='submit'][name='action'][value!='insert']").hide().attr('disabled', 'disabled');
$("#formId button[type='submit'][name='action'][value='insert']").show().removeAttr('disabled');

0

我的食谱:

<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>

如果没有“单击”任何按钮,它将发送默认的隐藏字段。

如果单击它们,则它们具有首选项,并且其值已传递。


2
但是该行为是否由标准指定?可以信任浏览器正确实现它吗?
斯图尔特

好问题。我已经测试过它可以在所有A浏览器上工作(来自ui浏览器矩阵),这是我在现实生活中可以得到的最有意义的结果(无论标准指定了什么)
gcb

@yellowandred会发生什么?稍后再看
gcb

1
我的错误是我更改了{type =“ hidden”},但我没有注意到相同的“名称”值。
黄色和红色

在IE11或Fx30中,这对我不起作用。该值始终设置为隐藏值。
Jamie Kitson 2014年

0

我使用的另一种解决方案是在表单中仅包含一个按钮,然后伪造其他按钮。

这是一个例子:

<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
禁用JS的用户的后备之处是什么?
斯图尔特

禁用了JS的用户将无法使用Internet,就像今天一样简单。
Christoffer Bubach'2

0

根据HTML 4规范

如果一个表单包含多个提交按钮,则仅激活的提交按钮成功。

这意味着,如果给出了多个提交按钮,并且没有激活(单击)任何按钮,那么任何一个都不应该成功。

我认为这是有道理的:想象一下一个具有多个提交按钮的巨大表单。顶部有一个“删除此记录”按钮,然后有很多输入,而底部有一个“更新此记录”按钮。用户在表单底部的字段中单击Enter时,永远不会怀疑他从顶部隐式单击了“删除此记录”。

因此,我认为使用用户未定义(单击)的第一个或任何其他按钮不是一个好主意。不过,浏览器当然会这样做。


-2

编辑:抱歉,在编写此答案时,我正在考虑一般意义上的提交按钮。下面的答案不是关于多个type="submit"按钮的,因为它只留下一个type="submit",将另一个改变为type="button"。我将答案留在这里作为参考,以防万一有人可以更改type其格式:

要确定在按Enter键时按下了什么按钮,可以用标记它type="submit",而其他按钮用标记它们type="button"。例如:

<input type="button" value="Cancel" />
<input type="submit" value="Submit" />

键入“按钮”不会导致表单提交。它仅用于触发客户端脚本。
斯图尔特

正是这就是为什么浏览器在您按Enter键时会跳过它,并执行“提交”类型的原因。例如,您可以使用类型为“按钮”的按钮进行其他操作。请删除反对票。
耶苏斯·卡雷拉

问题是关于多个提交按钮。
斯图尔特

我的示例对于多个提交按钮完全有效。类型为“提交”的类型是由浏览器确定为被按下的类型(这就是问题所在)。然后,使用另一个按钮,您可以将其用作提交按钮,也可以使用JavaScript事件(如示例中的onClick事件)用作提交按钮。因此,我的回答是相关的,不应该被否决。请删除它。
耶苏斯·卡雷拉

1
如果您的建议是通过仅使其中一个键入“ submit”并使用JavaScript来实现其他按钮来消除歧义,那么这与图形的答复是重复的,因此已被视为一个坏主意。
斯图尔特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.