Javascript 在 Chrome 上触发键盘事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1897333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:48:14  来源:igfitidea点击:

Firing a keyboard event on Chrome

javascriptgoogle-chromewebkit

提问by fserb

I'm trying to fire a keyboard event to a page using javascript on Chrome. I had an approach that used to work on Firefox:

我正在尝试在 Chrome 上使用 javascript 向页面触发键盘事件。我有一种曾经在 Firefox 上工作的方法:

pressKey = function(key, shift) {
  var evt = document.createEvent('KeyboardEvent');
  evt.initKeyEvent("keypress", false, true, null, false, false,
                   shift, false, keyCode(key), key.charCodeAt(0));
  document.dispatchEvent(evt);
}

where key is the desired key and keyCode changes lowercase letters into highercase and also calls charCodeAt().

其中 key 是所需的键,keyCode 将小写字母更改为大写字母并调用 charCodeAt()。

My problem is that events on Safari/Chrome don't have initKeyEvent, but initKeyboardEvent. The main difference I could notice was that you have to pass the key as a keyIdentifier (which looks like a unicode character) instead of passing the keycode and the keychar. Nonetheless I still can't manage to make it work.

我的问题是 Safari/Chrome 上的事件没有 initKeyEvent,而是 initKeyboardEvent。我注意到的主要区别是您必须将密钥作为 keyIdentifier(看起来像 unicode 字符)传递,而不是传递 keycode 和 keychar。尽管如此,我仍然无法使其工作。

I've also tried the JQuery approach described herewithout success.

我也尝试过这里描述的 JQuery 方法但没有成功。

EDIT:I debugged this a little further and it seems that the event on Chrome does trigger the listeners, but keyCode/charCode is always 0. I've tried to set evt.keyCode or evt.charCode with no success either.

编辑:我进一步调试了这一点,似乎 Chrome 上的事件确实触发了侦听器,但 keyCode/charCode 始终为 0。我尝试设置 evt.keyCode 或 evt.charCode 也没有成功。

采纳答案by Protector one

I just want to throw this basic snippet out there. It works in Chrome and is based on the hack mentioned by Paul Irish.
It uses charCode instead of keyCode (which can be useful in certain situation), but adapt to keyCode if you so please.

我只想把这个基本的片段放在那里。它在 Chrome 中工作,并且基于 Paul Irish 提到的 hack。
它使用 charCode 而不是 keyCode(这在某些情况下很有用),但如果您愿意,可以适应 keyCode。

var keyboardEvent = new KeyboardEvent('keypress', {bubbles:true}); 
Object.defineProperty(keyboardEvent, 'charCode', {get:function(){return this.charCodeVal;}}); 
keyboardEvent.charCodeVal = [your char code];
document.body.dispatchEvent(keyboardEvent);

回答by fserb

I've tracked this down to a bug on Webkitwhere created events only contain KeyIdentifier but no keyCode/charCode as can be seen on the browser source code. There seems to be a patch going on to solve this. So I guess this is not a proper question anymore...

我已经将此追溯到Webkit上的一个错误,其中创建的事件仅包含 KeyIdentifier,但没有在浏览器源代码上看到的 keyCode/charCode 。似乎有一个补丁正在解决这个问题。所以我想这不再是一个合适的问题了......

回答by termi

If you want do it in the right way, you can use DOM Keyboard Event Level 4KeyboardEvent construct and keyproperty.

如果您想以正确的方式进行操作,您可以使用 DOM键盘事件级别 4KeyboardEvent 构造和属性。

In latest browsers or with DOM Keyboard Event Level 3/4 polyfillyou can do something like this:

在最新的浏览器或DOM 键盘事件级别 3/4 polyfill 中,您可以执行以下操作:

element.addEventListener(function(e){ console.log(e.key, e.char, e.keyCode) })

var e = new KeyboardEvent("keydown", {bubbles : true, cancelable : true, key : "Q", char : "Q", shiftKey : true});
element.dispatchEvent(e);

//If you need legacy property "keyCode".
// Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari)
delete e.keyCode;
Object.defineProperty(e, "keyCode", {"value" : 666})

Example

例子

"map event.key to character values of a normal QUERTY (en-US) layout" proposal demo

“将 event.key 映射到普通 QUERTY (en-US) 布局的字符值”提案演示

Note that keyCodeand charCodeare deprecated in latest Spec (www.w3.org/TR/DOM-Level-3-Events/). So the is no chance to Chrome to implement initKeyEventwith keyCodesupport. But you can always override this value: UPDATE: bad method:

请注意,最新的规范 (www.w3.org/TR/DOM-Level-3-Events/) 中不推荐使用keyCodecharCode。所以 Chrome 没有机会通过keyCode支持来实现initKeyEvent。但是你总是可以覆盖这个值: UPDATE: bad method:

var evt = document.createEvent('KeyboardEvent');
evt.initKeyEvent("keypress", false, true, null, false, false,
               shift, false, keyCode(key), key.charCodeAt(0));
if(evt.keyCode != keyCode(key)) {
    delete evt.keyCode;
    // Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari)
    Object.defineProperty(evt, "keyCode", { keyCode(key) });
}

Or you can updateevent prototype: UPDATE: bad method:

或者你可以更新事件原型:UPDATE: bad method:

// Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari)
var _native_keyCode_getter = Object.getOwnPropertyDescriptor(KeyboardEvent.prototype, "keyCode");
Object.defineProperty(KeyboardEvent.prototype, "keyCode", {
    "enumerable" : true,
    "configurable" : true,
    "get" : function() {
        if("__keyCode" in this)return this["__keyCode"];

        return _native_keyCode_getter.call(this);
    },
    "set" : function(newValue) {
        return this["__keyCode"] = isNaN(newValue) ? 0 : newValue;
    }
});    

UpdateThere are various implementation of initKeyboardEvent. In my KeyboardEvent polyfill I detect it somehow like this (gist):

更新initKeyboardEvent 有多种实现。在我的 KeyboardEvent polyfill 中,我以某种方式检测到它(要点):

var _initKeyboardEvent_type = (function( e ) {
    try {
        e.initKeyboardEvent(
            "keyup" // in DOMString typeArg
            , false // in boolean canBubbleArg
            , false // in boolean cancelableArg
            , global // in views::AbstractView viewArg
            , "+" // [test]in DOMString keyIdentifierArg | webkit event.keyIdentifier | IE9 event.key
            , 3 // [test]in unsigned long keyLocationArg | webkit event.keyIdentifier | IE9 event.location
            , true // [test]in boolean ctrlKeyArg | webkit event.shiftKey | old webkit event.ctrlKey | IE9 event.modifiersList
            , false // [test]shift | alt
            , true // [test]shift | alt
            , false // meta
            , false // altGraphKey
        );
        return ((e["keyIdentifier"] || e["key"]) == "+" && (e["keyLocation"] || e["location"]) == 3) && (
            e.ctrlKey ?
                e.altKey ? // webkit
                    1
                    :
                    3
                :
                e.shiftKey ?
                    2 // webkit
                    :
                    4 // IE9
            ) || 9 // FireFox|w3c
            ;
    }
    catch ( __e__ ) { alert("browser do not support KeyboardEvent") }
})( document.createEvent( "KeyboardEvent" ) );

var e = document.createEvent( "KeyboardEvent" );
...
if( "initKeyEvent" in e ) {//FF
    //https://developer.mozilla.org/en/DOM/event.initKeyEvent
    e.initKeyEvent( type, _bubbles, _cancelable, _view, _ctrlKey, _altKey, _shiftKey, _metaKey, _keyCode, _keyCode );
}
else if( "initKeyboardEvent" in e ) {//https://developer.mozilla.org/en/DOM/KeyboardEvent#initKeyboardEvent()
    if( _try_initKeyboardEvent ) {
        if( _initKeyboardEvent_type == 1 ) { // webkit
            //http://stackoverflow.com/a/8490774/1437207
            //https://bugs.webkit.org/show_bug.cgi?id=13368
            e.initKeyboardEvent( type, _bubbles, _cancelable, _view, _key, _location, _ctrlKey, _shiftKey, _altKey, _metaKey, _altGraphKey );
        }
        else if( _initKeyboardEvent_type == 2 ) { // old webkit
            //http://code.google.com/p/chromium/issues/detail?id=52408
            e.initKeyboardEvent( type, _bubbles, _cancelable, _view, _ctrlKey, _altKey, _shiftKey, _metaKey, _keyCode, _keyCode );
        }
        else if( _initKeyboardEvent_type == 3 ) { // webkit
            e.initKeyboardEvent( type, _bubbles, _cancelable, _view, _key, _location, _ctrlKey, _altKey, _shiftKey, _metaKey, _altGraphKey );
        }
        else if( _initKeyboardEvent_type == 4 ) { // IE9
            //http://msdn.microsoft.com/en-us/library/ie/ff975297(v=vs.85).aspx
            e.initKeyboardEvent( type, _bubbles, _cancelable, _view, _key, _location, _modifiersListArg, _repeat, _locale );
        }
        else { // FireFox|w3c
            //http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent-initKeyboardEvent
            //https://developer.mozilla.org/en/DOM/KeyboardEvent#initKeyboardEvent()
            e.initKeyboardEvent( type, _bubbles, _cancelable, _view, _char, _key, _location, _modifiersListArg, _repeat, _locale );
        }
    }
}

回答by John

You can work around the Webkit bug using createEvent('Event')rather than createEvent('KeyboardEvent'), and then assigning the keyCodeproperty. See this answerand this example.

您可以使用createEvent('Event')而不是createEvent('KeyboardEvent'),然后分配keyCode属性来解决 Webkit 错误。请参阅此答案此示例

回答by Dennis

Depending on your needs, a TextEvent might work. (It worked for me for my needs - for chrome. This is not cross-browser tested, but then, the question was specifically about chrome.)

根据您的需要,TextEvent 可能会起作用。(它对我的需求有用 - 对于 chrome。这不是跨浏览器测试的,但是,问题是专门关于 chrome 的。)

// get a reference to the DOM element you want to affect
var input = document.getElementsByTagName('input')[0];
// create a TextEvent
var textEvent = document.createEvent('TextEvent');
// initialize the TextEvent
textEvent.initTextEvent('textInput', true, true, null, String.fromCharCode(13)+"\r\n", 9, "en-US");
// dispatch ('fire') the TextEvent
input.dispatchEvent(textEvent);