Chrome 中的 Keydown 模拟正常触发但不是正确的键

IT技术 javascript google-chrome dom-events
2021-01-26 03:56:52

我想keydown在 html 页面中的给定 textarea 元素上模拟事件。因为我使用的是 Chrome,所以我调用initKeyboardEvent了我的变量,并将keyCode我想要输入的内容传递给了 textarea。这是我尝试过的:

var keyEvent = document.createEvent('KeyboardEvent');
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0);
inputNode.dispatchEvent(keyEvent);

在这段代码中,我正在输入字母,m但是 textarea 只得到keyCode13,这是Enter关键。所以,我尝试了一个我在网上看到的覆盖代码,该代码将值设置为keyCodeVal,但没有成功。

var keyEvent = document.createEvent('KeyboardEvent');
Object.defineProperty(keyEvent, 'keyCode', { 
                         get : function() {
                                 return this.keyCodeVal;
                         }
                        });
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0);
keyEvent.keyCodeVal = 77;
inputNode.dispatchEvent(keyEvent);

有谁知道如何设置keyCode值?

6个回答

所以非常非常接近...

您只需要覆盖 'which' 属性。这是一些示例代码:

Podium = {};
Podium.keydown = function(k) {
    var oEvent = document.createEvent('KeyboardEvent');

    // Chromium Hack
    Object.defineProperty(oEvent, 'keyCode', {
                get : function() {
                    return this.keyCodeVal;
                }
    });     
    Object.defineProperty(oEvent, 'which', {
                get : function() {
                    return this.keyCodeVal;
                }
    });     

    if (oEvent.initKeyboardEvent) {
        oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, k, k);
    } else {
        oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, k, 0);
    }

    oEvent.keyCodeVal = k;

    if (oEvent.keyCode !== k) {
        alert("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ")");
    }

    document.dispatchEvent(oEvent);
}

示例用法:

Podium.keydown(65);

注意:此代码不适用于 IE、Safari 或其他浏览器。好吧,也许用 Firefox。天啊。

适用于 Chrome 28(到目前为止)。
2021-03-17 03:56:52
吸气剂可以简单地返回k无需将keyCodeVal属性附加到事件对象。
2021-03-25 03:56:52
它对我来说很好用,版本 21.0.1180.89。注意虚拟键盘中的按下键 - nt4.com/ss/keydown-65.png也许你误解了它在做什么。虽然我感谢您的担忧,但它们超出了原始问题的范围。@sunglim:感谢您的注意 :) freeall:从哪里开始……“Facebook 自动化”、“TextArea 与输入”、“KeyX 事件与更改 HTML 内容”……都超出了范围。其他所有人 - 这会触发事件,它不会为您输入。
2021-04-02 03:56:52
有人可以发布一个非 jquery 版本的吗?不需要 keydown 方法,因为它在 chrome 44.x 中不起作用。
2021-04-04 03:56:52
我在 Chrome 扩展程序中使用它来触发文本区域上的 keydown 事件(在 Facebook 上)。出于某种原因,站点的处理程序从未被触发,因此它似乎没有响应。知道为什么吗?
2021-04-07 03:56:52

Orwellophile 的解决方案确实有效。

  • 第一:'keyCode'、'charCode' 和 'which' 在 Safari 和 IE9+ 中是只读的(至少)。
  • 第二:initKeyboardEvent 有点乱。所有浏览器都以不同的方式实现它。即使在 webkit 中,initKeyboardEvent 也有几种不同的实现。在 Opera 中没有“好”的 initKeyboardEvent 方法。
  • 第三:不推荐使用 initKeyboardEvent。您需要使用 initKeyEvent 或 KeyboardEvent 构造函数。

这里我写了一个跨浏览器的initKeyboardEvent函数(要点):

例子:

var a = window.crossBrowser_initKeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey)

这是我的带有跨浏览器 KeyboardEvent 构造函数的DOM 键盘事件级别 3 polyfill

例子:

var a = new KeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey)

示例 2

示例 3

重要说明 1:不推荐使用 charCode、keyCode 和哪些属性。因此,我的 crossBrowser_initKeyboardEvent 和 KeyboardEvent 构造函数都不能绝对保证某些浏览器中该属性的正确值。您可以使用属性“key”和“char”来代替,或者编辑我的要点以强制在浏览器中使用只读 charCode、keyCode 和 which 属性使用 initEvent。

重要说明 2:keypress 事件已被弃用,目前在我的键盘事件级别 3 polyfill 中不受支持这意味着 keypress 事件中的 key 和 char 属性可以具有随机值。我正在努力解决该问题以向后兼容。

迄今为止我见过的问题的最佳描述。+1
2021-03-13 03:56:52
好东西,@termi!如果你有机会,请看看你是否能解决stackoverflow.com/questions/32298753/...
2021-03-14 03:56:52
@AkashKava,您尝试“跨浏览器 initKeyboardEvent 函数(要点)”还是 polyfill?Polyfill 已过时。我没有太多空闲时间来修复它。但是“跨浏览器 initKeyboardEvent 函数(要点)”对我有用。你能提供一个例子吗?
2021-04-09 03:56:52
@termi,我曾尝试使用您的源代码在 Chrome 36 上模拟事件,但不起作用!
2021-04-11 03:56:52

为了让@Orwellophile 的脚本在 Google Chrome 26.0.1410.65 上运行(在 Mac OS X 10.7.5 上,如果这很重要的话),我不得不更改一行:他的脚本的参数似乎initKeyboardEventMDN 的顺序不同initKeyboardEvent 的文档

更改后的行如下所示:

oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, k, k, "", "", false, "");

好吧,上述解决方案确实有效,还要感谢@dland 提供参数提示。如果您无法在正确的位置触发事件,我发现这里有一些有用的东西。

@Orwellophile 的脚本在文档上触发事件。事件侦听器可能并不总是在 上注册document我将最后一行更改为以下内容,现在几乎每次都有效。

document.activeElement.dispatchEvent(oEvent);

document.activeElement始终激发了用户目前的重点是在元素上的事件。

我认为你错过了 SO 的重点。如果您有任何建议,请将其放在答案的评论中。如果您有更改,请修改代码。如果您没有执行这些操作的权限,那么您绝对不应该将您的经验和单行更改发布为“答案”。现在,您说的很可能是正确的,但是这段代码自 2012 年(大约 5 年前)以来一直在线并被大量引用。从使用它并对其发表评论的人数来看,我知道它有效。如果我现在做出这种边缘情况的改变,然后呢?
2021-04-01 03:56:52

上面的所有解决方案都有效,但我发现了一个他们不会的情况。

如果正在使用 Dart,则使用 KeyboardEvents 的 Dart 代码将不适用于一般事件。

你会得到类似 get$keyCode 未定义的信息。

在为此敲了几个小时后,我发现了以下技巧:

function __triggerKeyboardEvent(el, keyCode)
{
   var eventObj = document.createEventObject ?
       document.createEventObject() : document.createEvent("Events");

   var tempKeyboardObj = document.createEvent("KeyboardEvents");

   if(eventObj.initEvent){
      eventObj.initEvent("keydown", true, true);
   }
   eventObj.___dart_dispatch_record_ZxYxX_0_ = tempKeyboardObj.___dart_dispatch_record_ZxYxX_0_
   eventObj.keyCode = keyCode;
   eventObj.which = keyCode;

   el.dispatchEvent ? el.dispatchEvent(eventObj) : el.fireEvent("onkeydown", eventObj);

} 

愚弄 Dart 拦截器认为我们的事件实际上是一个 KeyboardEvent,成功了。

把它留在这里,对于试图在基于 webkit 的浏览器上测试 Dart 应用程序的可怜人。