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

kyxcudwk  于 2023-05-11  发布在  Go
关注(0)|答案(6)|浏览(155)

我想模拟keydown事件在一个给定的textarea元素的html页面。因为我使用的是Chrome,所以我在变量上调用了initKeyboardEvent,并将我想输入的keyCode传递到文本区域。以下是我尝试的:

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

在这段代码中,我输入了字母m,但是文本区域只得到了keyCode 13,这是回车键。因此,我尝试了一个我在网上看到的重写代码,将值设置为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值?

kmpatx3s

kmpatx3s1#

非常非常接近。。
你只需要覆盖“which”属性。下面是一些示例代码:

document.addEventListener('keydown', e => console.log(
'altKey                : ' + e.altKey + '\n' +
'charCode (Deprecated) : ' + e.charCode + '\n' +
'code                  : ' + e.code + '\n' +
'ctrlKey               : ' + e.ctrlKey + '\n' +
'isComposing           : ' + e.isComposing + '\n' +
'key                   : ' + e.key + '\n' +
'keyCode (Deprecated)  : ' + e.keyCode + '\n' +
'location              : ' + e.location + '\n' +
'metaKey               : ' + e.metaKey + '\n' +
'repeat                : ' + e.repeat + '\n' +
'shiftKey              : ' + e.shiftKey + '\n' +
'which (Deprecated)    : ' + e.which + '\n' +
'isTrusted             : ' + e.isTrusted + '\n' +
'type                  : ' + e.type
));

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);
}

//Sample usage
Podium.keydown(65);

注意:此代码不适用于IE、Safari或其他浏览器。也许是Firefox。YMMV。

oalqel3c

oalqel3c2#

Orwellophile的解决方案确实有效。

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

下面我写了一个cross-browser initKeyboardEvent function(gist):
示例:

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

下面是我的DOM Keyboard Event Level 3 polyfill和跨浏览器的KeyboardEvent构造函数。
示例:

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

Example 2
Example 3
重要提示1:charCode、keyCode以及哪些属性已弃用。所以我的crossBrowser_initKeyboardEvent no KeyboardEvent构造函数在某些浏览器中不能绝对保证该属性的正确值。您可以使用属性“key”和“char”代替或编辑我的gist强制使用initEvent在浏览器中只读charCode,keyCode和which属性。
重要提示2:keypress事件是不推荐的,现在不支持在我的Keyboard Event Level 3 polyfill。这意味着按键事件中的key和char属性可以具有随机值。我正在努力解决向后兼容性的问题。

yk9xbfzb

yk9xbfzb3#

为了让@Orwellophile的脚本在Google Chrome 26.0.1410.65上工作(在Mac OS X 10.7.5上,如果这很重要的话),我必须更改一行:他的脚本中initKeyboardEvent的参数顺序似乎与initKeyboardEvent的MDN文档中的顺序不同。
更改后的行如下所示:

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

gcxthw6b4#

好吧,上述解决方案确实有效,也要感谢@dland的参数提示。如果你不能让事件在正确的地方触发,我发现这里有一些有用的东西。
@Orwellophile的脚本在document上触发事件。事件侦听器可能并不总是在document上注册。我把最后一行改成了following,现在每次都能用了。
document.activeElement.dispatchEvent(oEvent);
document.activeElement总是在用户当前关注的元素上触发事件。

gr8qqesn

gr8qqesn5#

上面所有的解决方案都有效,但我发现有一种情况是行不通的。
如果正在使用Dart,则使用KeyboardEvents的Dart代码将无法在常规Event上工作。
你会得到类似get$keyCode is undefined的结果。
在我绞尽脑汁想了几个小时之后,我发现了下面的窍门:

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应用程序的可怜的家伙。

disbfnqx

disbfnqx6#

我还没有设法让它为我工作,但我发现为什么在这个线程,显然是不再允许的安全原因,一些事件是不可靠的
JavaScript trigger an InputEvent.isTrusted = true

相关问题