我对javascript中的关键事件不是很满意。我需要捕获两个写字母(我在<canvas>
上写文字)和其他命令的功能键(转义)。
在Firefox中可行,因为Firefox会为任何键触发keypress
事件。这很舒服,但specification directly permits it:
如果用户代理支持,则必须在按下某个键时调度此事件,当且仅当该键通常产生字符值时才会发送。
我不同意该规范,因为我认为没有理由。但就像现在一样,我对此无能为力。
问题是Google Chrome遵循该规范,并且不会针对功能键触发keypress
。但是,它确实会为所有密钥发送keydown
。
我的程序只有一个关键事件处理程序。它期望事件包含keyCode
(物理密钥的ID和可选 charCode
,等效字符值(对于有意义的密钥)。
keydown
事件在两个浏览器中都不包含任何字符值!它只包含keyCode
。因此,如果您定义 Ctrl + Z 组合并监听keydown
事件,那么对于拥有QWERTZ的用户,您的程序将被破坏布局 - 因为密钥(keyCode
)的物理位置仍然相同。
如果您同时收听keydown
和keypress
,则字符事件将触发两次(因为首先触发keydown
然后keypress
具有正确的charCode
属性)
基于以上所述,我需要忽略导致keydown
的密钥的keypress
事件。这样做,我将能够捕获keydown
中的 Esc 和keypress
中的字符。
我怎么可能这样做?
//Keypress for character codes
div.addEventListener("keypress", function(event) {
console.log(event);
if(_this.editor.event(event)) {
console.log("Event canceled.");
event.preventDefault();
event.cancelBubble = true;
return false;
}
return true;
});
//Keydown for Esc and the likes
div.addEventListener("keydown", function(event) {
//Character events are handled by keypress
if(event.charCode!=0) //Does NOT work - in keydown, charCode is ALLWAYS 0
return true;
console.log(event);
if(_this.editor.event(event)) {
console.log("Event canceled.");
event.preventDefault();
event.cancelBubble = true;
return false;
}
return true;
});
我认为我花了很多时间制作JSFiddles并没有真正增加获得答案的几率,所以我上传了实际的项目。
点击Firefox中的白色方块,按 T ,输入文字,按 Esc ,按 Esc 。在秒 Esc 之后,光标应该恢复正常。尝试绘制并按 Ctrl + Z 。
在Google Chrome中重复此过程。 Escape不起作用,因为它不会触发keypress
。出于某种原因, Ctrl + Z 会使用keyCode
26来触发事件。
@someDoge has created a fiddle我已经扩展了,现在很好地展示了这种情况。如您所见,您可以知道键不是字符并在按键中忽略它。但你不能知道 tab 不是字符并在keydown
中取消它(除非你在注释中有@someDoge sugest的固定数组的键码值)。
答案 0 :(得分:2)
您需要监听keyup
个事件而不是keydown
,这样您就不会生成两个单独的事件。
然后,您可以使用相同的处理函数处理2个事件类型,这些函数将获得charCode,具体取决于特定键是否生成了“keypress”事件。只要你防止冒泡,你的处理程序只会被调用一次。
关于Chrome CTRL + Z问题:如果按下控制键,我看不到如何获取charCode,因为它似乎只会生成一个keyup事件。