代码之家  ›  专栏  ›  技术社区  ›  orip

在Chrome上触发键盘事件

  •  26
  • orip  · 技术社区  · 15 年前

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

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

    其中key是所需的键,keycode将小写字母更改为highercase,并调用charcodeat()。

    我的问题是Safari/Chrome上的事件没有initkeyEvent,而是initkeyBoardEvent。我能注意到的主要区别是,您必须将密钥作为keyIdentifier(看起来像Unicode字符)传递,而不是传递keycode和keychar。尽管如此,我仍然无法让它发挥作用。

    我还尝试了描述的jquery方法 here 没有成功。

    编辑: 我对此进行了进一步的调试,似乎chrome上的事件确实触发了侦听器,但keycode/charcode始终为0。我试图设置evt.keycode或evt.charcode,但也没有成功。

    5 回复  |  直到 11 年前
        1
  •  5
  •   Protector one reece    11 年前

    我只想把这个基本的片段扔出去。它在Chrome中工作,基于PaulIrish提到的黑客。
    它使用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);
    
        2
  •  19
  •   orip    15 年前

    我已经查到了 bug on Webkit 其中创建的事件只包含keyIdentifier,但没有在 browser source code . 似乎有一个补丁正在解决这个问题。所以我想这不再是一个合适的问题了…

        3
  •  11
  •   termi    12 年前

    如果您想以正确的方式进行,可以使用dom 键盘事件级别4 键盘通风口结构和 钥匙 财产。

    在最新浏览器中或 DOM Keyboard Event Level 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

    注意 密钥代码 字符码 在最新规范(www.w3.org/tr/dom-level-3-events/)中已弃用。所以没有机会实现chrome 关键事件 具有 密钥代码 支持。但始终可以覆盖此值: 更新 坏方法:

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

    或者你可以 更新 事件原型: 更新 坏方法:

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

    更新 initKeyboardEvent有多种实现。在我的键盘上的Polyfill里,我发现它是这样的。( gist ):

    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 );
            }
        }
    }
    
        4
  •  2
  •   Dennis    13 年前

    根据您的需要,TextEvent可能有效。(它为我的需要——为铬而工作。这不是跨浏览器测试,但问题是关于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);
    
        5
  •  2
  •   Community CDub    8 年前

    您可以使用 createEvent('Event') 而不是 createEvent('KeyboardEvent') ,然后分配 keyCode 财产。见 this answer this example .