检测命令 + Safari 中的按键
我正在尝试拦截 Safari 中的命令+按键。我添加了一个事件处理程序,如下所示:
document.onkeypress = handleKeyPress;
function handleKeyPress(event) {
if ("+" === String.fromCharCode(event.charCode) && event.metaKey) {
// my code here
return false;
}
return true;
}
当我点击 command shift = (shift = 在我的美国键盘上是 +
),if 语句不会返回 true。
如果我删除 if 语句的 event.metaKey 部分并点击 shift =,则 if 语句确实返回 true。
另外,如果我将匹配字符串从“+”更改为“=”并点击 command = (使用或不使用 Shift 键),if 语句确实返回 true。
有没有一种方法可以实际检测命令+按键(不假设+键是shift =并检查event.shiftKey,因为对于某些非美国键盘来说并非如此)?
I'm trying to intercept the command + keystroke in Safari. I've added an event handler as follows:
document.onkeypress = handleKeyPress;
function handleKeyPress(event) {
if ("+" === String.fromCharCode(event.charCode) && event.metaKey) {
// my code here
return false;
}
return true;
}
When I hit command shift = (shift = is +
on my US keyboard), the if statement does not return true.
If I remove the event.metaKey portion of the if statement and hit shift =, the if statement does return true.
Also, if I change the matching string from "+" to "=" and hit command = (with or without the shift key), the if statement does return true.
Is there a way to actually detect the command + keypress (without assuming that the + key is shift = and checking for the event.shiftKey, since this will not be true for some non-US keyboards)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,我不一定推荐使用 ⌘+ 作为快捷方式,因为它在 Safari 中已经意味着某些功能(即缩放页面)。有人可能希望它仍然正常工作。根据您正在构建的内容,这可能有意义,但除非您确定,否则不要覆盖默认快捷方式。
无论如何:按键事件很棘手,通常是因为 keyCode/charCode/which 属性并不总是匹配加上正确的字母,因此
String.fromCharCode
并不总能得到正确的字符串。keyIdentifier
有时看起来更好,但并非总是如此(例如,其字母键的代码始终是大写字母)。我过去所做的(我不确定这是最好的方法,但它工作正常),是监听 keydown 和 keyup 事件以及“堆栈”修饰键。即,每当按下某个键时,检查它是否是修饰键(即是否是 cmd、ctrl、alt 或 shift)。如果是,请将其添加到修饰符“堆栈”中。在 keyup 上执行相反的操作;如果释放的键是修饰符,则将其从堆栈中删除。
现在,回到 keydown 处理程序,如果该键不是修饰键,您可以发送 keydown 事件(与按键事件不同,该事件将有一个非常可靠的
keyIdentifier
属性来检查) ,以及修饰符堆栈以及其他一些回调,将从那里获取它。在您的情况下,这样的回调将检查 cmd-key 是否在堆栈中,以及 keydown 事件的 keyIdentifier 是否为“U+002B”(这是
+
的 unicode 代码)。我整理了一个 jsfiddle 示例来说明我正在谈论的内容。如果您单击“结果”窗格(以确保它获得焦点),然后按 ⌘+,它应该显示您使用的组合键,并写下“成功!”以下。否则,它只会显示组合键。在我的键盘上,可以直接访问加号,因此我看到的组合键只是“⌘+”。但如果您需要 Shift 来输入加号,您应该会看到“⇧⌘+”。
这是一段通用代码,非常适合处理 Safari/Mac 中的键盘快捷键,因此如果需要,您可以在其基础上进行构建。您需要添加一些事件侦听器来重置模糊事件等的修改器堆栈。理想情况下,当您释放按键时,修改器堆栈会自动重置,但由于某些原因可能会导致浏览器或观察到的元素/窗口/文档失去焦点,因此不会处理 keyup 事件,并且释放的按键将不会被处理。不从堆栈中删除。因此检查模糊事件。
First of all, I can't necessarily recommend using ⌘+ as a shortcut, since it already means something in Safari (namely, zoom the page). Someone might want that to still work normally. Depending on what you're building, it might make sense, but don't override the default shortcuts unless you're sure.
Anyway: Key events are tricky, often because the keyCode/charCode/which properties don't always match up with the right letter, so
String.fromCharCode
won't always get you a proper string.keyIdentifier
is sometimes a better thing to look at, but not always (for instance, its codes for letter keys are always uppercase letters).What I've done in the past (and I'm not sure that this is the best way to do it, but it works ok), is to instead listen for keydown and keyup events, and "stack" modifier keys. I.e. whenever a key is depressed, check whether it's a modifier key (i.e. if it's cmd, ctrl, alt, or shift). If it is, add it to the "stack" of modifiers. Do the opposite on keyup; if the released key was a modifier, remove it from the stack.
Now, back in the keydown-handler, if the key wasn't a modifier key, you can send the keydown event (which, unlike a keypress event, will have a pretty reliable
keyIdentifier
property to check), and the stack of modifiers along to some other callback, that'll take it from there.In your case, such a callback would check that the cmd-key is in the stack, and that the keyIdentifier for the keydown event is "U+002B" (which is the unicode code for
+
).I've put together a jsfiddle example of what I'm talking about. If you click in the "Result" pane (to make sure it's got focus), and press ⌘+, it should show the key combo you used, and write "Success!" below. Otherwise, it'll just show the key combo. On my keyboard, the plus sign is directly accessible, so the key combo I see is just "⌘+". But if you need shift to type a plus sign, you should see "⇧⌘+".
It's a generalized piece of code that's good for handling keyboard shortcuts in Safari/Mac, so you can build on it, if you want. You'll want to add a few event listeners to reset the modifier stack on blur events and such. Ideally, the modifier stack would reset automatically, as you release the keys, but since something might cause the browser, or the observed element/window/document, to lose focus, the keyup events won't be handled, and the released keys won't be removed from the stack. So check for blur events.
在一级窗口对象中注册事件对象,例如 event = window.EE,然后使用 Firebug 或 Safari 的 Web 开发人员工具浏览它并查看所需时触发的值。这样你就会知道要与什么进行比较。
Register the event object in a window object level one, event = window.EE for example, then browse it with Firebug or Safari’s Web Developer Tools and see the values that are triggered when you want. So you will know what to compare against.
可悲的是,我认为没有答案。问题是,对于
CMD+SHIFT+=
,按下的charCode
是 61 (=
),而不是 43 (+
>)。这似乎是一个系统范围的设计,因为 Mac OS X 本身将CMD+SHIFT+=
解释为=
加两个修饰符,而不是+
和命令。我整理了一个简单的 jsFiddle 来展示这一点: http://jsfiddle.net/ScuDj/1/
基本上,如果您想检测
COMMAND +
,则必须处理键盘布局。或者,您可以只支持数字键盘
+
- 一致工作! (开个玩笑;-)(另外:我尝试附加到
textInput
事件,但无法让它全局注册。我认为它只适用于 domNodes。我还没有真正使用过它事件很多。)Sadly, I don't think there is an answer. The problem is, for
CMD+SHIFT+=
thecharCode
being pressed is 61 (=
), not 43 (+
). This appears to be a system-wide design, in that Mac OS X itself interpretsCMD+SHIFT+=
as=
plus two modifiers, not+
andCOMMAND
.I put together a simple jsFiddle to show this: http://jsfiddle.net/ScuDj/1/
Basically, you are going to have to deal with keyboard layouts if you want to detect
COMMAND +
.Alternatively, you could only support the numeric keypad
+
- that works consistently! (just kidding ;-)(Also: I tried to attach to the
textInput
event, but couldn't get it to register globally. I think it only works on domNodes. I've not really used that event much.)