我在 Mac 版 Firefox 中遇到 keydown 事件和自动完成问题
这让我抓狂。这很难解释,但我会尝试一下。
我的网站首页上有一个输入文本字段。我编写了一个 keydown 事件观察器,它检查 keyCode,如果它是 ENTER (或等效值),它将检查输入值(电子邮件)。如果电子邮件在数据库中有效且唯一,它将提交表单。基本的东西,或者你可能会这么想。
如果我在字段中输入我的电子邮件地址并按 Enter 键,它在所有浏览器中都可以正常工作。但是,如果我键入前几个字母,然后使用箭头键从历史记录下拉框中选择电子邮件(希望您知道我在这里的意思),然后按 Enter 键,结果会有所不同。表单字段的值仅被捕获为我输入的几个字母,因此验证失败。似乎当我按回车键从历史记录下拉列表中“选择”电子邮件时,浏览器会中断它,就像我正在打字一样。
在 Chrome 和 Safari 中,它可以正常工作。这意味着当您按 Enter 键从历史记录下拉列表中“选择”电子邮件时,它所做的只是将该电子邮件地址放入文本框中。只有在第二次按下 ENTER 键时,才会触发事件观察器,并且电子邮件将被验证。
希望有人能够解释为什么会发生这种情况......我的直觉是它是浏览器的问题,并且将是我无法修复的问题。
谢谢 李
编辑: 为了澄清我的问题,让我补充一点,我使用“keydown”事件来捕获按下 Enter 键的时刻。我尝试过“keyup”事件,这解决了我上面的问题,但我似乎无法阻止表单自行提交。 “keyup”事件在默认行为之后触发,因此它不是正确的选择。
进一步编辑:
再次感谢您,顺便说一句,您的英语非常好(回应您关于英语不好的评论)。
我已将事件处理程序从以下更改
$("emailInputBox").observe("keydown", function(event) {
return submitViaEnter(event, submitSignupFormOne);
});
为:
$("emailInputBox").observe("keydown", function(event) {
setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0);
});
submitViaEnter
:
function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
event.stop();
return callback(event);
}
return true;
}
似乎可以工作,但现在的问题是浏览器被允许在运行 submitViaEnter
之前执行默认操作> 函数,这意味着当我按 ENTER 键时正在提交表单。
This is driving me nuts. Its a tough one to explain but I'll have a go.
I have one input text field on the front page of my site. I have coded a keydown event observer which checks the keyCode and if its ENTER (or equiv), itll check the input value (email). If the email is valid and unique in the DB itll submit the form. Basic stuff, or so you would think.
If I type my email address in the field and hit enter, it works fine in all browsers. However, if I type the first couple of letters, and then use the arrow keys to select the email from the history dropdown box (hope you know what I mean here), and then press enter the result is different. The value of the form field is being captured as just the couple of letters I typed, and therefore the validation is failing. It seems that when I press the enter key to "select" the email from the history dropdown, the browser is interrupting that as if I was typing.
In Chrome and Safari it works as it should. As it should means that when you press enter to "select" the email from the history dropdown, all it does is puts that email address into the text box. Only on the second ENTER key press does it then trigger the event observer, and the email is validated.
Hope somebody can shed some light on why this is happening... My gut feeling is its a browser thing and will be something I cant fix.
Thanks
Lee
EDIT:
To add clarification to my question let me add that Im using the "keydown" event to capture the moment when the enter key is pressed. I have tried the "keyup" event and this solved my problem above, but then I cant seem to stop the form submitting by itself. The "keyup" event triggers AFTER the default behaviour, therefore its not the right choice for this.
FURTHER EDIT:
Thank you again, and btw, your English is excellent (in response to your comment about bad English).
I have changed my event handler from this:
$("emailInputBox").observe("keydown", function(event) {
return submitViaEnter(event, submitSignupFormOne);
});
to this:
$("emailInputBox").observe("keydown", function(event) {
setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0);
});
submitViaEnter
:
function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
event.stop();
return callback(event);
}
return true;
}
Seems to work but the problem now is that the browser is permitted to carry out the default action before running the submitViaEnter
function which means the form is being submitted when I hit ENTER.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
原始问题的答案
是的,这是一个 Gecko 错误(尽管不是 Mac 特有的)。
此评论的最后部分包含解决方法的描述:使用超时。
[编辑]因为您要求澄清错误
当您按 Enter 并且自动完成功能处于活动状态时,Firefox(错误地)首先触发页面的键处理程序,然后关闭浏览器的内部键处理程序自动完成弹出窗口并更新文本区域值,而可以说它应该在自动完成弹出窗口中触发它,并且只让页面知道文本框值已更改。
这意味着当您的键处理程序被调用时,自动完成的处理程序尚未运行 - 自动完成弹出窗口仍然打开,并且文本框值就像自动完成发生之前一样。
当您向按键处理程序添加
setTimeout
调用时,您就是在对浏览器说“嘿,在完成 P1 待办事项列表中已有的操作后立即运行此函数”。因此,自动完成的处理程序会运行,因为它已经在待办事项列表中,然后当自动完成弹出窗口已经关闭并且文本框的值已更新时,您放置在超时上的代码就会运行。[编辑]回答“进一步编辑”中的问题
对。如果您希望它起作用,您需要取消事件处理程序中的默认操作,而不是超时中的默认操作:
如果您仍然想在 Enter 上提交表单,这将是一个更有趣的练习,但它似乎并不适合您。做。
Answer to the original question
Yeah, it's a Gecko bug (not Mac-specific though).
The last part of this comment contains the description of the work-around: use the time-out.
[edit] since you asked for the clarification of the bug
When you press Enter and the auto-complete is active, Firefox (erroneously) first fires the page's key handler, then the browser's internal key handler that closes the autocomplete popup and updates the text area value, while it arguably should just fire it at the autocomplete popup and only let the page know the textbox value changed.
This means that when your key handler is called, the autocomplete's handler hasn't run yet -- the autocomplete popup is still open and the textbox value is like it was just before the auto-completion happened.
When you add a
setTimeout
call to your key handler you're saying to the browser "hey, run this function right after you finished doing stuff already in your P1 to-do list". So the autocomplete's handler runs, since it's already in the to-do list, then the code you put on a time-out runs -- when the autocomplete popup is already closed and the textbox's value updated.[edit] answering the question in "Further edit"
Right. You need to cancel the default action in the event handler, not in the timeout, if you want it to work:
If you still wanted to submit the form on Enter, it would be a more interesting exercise, but it doesn't seem you do.
好的,排序了。非常感谢您的帮助。这是我之前缺少的 curry 函数。我试图在 setTimeout 函数的范围内处理该事件。
这在下面起作用。从 eventobserver 调用 SubmitViaEnter 并响应 keyDown 事件:
停止 eventObserver 内的默认操作意味着无法键入任何字符。所以我陷入了 if ENTER 键子句中。
ok sorted it. Thanks so much for your help. It was the curry function that I was missing before. I was trying to work on the event inside the scope of the setTimeout function.
This works below. The submitViaEnter is called from the eventobserver and responds to the keyDown event:
Stopping the default action inside the eventObserver meant that no characters could be typed. So I stuck inside the if ENTER key clause.