2009-12-13 316 views
24

我想将键盘事件触发到在Chrome上使用JavaScript的页面。 我有这样的习惯在Firefox上运行的方法:在Chrome上触发键盘事件

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

,其中关键是需要的键和键改变小写字母为highercase还呼吁charCodeAt()。

我的问题是Safari/Chrome上的事件没有initKeyEvent,而是initKeyboardEvent。我可以注意到的主要区别是您必须将key作为keyIdentifier(它看起来像一个unicode字符)而不是传递keycode和keychar。尽管如此,我仍然无法做到这一点。

我也试过jQuery方法here没有成功。

编辑: 我调试这个远一点,似乎在Chrome的事件不触发听众,但键代码/ charCode为始终为0。我试图设置evt.keyCode或evt.charCode与也没有成功。

+1

我已经移除问题的意见,并把作为回答,因为我认为,甚至认为它并没有真正解决问题的,它可能是有同样的问题,像我一样的人真的很有帮助。 – fserb 2009-12-13 19:42:08

+0

嘿,你是怎么解决这个问题的?我也面临着模拟铬/ safari左右按键的问题。但没有成功,你是怎么做到的? – MaX 2013-01-15 00:50:16

+0

您是否尝试过我发布的解决方案?它对我有用,可能会帮助你实现你的目标,所以你接受你自己的“这是一个bug”的答案对我来说很奇怪。 – Dennis 2014-07-02 17:53:51

回答

5

我只想把这个基本片段放在那里。它在Chrome中运行,基于Paul Irish提到的黑客攻击。
它使用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); 
+0

是不是initKeyboardEvent? – SuperUberDuper 2017-04-01 14:33:52

19

我已经将其跟踪至bug on Webkit,其中创建的事件只包含KeyIdentifier,但没有keycode/charCode,如在browser source code上可以看到的。似乎有一个补丁正在解决这个问题。所以我想这不是一个适当的问题了...

+1

记住接受你自己的答案,当你可以 – Graviton 2009-12-14 12:20:49

+1

人们已经报道成功与这个美丽的黑客在这里:http://stackoverflow.com/a/10520017/89484 – 2013-12-11 23:41:29

+9

不应该有人在Chromium或Webkit项目已修复此错误现在? (已经差不多5年了...) – 2014-05-22 15:32:21

2

根据您的需要,TextEvent可能工作。 (它的工作对我来说我的需求 - 对铬这不是跨浏览器测试,但后来,这个问题是特别为约铬)

// 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); 
+0

虽然这会触发事件,但它并不实际插入文本。 Chrome 61中的安全“功能”? - 试试这个,它不起作用https://gist.github.com/flying19880517/3180456 – mhenry1384 2017-11-10 20:08:14

11

如果你想要做正确的方式,你可以使用DOM 键盘事件级别4 KeyboardEvent构造和属性。

在最新的浏览器或与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

注意键代码则charCode在最新规格(WWW已被弃用.w3.org/TR/DOM级别-3-活动/)。所以Chrome没有机会实现initKeyEventkeyCode的支持。但你总是可以覆盖该值: UPDATE:坏方法:

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

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

// 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有各种实现。在我的KeyboardEvent填充工具我发现它在某种程度上是这样的(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); 
     } 
    } 
} 
+1

你建议的解决方法都不起作用。第一个失败是因为'keyCode'属性是不可配置的。第二个是因为属性描述符的'get'从来没有被实际调用过。 – John 2013-01-22 21:38:26

+0

“第一个失败,因为keyCode属性不可配置。” 我正在更新我的polyfill来修复各种错误和浏览器兼容性 – termi 2013-01-26 20:55:46

2

您可以解决使用createEvent('Event'),而不是createEvent('KeyboardEvent')的Webkit的错误,然后分配keyCode财产。见this answerthis example

+4

这两者之间有一个区别。如果您在WebKit中使用createEvent(“Events”)并将具有keyCode 13的事件发送到表单元素,则它实际上并不模仿返回键。如果有监听器在监听keyCode 13,它会触发该监听器,但与Firefox相比,它实际上模仿按下键盘上的返回键并提交表单。一直在处理这个问题一天左右,并认为我会分享。 :) – jxpx777 2013-04-04 20:03:10