将Javascript keyCode转换为charCode,用于非美国键盘布局(即azerty)

kan*_*aka 16 javascript browser html5 cross-browser

快速背景:

  • 当在浏览器中按下某个键时,会生成三个事件:keyDown,keyPresskeyUp.
  • keyDownkeyUp有一个keyCode属性,大约是按下的物理键.
  • keyPress还具有charCode属性集,该属性集考虑了修饰键和键盘布局(A和a具有相同的keyCode但具有不同的charCode).
  • 所有三个事件都具有指示在这些事件期间按下了哪些修改键的属性.

我是主要的noVNC开发人员,我遇到了一个棘手的问题:noVNC需要转换的charCode值而不使用keyPress事件,原因如下:

  • noVNC需要将keyDown和keyUp事件分别发送到VNC服务器(否则它不是一个功能完备的VNC客户端).
  • 更重要的是,noVNC需要在连接时阻止默认键盘操作,这意味着调用keyDown事件的preventDefault()方法.这具有防止keyPress事件被触发的副作用.

由于键盘布局的不同(即不同的keyCode到charCode映射),我确定noVNC将需要一个用于不同键盘布局的查找表.

但这是真正的问题:在备用布局上,一些不同的物理键具有SAME keyCode.例如,使用azerty(法语)键盘布局,' - '(破折号)和'_'下划线键都生成keyCode 189. Ack !!!

那么......我如何获得正确的keyCode到charCode映射并同时防止默认的浏览器操作?

顺便说一句,我怀疑这个解决方案适用于其他交互式Web应用程序和HTML5游戏,因为您经常希望能够了解有关按键的完整信息,而不会触发对该按键的任何其他浏览器响应.

有用的链接:

解决方案:请参阅下面的帖子.

kan*_*aka 8

我已经解决了我自己的问题.它不是100%的解决方案,但它应该涵盖大部分需要的东西.希望浏览器供应商开始集成DOM Level 3 Events时会有更清晰的解决方案.

只是重新迭代主要约束:

  1. 按键和按键事件应在实际发生时报告/发送.即,在keyPress事件期间发送密钥并将密钥连接在一起是不够的.
  2. 在keyDown事件期间必须完全处理许多键组合,因为它们从不触发keyPress事件(即Ctrl键),或者因为必须在keyDown(WebKit)中停止默认操作,这样做会阻止keyPress事件发生.
  3. 键向下和键事件应报告翻译的字符代码而不是keyCode值.

如果没有一些开箱即用的顿悟,当前的浏览器实现似乎会阻止所有三个约束完全实现.所以我决定稍微放松约束#3.

  • 在浏览器keyDown事件上将事件添加到按键向下列表,并检查它是否是安全的(没有不受欢迎的浏览器默认行为)组合键:

    • 安全:直到keyPress才做任何事.

    • 不安全:立即报告/发送按键事件.这就是约束#3被放宽的地方,因为这些有限的键组合没有被转换为字符代码(尽管它们中的许多都没有它们).

  • 在浏览器keyPress事件(在keyDown事件之后立即发生)检查它是否是一个安全的组合键:

    • 安全:报告/发送按键事件.使用已翻译的字符代码(event.which)更新按键向下列表.

    • 不安全:不执行任何操作,因为它已在keyDown期间报告/发送.

  • 在浏览器keyUp事件上,从按键列表中查找并删除匹配事件,并使用已翻译的代码报告/发送按键事件.

有趣的一些额外链接: