2009-12-13 11 views
24

Estoy intentando activar un evento de teclado en una página usando javascript en Chrome. que tenía un enfoque que utiliza para trabajar en Firefox:Disparar un evento de teclado en 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); 
} 

donde la clave es la clave deseada y keyCode cambia letras minúsculas en highercase y también llama charCodeAt().

Mi problema es que los eventos en Safari/Chrome no tienen initKeyEvent, pero initKeyboardEvent. La principal diferencia que pude notar fue que debe pasar la clave como keyIdentifier (que se parece a un carácter Unicode) en lugar de pasar el código clave y el keychar. Sin embargo, todavía no puedo lograr que funcione.

También probé el enfoque JQuery descrito here sin éxito.

EDIT: I depurado esto un poco más y parece que el evento se dispara en Chrome los oyentes, pero keyCode/charCode es siempre 0. He tratado de establecer evt.keyCode o con evt.charCode sin éxito tampoco.

+1

he quitado un comentario de la pregunta y puso como respuesta, porque creo que incluso pensó que en realidad no resuelve la cuestión, podría ser muy útil para las personas que tienen el mismo problema que yo. – fserb

+0

¿Cómo resolvió el problema? También estoy enfrentando el problema de simular la pulsación de teclas de izquierda y derecha en cromo/safari. Pero sin éxito, ¿cómo lo hiciste? – MaX

+0

¿Has probado la solución que publiqué? Me funcionó y probablemente te haya ayudado a lograr tu objetivo, por lo que es extraño para mí que hayas aceptado tu propia respuesta de "es un error". – Dennis

Respuesta

5

Solo quiero arrojar este fragmento básico por ahí. Funciona en Chrome y se basa en el hack mencionado por Paul Irish.
Utiliza charCode en lugar de keyCode (que puede ser útil en determinadas situaciones), pero se puede adaptar a keyCode si así lo desea.

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

¿no es initKeyboardEvent? – SuperUberDuper

19

He rastreado esto hasta bug on Webkit donde los eventos creados solo contienen KeyIdentifier pero no keyCode/charCode como se puede ver en browser source code. Parece que hay un parche para resolver esto. Así que supongo que ya no es una pregunta adecuada ...

+1

Recuerde aceptar su propia respuesta cuando pueda – Graviton

+1

La gente ha informado de éxito con este hermoso hack aquí: http://stackoverflow.com/a/10520017/89484 –

+9

No debería alguien en los proyectos de Chromium o Webkit ha solucionado este error por ¿ahora? (Han pasado casi 5 años ...) –

2

Dependiendo de sus necesidades, un TextEvent podría funcionar. (A mí me funcionó para mis necesidades -. De cromo Esto no es a prueba de cross-browser, pero entonces, la pregunta era específicamente sobre cromo.)

// 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

Aunque esto desencadena el evento, en realidad no inserta el texto. "Característica de seguridad" en Chrome 61? - Inténtalo, no funciona https://gist.github.com/flying19880517/3180456 – mhenry1384

11

Si desea hacerlo de la manera correcta, puede use DOM Keyboard Event Level KeyboardEvent construye y key propiedad.

En los navegadores más recientes o con DOM Keyboard Event Level 3/4 polyfill se puede hacer algo como esto:

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

Tenga en cuenta que keyCode y charCode están en desuso en la última Spec (www .w3.org/TR/DOM-Level-3-Events /). Por lo tanto, no es posible que Chrome implemente initKeyEvent con keyCode support. Pero siempre se puede reemplazar este valor: ACTUALIZACIÓN: mal método:

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

O puede actualización prototipo evento: ACTUALIZACIÓN: mal método:

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

actualización Hay varias implementaciones de initKeyboardEvent.En mi polyfill KeyboardEvent detecto alguna manera como esto (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

Ninguna de las soluciones alternativas sugeridas funciona. El primero falla porque la propiedad 'keyCode' no es configurable. El segundo porque el 'get' del descriptor de propiedad nunca se llama realmente. – John

+0

"El primero falla porque la propiedad keyCode no es configurable". Estoy actualizando mi polyfill para corregir varios errores y la compatibilidad del navegador – termi

2

Puede solucionar el error usando Webkit createEvent('Event') en lugar de createEvent('KeyboardEvent') y asignando a la propiedad keyCode. Ver this answer y this example.

+4

Hay una diferencia entre los dos. Si utiliza createEvent ("Events") en WebKit y envía un evento con keyCode 13 a un elemento de formulario, en realidad no imita la clave de devolución. Si hay un oyente que escucha el código 13, lo desencadenará, pero compare con Firefox donde imita la presión de la tecla de retorno en el teclado y envía el formulario. He estado lidiando con este problema por un día o así y pensé que lo compartiría. :) – jxpx777

Cuestiones relacionadas