如果表单已提交但未通过任何特定按钮提交,例如
HTMLFormElement.submit()
浏览器应该如何确定多个提交按钮中的哪一个(如果有的话)用作按下的按钮?
这在两个层面上很重要:
onclick
事件处理程序到目前为止,我的实验表明:
标准说什么?
如果它有用,这是我的测试代码(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>
答案 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 owner是formdefault 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的旧浏览器,它们仍然可以获得可行的解决方案,但这些元素不会被颠倒。
答案 6 :(得分:2)
我在同一个问题上挣扎,因为我在重定向提交到另一个页面的中间提交了按钮,如下所示:
<button type="submit" onclick="this.form.action = '#another_page'">More</button>
当用户按下回车键时,单击此按钮而不是另一个提交按钮。
所以我做了一些原始测试,创建了一个带有多个提交按钮和不同可见性选项的on和onclick事件提醒单击了哪个按钮:https://jsfiddle.net/aqfy51om/1/
我用于测试的浏览器和操作系统:
<强> WINDOWS 强>
<强> OSX 强>
大多数浏览器都点击了第一个按钮,尽管应用了可见性选项 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>
所以我的建议,我将自己使用,是:
如果您的表单有多个具有不同含义的提交按钮,则在表单的开头包含带有默认操作的提交按钮:
style="width: 0; height: 0; overflow: hidden;"
修改强>
另一个选择可能是偏移按钮(仍然在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" />