Web 键盘输入法应用开发指南 (4) —— 组合键
介绍
在 Web 应用程序中,组合键也是一种常用的功能,比如复制-剪切-粘贴的系统功能,ALT+F 打开文件菜单的浏览器功能,以及一些自定义的组合键(比如 Ctrl+Shift+A 完成应用程序的某个操作)。更广义的组合键还包括在某些欧洲键盘布局上,一些特殊字符的输入方式。例如在 Mac OS 的英语键盘上,可以通过Option+Shift+K
组合键输出苹果 Logo 字符(这里没有写出该字符是因为,在 Windows 上没有苹果的字体,无法正确显示该 Unicode 字符)。在这篇文章中我们来看看组合键的处理实践。
事件处理
一般来说,涉及系统的快捷键,都会被系统首先截获并处理,然后才会发送给浏览器,触发相应的按键事件进行处理。我们这里关注的就是浏览器通过事件提供给应用程序的这一部分,如果发现浏览器中有事件的缺失,首先要考虑操作系统的实现,是否为了某种目的少发了一些事件,比如 Windows 10 系统 2004 以后的版本可能会有此问题,又是 ALT/SHIFT/CTRL 组合键的 keyup 事件会被丢掉)。
然后再考虑是否是输入法等系统软件吃掉了一些事件,比如有些快捷键恰好能被输入法响应(如 Ctrl+Space 等);再考虑浏览器在当前系统上的实现,比如一些 Linux 系统上的 Firefox 浏览器与 Windows 的实现有较大差异。排除了这些兼容性问题后,我们就可以把精力放在应用程序对事件的处理上了。
常规组合键
我们先来看常规组合键。以ALT+SHIFT
为例,如果想在用户按住 ALT 键然后按下 SHIFT 键时做一些事情,通常的做法是:先捕获 ALT 的keydown
事件,然后记住 ALT 被按下的状态后马上返回;等到 SHIFT 的 keydown 事件到达时,判断 SHIFT 按键事件的altKey
是否为true
(是否按住了 ALT 键);如果为true
,则满足期待的条件,进行下一步处理。
如代码所示,当前事件(event)为 ALT 触发时(keyCode = 18
),记住当前的事件对象,然后返回true
,表示让事件继续传播,保持默认行为,可能有其他的事件处理器需要。在接下来的某个按键(如 SHIFT)事件触发时,一同处理刚才的 ALT 和这个键,并清空刚才的 ALT 状态。这样我们就是知道是组合键生效了,而不是单独按了 ALT 键或者其他键。当然,如果 ALT+SHIFT 后面还有键,比如一个字母键F
作为组合键,则对 SHIFT 也要做类似处理,并在字母键到达时,判断 ALT 和 SHIFT 的状态。
需要注意的是,一些组合键会被系统上的键盘或输入法框架首先捕获,如 Windows 上的ALT+SHIFT
,以及 Mac 上的CTRL+SPACE
,都可以切换系统当前的输入法或者键盘,然后才被浏览器处理。
我们的 Web 应用程序可能要避开这些系统的组合键,因此要对这类组合键事件选择性地忽略。要做到这一点,也要首先识别出组合键,方法与上面类似,然后直到用户的输入不满足组合键的模式时,才继续处理。
比如我们要忽略 ALT+SHIFT,那么在 ALT 键按下时我们不能进行常规处理,而是要阻塞住并等待后续按键。当 SHIFT 按下时,我们依然不能常规处理,直到用户后面又按下了字母键 F,前面阻塞的 ALT 和 SHIFT 才会继续处理。此时应用程序认为用户按的是 ALT+SHIT+F 的序列,而不是 ALT+SHIFT 的组合键,因此要解除阻塞正常处理。这里面涉及的逻辑很容易出 bug,要多调试多测试,原则就是既能保证目标组合键被忽略,又不破坏正常的按键序列。
在某些欧洲语言中(比如法语),一些字符(货币符号、口音符号等)需要AltGraph
键[1]配合完成输入。AltGraph 是一种修饰符(modifier)键,在 Windows 上,该键就是键盘右侧的 ALT 键。对于系统本身来说,在组合键中使用左边还是右边的 ALT 键效果是类似的。
但到了浏览器环境就不一样了,一些浏览器会将右边 ALT 键转换为一个 CTRL 键加上一个左边的 ALT 键的组合。这会增加我们应用程序的处理复杂性,不过对于支持多语言输入的应用程序来说,这也是必须考虑的一个点。
修饰符键
正如前文所述,一些欧洲语言中的字符需要借助 AltGraph 或者 Option 等功能键组合完成输入,这类组合键严格意义来说并不是真的组合键,因为它完成的还是输入字符本身,而不是一些功能性的行为。对于这类组合键,浏览器的一般会使用keypress
事件获取输入的结果。
比如在 Mac OS 上,当输入Option+字母P
会产生π
这个字符。在对应的 keypress 事件中,code
属性的值为“KeyP”,表示字母 P 这个位置的键被按下了;key
属性的值为“π”,表示最终的输入结果。关于 key 和 code 属性的详情,可以参考这个系列的第二篇文章。
有时,组合键的输出结果还有 CapsLock 键的状态相关,我们可以通过 event 对象上的getModifierState
方法来检查这个状态[2]。
总结
涉及组合键的处理通常比较复杂,要想消除 bug 需要尽量考虑多语言、多平台的兼容性,多做回归测试。另外,有些组合键的顺序也比较关键,哪个键先按下,哪个键先释放,都对处理逻辑有影响,这些都需要经验的积累。下一讲我会分享一些与实践相关的技巧。
参考阅读
[1] AltGraph Key
[2] CapsLock State
系列导航
如果您对这个系列感兴趣,可以通过下面的导航找到对应文章👇🏻。
版权声明: 本文为 InfoQ 作者【天择】的原创文章。
原文链接:【http://xie.infoq.cn/article/aa6d2d1f42a6696a7e9ec5d72】。文章转载请联系作者。
评论