如果提交了表单,但不是通过任何特定的按钮,例如
按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>
If you submit the form via JavaScript (i.e., formElement.submit() or anything equivalent), then none of the submit buttons are considered successful and none of their values are included in the submitted data. (Note that if you submit the form by using submitElement.click() then the submit that you had a reference to is considered active; this doesn't really fall under the remit of your question since here the submit button is unambiguous but I thought I'd include it for people who read the first part and wonder how to make a submit button successful via JavaScript form submission. Of course, the form's onsubmit handlers will still fire this way whereas they wouldn't via form.submit() so that's another kettle of fish...)
If the form is submitted by hitting Enter while in a non-textarea field, then it's actually down to the user agent to decide what it wants here. The specifications don't say anything about submitting a form using the Enter key while in a text entry field (if you tab to a button and activate it using space or whatever, then there's no problem as that specific submit button is unambiguously used). All it says is that a form must be submitted when a submit button is activated. It's not even a requirement that hitting Enter in e.g. a text input will submit the form.
我相信Internet Explorer会选择在源代码中首先出现的提交按钮;我有一种感觉,Firefox和Opera会选择标签索引最低的按钮,如果没有其他定义,就会退回到第一个定义的按钮。关于提交是否具有非默认值属性IIRC,也存在一些复杂性。
The point to take away is that there is no defined standard for what happens here and it's entirely at the whim of the browser - so as far as possible in whatever you're doing, try to avoid relying on any particular behaviour. If you really must know, you can probably find out the behaviour of the various browser versions, but when I investigated this a while back there were some quite convoluted conditions (which of course are subject to change with new browser versions) and I'd advise you to avoid it if possible!
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.
我有一个带有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例程将验证它们。
现在可以使用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