如果提交了表单,但不是通过任何特定的按钮,例如

按Enter键 使用JS中的HTMLFormElement.submit()

浏览器应该如何确定多个提交按钮(如果有的话)中的哪一个作为按下的按钮呢?

这在两个层面上很重要:

调用附加到提交按钮的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>

当前回答

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规范指出多个提交按钮是有效的,但忽略了关于用户代理应该如何处理它们的指导,所以浏览器制造商只能按照他们认为合适的方式来实现。我发现他们要么提交表单中的第一个提交按钮,要么在当前有焦点的表单字段之后提交下一个提交按钮。

不幸的是,简单地添加一个显示样式:none;这是行不通的,因为W3C规范指出任何隐藏元素都应该从用户交互中排除。所以把它藏在众目睽睽之下吧!

上面是我最终投入生产的解决方案示例。按enter键触发默认表单提交,即使在DOM中出现其他非默认值并在默认提交按钮之前也是如此。与显式用户输入的鼠标/键盘交互的额外好处,同时避免JavaScript处理程序。

Note: tabbing through the form will not display focus for any visual element yet will still cause the invisible button to be selected. To avoid this issue, simply set tabindex attributes accordingly and omit a tabindex attribute on the invisible submit button. While it may seem out of place to promote these styles to !important, they should prevent any framework or existing button styles from interfering with this fix. Also, those inline styles are definitely poor form, but we're proving concepts here... not writing production code.

其他回答

我使用的另一种解决方案是在表单中只设置一个按钮,并伪造其他按钮。

这里有一个例子:

<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元素的样式设置为看起来像一个按钮。JavaScript侦听器观察跨度,并在单击后执行所需的操作。

这并不一定适用于所有情况,但至少很容易做到。

要确定按enter键时按下了哪个按钮,可以用type="submit"标记它,其他按钮用type="button"标记它们。例如:

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

抱歉,当我写这个答案时,我想的是一般意义上的提交按钮。下面的答案不是关于多个type="submit"按钮,因为它只留下一个type="submit",而把另一个改为type="button"。我把答案留在这里作为参考,以防帮助可以更改表单类型的人。

现在可以使用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 */
}

解释

使用Flexbox,我们可以通过使用CSS规则:flex-direction: row-reverse来反转使用display: flex的容器中的元素顺序。这不需要CSS或隐藏元素。对于不支持Flexbox的旧浏览器,他们仍然得到一个可行的解决方案,但元素不会被反转。

Demo

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

HTML 4并没有将其显式化。HTML 5规定第一个提交按钮必须是默认的:

4.10.21.2隐式提交 表单元素的默认按钮是按树顺序排列的第一个提交按钮,其表单所有者就是该表单元素。 如果用户代理支持让用户隐式提交表单 (例如,在某些平台上,在输入文本时按下“enter”键 控件隐式地提交表单),然后为 表单,其默认按钮具有激活行为,但没有 禁用时,必须导致用户代理在此触发单击事件 默认按钮。

如果你想在保持视觉顺序的同时影响哪个是“第一个”,那么你可以采取一些方法。

一个屏幕外、无法对焦的按钮。

.hidden-default { 位置:绝对的; 左:-9999 px; } < >形式 <输入名称= " text " > <button name="submit" value="wanted" class="hidden-default" tabindex="-1"></button> <button name="submit" value="not wanted">不是默认值 <button name="submit" value="wanted">看起来像默认的</button> > < /形式

Flexbox顺序:

.ordering { 显示:inline-flex; } . ordered按钮{ 秩序:2; } .订购按钮+按钮{ 顺序:1; } < >形式 <输入名称= " text " > < div class = "排序" > <button name="submit" value="wanted">文件顺序第一个</button> <button name="submit" value="not wanted">在文档顺序中的第2位</button> . </button> . <button name="submit" value="not wanted < / div > > < /形式

从HTML 4规范:

如果一个表单包含多个提交按钮,只有激活 提交按钮成功。

这意味着如果有多个提交按钮且没有激活(单击),则没有一个提交按钮会成功。

我认为这是有道理的:

想象一个有多个提交按钮的巨大表单。在顶部,有一个“删除这条记录”按钮,然后有很多输入,在底部有一个“更新这条记录”按钮。当用户在表单底部的字段中按Enter时,他/她永远不会怀疑他/她从顶部隐式地按下了“删除此记录”。

因此,我认为使用用户没有定义(点击)的第一个按钮或任何其他按钮都不是一个好主意。不过,浏览器当然也在这么做。