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

时间:2009-05-29 10:24:52

标签: javascript html cross-browser standards

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

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

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

这在两个层面上很重要:

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

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

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

15 个答案:

答案 0 :(得分:106)

如果您通过Javascript(即formElement.submit()或任何等效内容)提交表单,则提交按钮的 none 将被视为成功,并且其提交的数据中不包含任何值。 (请注意,如果您使用submitElement.click()提交表单,那么您引用的提交被认为是活动的;这并不属于您的问题的范围,因为此处的提交按钮是明确的,但我认为我将它包含在阅读第一部分并想知道如何通过JS表单提交成功提交按钮的人中。当然,表单的onsubmit处理程序仍然会以这种方式触发,而它们不会通过form.submit()所以那是另一条鱼......)

如果在非textarea字段中按Enter键提交表单,那么它实际上是由用户代理决定它在这里需要什么。 specs没有说明在文本输入字段中使用回车键提交表单(如果您选择按钮并使用空格或其他任何方式激活它,那么没有问题,因为特定的提交按钮是毫不含糊地使用)。所有这一切都表明,当激活提交按钮时必须提交表单,甚至不要求输入例如文本输入将提交表单。

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

要点拿走的是,这里发生的事情没有明确的标准,而且完全是浏览器的一时兴起 - 尽可能地在你做的任何事情上,尽量避免依赖任何特定的行为。如果你真的必须知道,你可能会发现各种浏览器版本的行为,但是当我调查这一段时间后,有一些非常复杂的条件(当然可能会随着新的浏览器版本而改变)并且我建议如果可能的话,你要避免它!

答案 1 :(得分:59)

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规范表明多个提交按钮有效,但省略了关于用户代理应如何处理它们的指导,因此浏览器制造商可以按照自己的意愿实施。我发现他们要么在表单中提交第一个提交按钮,要么在当前具有焦点的表单字段之后提交下一个提交按钮。

不幸的是,只需添加 display:none; 样式就行不通,因为W3C规范指出应该从用户交互中排除任何隐藏元素。所以请将它隐藏在普通的视线中!

以上是我最终投入生产的解决方案示例。按Enter键触发默认表单提交是预期的行为,即使存在其他非默认值并且在DOM中的默认提交按钮之前。鼠标/键盘与显式用户输入交互的奖励,同时避免使用javascript处理程序。

注意:通过表单的Tab键不会显示任何视觉元素的焦点,但仍会导致选择不可见的按钮。要避免此问题,只需相应地设置tabindex属性,并在不可见的提交按钮上省略tabindex属性。虽然将这些样式推广到重要部分似乎不合适,但它们应该阻止任何框架或现有按钮样式干扰此修复。此外,那些内联样式肯定是糟糕的形式,但我们在这里证明了概念...不编写生产代码。

答案 2 :(得分:57)

HTML 4没有明确说明。当前的HTML5工作草案specifies that the first submit button must be the default

  

form元素的默认按钮是     第一个submit button     tree order form ownerform     default button元素。

     

如果用户代理支持让用户提交表单     隐式地(例如,在某些平台上点击“输入”键     然后,文本字段被隐式地提交表单)     对activation behavior已定义的表单执行此操作     run synthetic click activation steps必须导致用户代理     default button就此而言     {{3}}

答案 3 :(得分: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;
}
});
}); 

答案 4 :(得分:6)

我有一个表单上有11个提交按钮,当用户按下回车键时,它总是会使用第一个提交按钮。我在别处读到,在表单上有多个提交按钮不是一个好主意(不好的做法),最好的方法是将默认按钮作为表单上的唯一提交按钮。其他按钮应设置为“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。

答案 5 :(得分:5)

现在可以使用flexbox

解决此问题

<强> HTML

mail servers

<强> CSS

<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 */ } 来反转使用display: flex的容器中元素的顺序。这不需要CSS或隐藏元素。对于不支持flexbox的旧浏览器,它们仍然可以获得可行的解决方案,但这些元素不会被颠倒。

<强>演示
http://codepen.io/Godwin/pen/rLVKjm

答案 6 :(得分:2)

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

<button type="submit" onclick="this.form.action = '#another_page'">More</button>

当用户按下回车键时,单击此按钮而不是另一个提交按钮。

所以我做了一些原始测试,创建了一个带有多个提交按钮和不同可见性选项的on和onclick事件提醒单击了哪个按钮:https://jsfiddle.net/aqfy51om/1/

我用于测试的浏览器和操作系统:

<强> WINDOWS

  • Google Chrome 43(来吧谷歌:D)
  • Mozilla Firefox 38
  • Internet Explorer 11
  • Opera 30.0

<强> OSX

  • Google Chrome 43
  • Safari 7.1.6

大多数浏览器都点击了第一个按钮,尽管应用了可见性选项 exept 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;"
  3. 包装在容器中

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

答案 7 :(得分:1)

来自您的评论:

  

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

我将<input type="hidden" value="form_name" />放入每个表单。

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

答案 8 :(得分:1)

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

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

});

答案 9 :(得分:1)

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

前面放置编辑的不那么苛刻和简单
<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');

答案 10 :(得分: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>

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

如果点击它们,它们会有偏好并且它的值会被传递。

答案 11 :(得分: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监听器观察跨度并在单击后执行所需的操作。

不一定适合所有情况,但至少它很容易做到。

答案 12 :(得分:0)

来自HTML 4 spec

  

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

这意味着如果有超过1个提交按钮而没有激活(点击),则不会有任何成功。

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

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

答案 13 :(得分:0)

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

如果您从文本输入中按Enter键,则该按钮将不会被选中,然后我们将忽略此点击,而是单击默认的提交,但是如果您通过鼠标单击该按钮,它将被选中,那么我们将应用此点击< / p>

答案 14 :(得分:-2)

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

要确定点击输入时按下了什么按钮,您可以使用type="submit"进行标记,其他按钮用type="button"标记。例如:

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