28

我想模拟keydownhtml 页面中给定 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值?

4

6 回答 6

79

所以非常非常接近...

您只需要覆盖“哪个”属性。这是一些示例代码:

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

Note: this code is not designed to work in IE, Safari, or other browsers. Well, maybe with Firefox. YMMV.

于 2012-05-09T16:15:23.967 回答
14

Orwellophile's solution does work.

  • First: 'keyCode', 'charCode' and 'which' is readonly in Safari and IE9+ (at least).
  • Second: initKeyboardEvent is kind of messy. All browsers implement it in a different way. Even in webkit's there are several different implementation of initKeyboardEvent. And there is no "good" way to initKeyboardEvent in Opera.
  • Third: initKeyboardEvent is deprecated. You need to use initKeyEvent or KeyboardEvent constructor.

Here I wrote a cross-browser initKeyboardEvent function (gist):

Example:

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

And here is my DOM Keyboard Event Level 3 polyfill with cross-browser KeyboardEvent constructor.

Example:

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

Example 2

Example 3

Important Note 1: charCode, keyCode and which properties is deprecated. So neither my crossBrowser_initKeyboardEvent no KeyboardEvent constructor is absolutely guaranteed right values of that properties in some browsers. You can using properties "key" and "char" instead or edit my gist to force using initEvent in browsers with read-only charCode, keyCode and which properties.

Important Note 2: keypress event is deprecated and for now unsupported in my Keyboard Event Level 3 polyfill. That's mean that key and char properties in keypress event can have random values. I am working to fix that problem to backward compatibility.

于 2013-01-28T11:44:30.363 回答
4

In order to get @Orwellophile's script to work on Google Chrome 26.0.1410.65 (on Mac OS X 10.7.5, if that matters), I had to change one line: his script appears to have the paramaters of initKeyboardEvent in different order than the MDN documentation for initKeyboardEvent.

The changed line looks like this:

oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, k, k, "", "", false, "");
于 2013-04-15T18:55:26.830 回答
3

Well the above solutions did work, also thanks to @dland for the parameter tip. Here is something I found useful, if you are not able to get the events firing at the right place.

The @Orwellophile's script fires the event on document. It may be possible that the event listener is not always registered on document. I changed the last line to following and now it pretty much works every time.

document.activeElement.dispatchEvent(oEvent);

The document.activeElement always fires the event on the element where the user is currently focusing on.

于 2015-07-15T20:06:15.777 回答
0

All the solutions above are working, but I've found one case they won't.

If Dart is being used, Dart code that uses KeyboardEvents won't work on a general Event.

You'll get something like get$keyCode is undefined.

after banging my head for hours on this, I've found the following trick:

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

} 

Fooling Dart interceptor to thing our Event is actually a KeyboardEvent, did the trick.

Leaving it here, for the poor guy that is trying to test Dart app on a webkit based browser.

于 2014-11-25T18:36:16.743 回答
0

I have not managed to get it to work for me, but I found why in this thread, apparently it is no longer allowed for security reasons, some events are not reliable

JavaScript trigger an InputEvent.isTrusted = true

于 2021-02-16T21:48:48.297 回答