Activando un evento de teclado en Safari, usando JavaScript

79

Estoy intentando simular un evento de teclado en Safari usando JavaScript.

He intentado esto:

var event = document.createEvent("KeyboardEvent");
event.initKeyboardEvent("keypress", true, true, null, false, false, false, false, 115, 0);

... y también esto:

var event = document.createEvent("UIEvents");
event.initUIEvent("keypress", true, true, window, 1);
event.keyCode = 115;

Sin embargo, después de probar ambos enfoques, tengo el mismo problema: después de ejecutar el código, las propiedades keyCode/ whichdel objeto de evento se establecen en 0, no 115.

¿Alguien sabe cómo crear y enviar de manera confiable un evento de teclado en Safari? (Preferiría lograrlo en JavaScript simple si es posible).

Steve Harrison
fuente
¿Está intentando ejecutar el código que ha definido o alguna combinación de teclas que el navegador comprenda? Si es su propio código, lo mejor sería configurar un contenedor de eventos al que pueda llamar mediante una interfaz de teclado "real" o mediante algún otro generador de eventos, como ha descrito aquí. Refactorización según corresponda.
Nolte
1
En este ejemplo, estoy intentando simular que el usuario presiona "s". En última instancia, estoy tratando de simular que el usuario presiona Comando-R en un widget de tablero de Apple.
Steve Harrison
2
Su código resolvió mi problema :)
@ acidzombie24: ¡Es un placer! :)
Steve Harrison
4
Duplicado de Simular eventos clave de JavaScript
Dan Dascalescu

Respuestas:

43

Estoy trabajando en DOM Keyboard Event Level 3 polyfill . En los últimos navegadores o con este polyfill, puede hacer algo como esto:

element.addEventListener("keydown", 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})

ACTUALIZAR:

Ahora mi polyfill admite propiedades heredadas "keyCode", "charCode" y "which"

var e = new KeyboardEvent("keydown", {
    bubbles : true,
    cancelable : true,
    char : "Q",
    key : "q",
    shiftKey : true,
    keyCode : 81
});

Ejemplos aquí

Además, aquí está initKeyboardEvent entre navegadores por separado de mi polyfill: (gist)

Demostración de Polyfill

termi
fuente
No parece funcionar para hacer que un área desplazable se desplace hacia abajo usando las teclas de flecha o de página arriba / abajo ...
Michael
Cambió su jsfiddle para enviar el evento en el cuadro de texto en lugar del documento @ jsfiddle.net/vnathalye/yjc5F/974 . Aunque activa el controlador de pulsaciones de teclas, el texto no se muestra en el cuadro de texto. ¿Alguna idea?
Vivek Athalye
1
@termi Su enlace de demostración está muerto
Sebastian
Tampoco parece funcionar para cambiar el valor de un elemento de entrada (texto).
Michael
El operando de un operador de eliminación no puede ser una propiedad de solo lectura.
nircraft
30

¿Enviaste el evento correctamente?

function simulateKeyEvent(character) {
  var evt = document.createEvent("KeyboardEvent");
  (evt.initKeyEvent || evt.initKeyboardEvent)("keypress", true, true, window,
                    0, 0, 0, 0,
                    0, character.charCodeAt(0)) 
  var canceled = !body.dispatchEvent(evt);
  if(canceled) {
    // A handler called preventDefault
    alert("canceled");
  } else {
    // None of the handlers called preventDefault
    alert("not canceled");
  }
}

Si usa jQuery, podría hacer:

function simulateKeyPress(character) {
  jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}
tyronegcarter
fuente
3
¿Es posible simular control + C (copiar atajo) con esto?
John John Pichler
1
@claudiopro Sí, tienes razón, debería ser(evt.initKeyEvent || evt.initKeyboardEvent).call(evt, // etc.
tyronegcarter
12
InitKeyboardEvent tampoco funciona en Chromium. event.keyCodey event.whichsiempre devuelve 0. Es un error conocido y la solución es usar un evento regularvar event = document.createEvent('Event'); event.initEvent('keydown', true, true); event.keyCode = 76;
lluft
5
Downvoted : initKeyEventy initKeyboardEventestán DESAPARECIDOS .
Константин Ван
2
@ K._ en lugar de votar negativamente por una respuesta que funcionaba anteriormente, afirmar que está obsoleto debería ser suficiente para avisar a todos sin afectar negativamente a tyronegcarter. Esta respuesta stackoverflow.com/questions/961532/… utiliza el moderno KeyboardEvent developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/…
bit-less
17

Esto se debe a un error en Webkit.

Puede solucionar el error de Webkit usando en createEvent('Event')lugar de createEvent('KeyboardEvent'), y luego asignando la keyCodepropiedad. Vea esta respuesta y este ejemplo .

John
fuente
8

La red de desarrolladores de Mozilla ofrece la siguiente explicación:

  1. Crea un evento usando event = document.createEvent("KeyboardEvent")
  2. Iniciar el evento clave

utilizando:

event.initKeyEvent (type, bubbles, cancelable, viewArg, 
       ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, 
           keyCodeArg, charCodeArg)
  1. Envíe el evento usandoyourElement.dispatchEvent(event)

No veo el último en tu código, tal vez eso es lo que te estás perdiendo. Espero que esto también funcione en IE ...

Javache
fuente
2
Desafortunadamente, la implementación de Mozilla no es estándar. En cuanto al punto 3, mi problema es crear el evento correcto; el envío del evento viene después de esto. Además, como estoy desarrollando para el Dashboard de Apple, ¡no tengo que preocuparme por IE en absoluto! (Whoopee!)
Steve Harrison
5
.initKeyEventahora está obsoleto
Hampus Ahlgren
1

No soy muy bueno con esto pero KeyboardEvent=> ver que KeyboardEvent se inicializa con initKeyEvent.
Aquí hay un ejemplo para emitir un evento en un <input type="text" />elemento.

document.getElementById("txbox").addEventListener("keypress", function(e) {
  alert("Event " + e.type + " emitted!\nKey / Char Code: " + e.keyCode + " / " + e.charCode);
}, false);

document.getElementById("btn").addEventListener("click", function(e) {
  var doc = document.getElementById("txbox");
  var kEvent = document.createEvent("KeyboardEvent");
  kEvent.initKeyEvent("keypress", true, true, null, false, false, false, false, 74, 74);
  doc.dispatchEvent(kEvent);
}, false);
<input id="txbox" type="text" value="" />
<input id="btn" type="button" value="CLICK TO EMIT KEYPRESS ON TEXTBOX" />

vutar
fuente
7
se muestra js:21TypeError: kEvent.initKeyEvent is not a function. (In 'kEvent.initKeyEvent("keypress", true, true, null, false, false, false, false, 74, 74)', 'kEvent.initKeyEvent' is undefined)en safari :(
He Yifei 何 一 非
Debe ser: var kEvent = document.createEvent ("KeyboardEvent"); kEvent.initKeyboardEvent ("pulsación de tecla", verdadero, verdadero, nulo, falso, falso, falso, falso, 74, 74); document.dispatchEvent (kEvent);
Любопытный