javascript - 将 Javascript keyCode 转换为非美国键盘布局的 charCode(即 azerty)

标签 javascript html browser cross-browser

快速背景:

  • 当在浏览器中按下一个键时,会生成三个事件:keyDownkeyPresskeyUp
  • 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 游戏,因为您通常希望能够了解有关所按按键的完整信息,而不触发对该按键的任何其他浏览器响应。

有用的链接:

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

最佳答案

我已经解决了我自己的问题。它不是 100% 的解决方案,但它应该涵盖大部分所需内容。希望当浏览器 vendor 开始集成时会有一个更清洁的解决方案 DOM Level 3 Events .

只是重申主要限制条件:

  1. 按键按下和按键弹起事件应该在实际发生时报告/发送。 IE。在 keyPress 事件期间同时发送按键和按键是不够的。
  2. 许多组合键必须在 keyDown 事件期间完全处理,因为它们永远不会触发 keyPress 事件(即 Ctrl 键),或者因为默认操作必须在 keyDown (WebKit) 中停止,这样做可以防止 keyPress 事件发生。
  3. 按键和按键事件应该报告翻译后的字符代码,而不是 keyCode 值。

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

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

    • 安全:在 keyPress 之前什么都不做。

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

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

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

    • 不安全:什么都不做,因为它已经在 keyDown 期间报告/发送。

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

一些有趣的额外链接:

关于javascript - 将 Javascript keyCode 转换为非美国键盘布局的 charCode(即 azerty),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5306132/

相关文章:

javascript - 如何在 jquery 中制作 ul 和 li 的框图?

javascript - 如何动态创建html元素?

html - Flex 从外部浏览器中的 HTML 组件打开 url

javascript - 使用cordova、android应用程序捕获和上传选项的不同图像路径

javascript - 覆盖正文区域的垂直侧边菜单

jquery - 使用AngularJS双击获取li的子div id

javascript - 如何对已经由前进动画处理的元素应用悬停效果?

.net - 以编程方式滚动 WebBrowser 有时不起作用

javascript - JS进入页面和刷新页面的区别

javascript - Vue3在js文件中使用全局变量