2009-12-13 12 views
24

Sto provando a generare un evento tastiera su una pagina utilizzando javascript su Chrome. ho avuto un approccio che consente di lavorare su Firefox:Attivazione di un evento tastiera su 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); 
} 

dove la chiave è la chiave desiderata e keyCode cambia le lettere minuscole in highercase e chiede anche charCodeAt().

Il mio problema è che gli eventi su Safari/Chrome non hanno initKeyEvent, ma initKeyboardEvent. La principale differenza che ho notato è che devi passare la chiave come keyIdentifier (che sembra un carattere unicode) invece di passare il keycode e il keychar. Tuttavia, non riesco ancora a farlo funzionare.

Ho anche provato l'approccio JQuery descritto here senza successo.

EDIT: Ho il debug di questo un po 'oltre e sembra che l'evento su Chrome non innescare gli ascoltatori, ma keyCode/charCode è sempre 0. Ho cercato di impostare evt.keyCode o evt.charCode con nessun successo neanche.

+1

ho rimosso un commento dalla questione e mettere come risposta, perché penso che anche pensato che non risolve veramente il problema, potrebbe essere molto utile per le persone che hanno lo stesso problema come ho fatto io. – fserb

+0

Ehi, come hai risolto il problema? Sto anche affrontando il problema di simulare la pressione dei tasti di sinistra e destra su chrome/safari. Ma nessun successo, come hai fatto? – MaX

+0

Hai provato la soluzione che ho postato? Ha funzionato per me e probabilmente ti avrebbe aiutato a raggiungere il tuo obiettivo, quindi è strano per me che tu abbia accettato la tua risposta di "è un bug". – Dennis

risposta

5

Voglio solo lanciare questo frammento di base là fuori. Funziona in Chrome e si basa sulla modifica citata da Paul Irish.
Utilizza charCode anziché keyCode (che può essere utile in determinate situazioni), ma si adatta a keyCode se lo si desidera.

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

non è initKeyboardEvent? – SuperUberDuper

19

Ho rintracciato questo in uno bug on Webkit dove gli eventi creati contengono solo KeyIdentifier ma nessun codice chiave/codiceCode come si può vedere sullo browser source code. Sembra che ci sia una patch in corso per risolvere questo problema. Quindi immagino che questa non sia più una domanda corretta ...

+1

Ricorda di accettare la tua risposta quando puoi – Graviton

+1

Le persone hanno segnalato il successo con questo bellissimo trucco qui: http://stackoverflow.com/a/10520017/89484 –

+9

Se qualcuno nei progetti Chromium o Webkit non ha risolto questo errore adesso? (Sono passati quasi 5 anni ...) –

2

A seconda delle esigenze, un oggetto TextEvent potrebbe funzionare. (Ha funzionato per me per le mie esigenze -. Per Chrome Questo non è cross-browser testati, ma poi, la domanda era specificamente su 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); 
+0

Sebbene ciò inneschi l'evento, in realtà non inserisce il testo. "Funzionalità" di sicurezza in Chrome 61? - prova questo, non funziona https://gist.github.com/flying19880517/3180456 – mhenry1384

11

Se si vuole farlo nel modo giusto, si può utilizzare DOM Keyboard Event Level 4 KeyboardEvent construct e chiave proprietà.

In browser più recenti o con DOM Keyboard Event Level 3/4 polyfill si può fare qualcosa di simile:

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

Nota che keyCode e charCode sono obsoleti in ultima Spec (www .w3.org/TR/DOM-Level-3-Events /). Pertanto, Chrome non ha alcuna possibilità di implementare initKeyEvent con il supporto keyCode. Ma si può sempre ignorare questo valore: UPDATE: cattivo metodo:

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

Oppure si può aggiornamento prototipo evento: UPDATE: cattivo metodo:

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

Aggiornamento Esistono varie implementazioni di initKeyboardEvent.Nel mio polyfill KeyboardEvent rilevo in qualche modo simile a questo (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

Nessuno dei tuoi suggerimenti ha funzionato. Il primo fallisce perché la proprietà 'keyCode' non è configurabile. Il secondo perché il descrittore della proprietà 'get' non viene mai effettivamente chiamato. – John

+0

"Il primo non riesce perché la proprietà keyCode non è configurabile." Sto aggiornando il mio polyfill per correggere vari bug e compatibilità con il browser – termi

2

È possibile aggirare il bug Webkit utilizzando createEvent('Event') piuttosto che createEvent('KeyboardEvent'), e assegnando la proprietà keyCode. Vedi this answer e this example.

+4

C'è una differenza tra i due. Se si utilizza createEvent ("Eventi") in WebKit e si invia un evento con keyCode 13 a un elemento del modulo, in realtà non imita la chiave di ritorno. Se c'è un ascoltatore che ascolta keyCode 13, lo farà scattare, ma paragonato a Firefox in cui effettivamente imita la pressione del tasto Invio sulla tastiera e invia il modulo. Ho avuto a che fare solo con questo problema per un giorno o giù di lì e ho pensato di condividere. :) – jxpx777

Problemi correlati