在不同的框中按 Enter 时防止按钮上的 onclick 事件触发
Posted
技术标签:
【中文标题】在不同的框中按 Enter 时防止按钮上的 onclick 事件触发【英文标题】:Prevent onclick event on a button from firing when hitting Enter in a different box 【发布时间】:2018-11-19 03:15:24 【问题描述】:我需要在 SE 编辑器的 #wmd-button-bar
中有一个用户输入字段,以及一个按钮。用户可以在输入字段中输入一些数据,然后按一个按钮来处理该数据。我正在使用用户脚本来实现这一点。我已经创建了一个单独的 MVCE,这里是 Tampermonkey/Greasemonkey 的 direct install link。
要重现该问题,请安装用户脚本。重新加载此页面,然后单击“编辑”。您会注意到一个带有按钮的新空白输入框。将“编辑摘要”框设为空白,将其留空,然后按 Enter。现在,您的插入符号将不再提交答案框,而是专注于新的空白输入框。
如果您在“问题标题”框中按 Enter,也会发生同样的情况。
从console.log
消息中,您会注意到按钮上有一个MouseClick
事件!这不是预期的行为。事实上,这怎么可能?我们只是在 Edit summary 框中按 Enter 键,甚至没有触摸新的空白输入或其按钮。那么它是如何注册鼠标点击的呢?
如何解决这个问题?
注意:按钮onclick
处理程序内的e.preventDefault();
是必需的。否则,当用户按下按钮来处理他们的输入数据时,答案框会自行提交。
The Userscript Code:
function createModal(buttonBar)
var div = document.createElement("div"),
input = document.createElement("input"),
btn = document.createElement("button");
div.id = "box";
input.type = "text";
btn.innerhtml = "Button";
btn.onclick = function(e)
e.preventDefault();
console.log("I was called");
input.focus();
console.dir(e);
console.trace();
;
div.appendChild(input);
div.appendChild(btn);
return div;
setInterval(function ()
var cont = document.querySelector(".wmd-container:not(.processed)"), ul, buttonBar, div;
if (cont && (ul = cont.querySelector(".wmd-button-bar ul")))
cont.classList.add("processed");
buttonBar = cont.querySelector("div[id^=wmd-button-bar]");
div = createModal(buttonBar);
buttonBar.appendChild(div);
, 500)
【问题讨论】:
您是否尝试过定义一个按键事件来按下回车键并将 e.preventDefault() 放入回调中?这可能会有所帮助。 @MarziehBahri 抱歉,我不希望禁用在编辑摘要框中按 Enter 键提交帖子的默认行为。所以,我不能那样做。 一种可能性是 -form
仅包含 input
文本在 Enter 按下时提交。这可能会触发所有提交活动,例如单击。如果是这种情况,那么您可以删除父表单元素或再添加一个隐藏的输入元素。或者添加stopPropagation
,通过回车键只触发一个提交事件。
您可以尝试的一个拼凑方法是在输入框上添加一个事件处理程序,用于输入按下,例如 - function preventSubmission(e) e.preventDefault();或者在输入处理程序中设置一个信号量/标志并在点击处理程序中检查它并相应地阻止操作。
【参考方案1】:
它的默认 HTML 行为。 form
中的所有buttons
都属于type="submit"
。在按下enter
时,默认情况下会单击form
的最新按钮并调用它们的处理程序。为了解决这个问题,按钮是用type="button"
创建的。
console.log(document.querySelector("#a").type)
console.log(document.querySelector("#b").type)
console.log(document.querySelector("#c").type)
<form>
<input type="text">
<button id="a" onclick="console.log('a')">Submit type</button>
<button id="b" onclick="console.log('b')" type="button">Button type</button>
<input id="c" type="submit" value="Input Submit type">
</form>
您可以refer this了解<button>
和<input type="button">
的行为。
如果您只是检查控制台,document.querySelector("#box").children[1].type
将显示为submit
。
默认情况下,按钮充当submit
类型,除非明确指定(submit
(default)/reset
/button
)。只需运行document.querySelector("#box").children[1].type=button
。您会发现它按预期工作。
在跨浏览器中的行为是相同的,并在Firefox Nightly
(开发版)、Chrome
、Safari
和works a little bit different in IE
中进行了测试。
您还可以看到默认情况下点击是console.log(event.detail)
是0
,因为它是在内部触发的。当通过左键单击触发时,它将是1
。 MDN Docs on click event
【讨论】:
【参考方案2】:简短而简单的答案是为您的按钮元素强制键入:
<button type="button"></button>
它默认为type="submit"
,这就是它采取相应行动的原因。
【讨论】:
这个答案被低估了。【参考方案3】:我在 Firefox 浏览器中尝试了以下代码,它按预期工作。
function createModal(buttonBar)
var div = document.createElement("div"),
input = document.createElement("input"),
btn = document.createElement("button");
div.id = "box";
input.type = "text";
btn.type = "button";
btn.innerHTML = "Button";
btn.onclick = function(e)
console.log("I was called");
input.focus();
console.dir(e);
console.trace();
;
div.appendChild(input);
div.appendChild(btn);
return div;
setInterval(function ()
var cont = document.querySelector(".wmd-container:not(.processed)"), ul, buttonBar, div;
if (cont && (ul = cont.querySelector(".wmd-button-bar ul")))
cont.classList.add("processed");
buttonBar = cont.querySelector("div[id^=wmd-button-bar]");
div = createModal(buttonBar);
buttonBar.appendChild(div);
, 500);
请注意,我已经设置了btn.type="button";
,这确保了表单没有被提交,并且还删除了e.preventDefault();
,因为按钮现在永远不会提交表单。
请记住,默认情况下,如果您不将 type
赋予 button
元素,那么它的行为将类似于 submit
按钮。
MouseClick
事件也被触发,因为在提交表单时,在表单中存在的提交按钮上触发了 click 事件。因为你有没有type
属性的按钮,所以它就像一个提交按钮。所以MouseClick
事件在您按下回车时被触发(作为提交表单)。
您可以通过将浏览器开发人员工具中的onclick
处理程序添加到Save edits
提交按钮并在文本字段上按Enter 来验证这一点。
【讨论】:
以上是关于在不同的框中按 Enter 时防止按钮上的 onclick 事件触发的主要内容,如果未能解决你的问题,请参考以下文章
C#:如何在文本框中按下输入触发按钮,但仍允许“Ctrl + A”等快捷方式通过?