javascript - teclado - ¿Es posible simular eventos de pulsación de tecla programáticamente?
simular enter jquery (18)
¿Es posible simular eventos clave de prensa programáticamente en JavaScript?
Aquí hay una biblioteca que realmente ayuda: https://cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js
No sé de dónde vino, pero es útil. Agrega un método .simulate()
a window.KeyEvent
, así que lo usas simplemente con KeyEvent.simulate(0, 13)
para simular un enter
o KeyEvent.simulate(81, 81)
para una ''Q''
.
Lo obtuve en https://github.com/ccampbell/mousetrap/tree/master/tests .
Aquí hay una solución que funciona en Chrome y Chromium (solo he probado estas plataformas). Parece que Chrome tiene algunos errores o un enfoque propio para manejar códigos clave, por lo que esta propiedad debe agregarse por separado a KeyboardEvent.
function simulateKeydown (keycode,isCtrl,isAlt,isShift){
var e = new KeyboardEvent( "keydown", { bubbles:true, cancelable:true, char:String.fromCharCode(keycode), key:String.fromCharCode(keycode), shiftKey:isShift, ctrlKey:isCtrl, altKey:isAlt } );
Object.defineProperty(e, ''keyCode'', {get : function() { return this.keyCodeVal; } });
e.keyCodeVal = keycode;
document.dispatchEvent(e);
}
Debería usar algunos JS lib con soporte para envolver el Modelo de evento DOM. A partir de ahí, puedes disparar y probar tus manejadores.
En algunos casos, el evento de keypress
no puede proporcionar la funcionalidad requerida, en general, los eventos se combinan de los dos eventos que se keydown
y, a keydown
, la keyup
de keyup
para la misma tecla. Así que solo genera los eventos uno por uno:
element.dispatchEvent(new KeyboardEvent(''keydown'',{''key'':''Shift''}));
element.dispatchEvent(new KeyboardEvent(''keyup'',{''key'':''Shift''}));
Este enfoque es compatible con el navegador cruzado cambiando el valor del código clave . Source
var $textBox = $("#myTextBox");
var press = jQuery.Event("keypress");
press.altGraphKey = false;
press.altKey = false;
press.bubbles = true;
press.cancelBubble = false;
press.cancelable = true;
press.charCode = 13;
press.clipboardData = undefined;
press.ctrlKey = false;
press.currentTarget = $textBox[0];
press.defaultPrevented = false;
press.detail = 0;
press.eventPhase = 2;
press.keyCode = 13;
press.keyIdentifier = "";
press.keyLocation = 0;
press.layerX = 0;
press.layerY = 0;
press.metaKey = false;
press.pageX = 0;
press.pageY = 0;
press.returnValue = true;
press.shiftKey = false;
press.srcElement = $textBox[0];
press.target = $textBox[0];
press.type = "keypress";
press.view = Window;
press.which = 13;
$textBox.trigger(press);
Esto es lo que logré encontrar:
function createKeyboardEvent(name, key, altKey, ctrlKey, shiftKey, metaKey, bubbles) {
var e = new Event(name)
e.key = key
e.keyCode = e.key.charCodeAt(0)
e.which = e.keyCode
e.altKey = altKey
e.ctrlKey = ctrlKey
e.shiftKey = shiftKey
e.metaKey = metaKey
e.bubbles = bubbles
return e
}
var name = ''keydown''
var key = ''a''
var event = createKeyboardEvent(name, key, false, false, false, false, true)
document.addEventListener(name, () => {})
document.dispatchEvent(event)
Esto funcionó para mí y simula un keyup para mi textaera. si lo desea para toda la página, simplemente coloque el KeySimulation()
en <body>
esta manera <body onmousemove="KeySimulation()">
o si no está onmousemove
, onmouseover
o onload
funciona también.
<script>
function KeySimulation()
{
var e = document.createEvent("KeyboardEvent");
if (e.initKeyboardEvent) { // Chrome, IE
e.initKeyboardEvent("keyup", true, true, document.defaultView, "Enter", 0, "", false, "");
} else { // FireFox
e.initKeyEvent("keyup", true, true, document.defaultView, false, false, false, false, 13, 0);
}
document.getElementById("MyTextArea").dispatchEvent(e);
}
</script>
<input type="button" onclick="KeySimulation();" value=" Key Simulation " />
<textarea id="MyTextArea" rows="15" cols="30"></textarea>
Lo que puede hacer es activar programáticamente oyentes de eventos clave disparando eventos clave . Tiene sentido permitir esto desde una perspectiva de seguridad de espacio aislado. Usando esta habilidad, puedes aplicar un observer-pattern típico de observer-pattern . Podrías llamar a este método "simulando".
A continuación se muestra un ejemplo de cómo lograr esto en el estándar W3C DOM junto con jQuery:
function triggerClick() {
var event = new MouseEvent(''click'', {
''view'': window,
''bubbles'': true,
''cancelable'': true
});
var cb = document.querySelector(''input[type=submit][name=btnK]'');
var canceled = !cb.dispatchEvent(event);
if (canceled) {
// preventDefault was called and the event cancelled
} else {
// insert your event-logic here...
}
}
Este ejemplo está adaptado de: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
En jQuery:
jQuery(''input[type=submit][name=btnK]'')
.trigger({
type: ''keypress'',
which: character.charCodeAt(0 /*the key to trigger*/)
});
Pero recientemente, no hay una forma [DOM] de activar realmente eventos clave que salgan de la caja de arena del navegador. Y todos los principales proveedores de navegadores se adherirán a ese concepto de seguridad.
En cuanto a los complementos como Adobe Flash, que se basan en el NPAPI, y permiten omitir el sandbox: se están phasing-out ; Firefox .
Explicación detallada:
No puede y no debe hacerlo por razones de seguridad (como ya señaló Pekka). Siempre requerirá una interacción del usuario en el medio. Además, imagine la posibilidad de que los proveedores de navegadores sean demandados por los usuarios, ya que varios eventos programáticos del teclado habrán provocado ataques de suplantación de identidad.
Vea esta post para alternativas y más detalles. Siempre existe el flash basado en copiar y pegar. Aquí hay un example elegante. Al mismo tiempo, es un testimonio de por qué la web se está alejando de los proveedores de complementos.
Existe una mentalidad de seguridad similar aplicada en el caso de la política CORS opt-in para acceder al contenido remoto mediante programación.
La respuesta es:
No hay forma de activar mediante programación las claves de entrada en el entorno del navegador de espacio aislado en circunstancias normales .
Línea de base: no estoy diciendo que no será posible en el futuro, bajo modos especiales de navegador y / o privilegios hacia el objetivo final de los juegos, o experiencias de usuario similares. Sin embargo, antes de ingresar a dichos modos, se le solicitará al usuario permisos y riesgos, de manera similar al modelo de API de pantalla completa .
Útil: en el contexto de KeyCodes, this herramienta y la asignación de códigos de clave serán útiles.
Revelación: La respuesta se basa en la respuesta here .
Para aquellos interesados, puede recrear eventos de entrada de teclado de manera confiable. Para cambiar el texto en el área de entrada (mover los cursores o la página a través de un carácter de entrada), debe seguir de cerca el modelo de evento DOM: http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents
El modelo debe hacer:
- foco (enviado en el DOM con el conjunto de objetivos)
Luego para cada personaje:
- keydown (enviado en el DOM)
- antes de la entrada (se envía al destino si es un área de texto o entrada)
- pulsación de tecla (enviada en el DOM)
- entrada (se envía al destino si es un área de texto o entrada)
- cambio (despachado en el objetivo si es una selección)
- keyup (enviado en el DOM)
Luego, opcionalmente para la mayoría:
- desenfoque (enviado en el DOM con el conjunto de objetivos)
Esto realmente cambia el texto en la página a través de javascript (sin modificar las declaraciones de valor) y activa a los oyentes / manejadores de javascript de manera apropiada. Si arruina la secuencia, javascript no se activará en el orden apropiado, el texto en el cuadro de entrada no cambiará, las selecciones no cambiarán o el cursor no se moverá al siguiente espacio en el área de texto.
Desafortunadamente, el código fue escrito para un empleador bajo un NDA, por lo que no puedo compartirlo, pero definitivamente es posible, pero debe recrear la "pila" de entrada de clave completa para cada elemento en el orden correcto.
Puede crear y enviar eventos de teclado, y activarán los controladores de eventos registrados adecuados, sin embargo , no generarán ningún texto , si se envían al elemento de entrada, por ejemplo.
Para simular completamente la entrada de texto, debe producir una secuencia de eventos de teclado y establecer explícitamente el texto del elemento de entrada. La secuencia de eventos depende de qué tan bien desea simular la entrada de texto.
La forma más simple sería:
$(''input'').val(''123'');
$(''input'').change();
Puedes enviar eventos de teclado en un elemento como este
element.dispatchEvent(new KeyboardEvent(''keypress'',{''key'':''a''}));
Puedes usar dispatchEvent()
:
function simulateKeyPress() {
var evt = document.createEvent("KeyboardEvent");
evt.initKeyboardEvent("keypress", true, true, window,
0, 0, 0, 0,
0, "e".charCodeAt(0))
var body = document.body;
var canceled = !body.dispatchEvent(evt);
if(canceled) {
// A handler called preventDefault
alert("canceled");
} else {
// None of the handlers called preventDefault
alert("not canceled");
}
}
No probé esto, pero está adaptado del código en la documentación de dispatchEvent () . Probablemente querrá leer todo eso y también los documentos para createEvent () y initKeyEvent ().
Si estás de acuerdo en usar jQuery 1.3.1:
function simulateKeyPress(character) {
jQuery.event.trigger({ type : ''keypress'', which : character.charCodeAt(0) });
}
$(function() {
$(''body'').keypress(function(e) {
alert(e.which);
});
simulateKeyPress("e");
});
Sobre la base de la respuesta de alex2k8, aquí hay una versión revisada que funciona en todos los navegadores compatibles con jQuery (el problema era que faltaban argumentos para jQuery.event.trigger, que es fácil de olvidar al usar esa función interna).
// jQuery plugin. Called on a jQuery object, not directly.
jQuery.fn.simulateKeyPress = function (character) {
// Internally calls jQuery.event.trigger with arguments (Event, data, elem).
// That last argument, ''elem'', is very important!
jQuery(this).trigger({ type: ''keypress'', which: character.charCodeAt(0) });
};
jQuery(function ($) {
// Bind event handler
$(''body'').keypress(function (e) {
alert(String.fromCharCode(e.which));
console.log(e);
});
// Simulate the key press
$(''body'').simulateKeyPress(''x'');
});
Incluso podría seguir presionando esto y dejar que no solo simule el evento, sino que en realidad inserte el carácter (si es un elemento de entrada), sin embargo, hay muchos elementos de este tipo en todos los navegadores al intentar hacer eso. Mejor usar un plugin más elaborado como SendKeys .
Tan pronto como el usuario presiona la tecla en cuestión, puede almacenar una referencia a ese par y usarla en cualquier otro elemento HTML:
EnterKeyPressToEmulate<input class="lineEditInput" id="addr333_1" type="text" style="width:60%;right:0%;float:right" onkeydown="keyPressRecorder(event)"></input>
TypeHereToEmulateKeyPress<input class="lineEditInput" id="addr333_2" type="text" style="width:60%;right:0%;float:right" onkeydown="triggerKeyPressOnNextSiblingFromWithinKeyPress(event)">
Itappears Here Too<input class="lineEditInput" id="addr333_3" type="text" style="width:60%;right:0%;float:right;" onkeydown="keyPressHandler(event)">
<script>
var gZeroEvent;
function keyPressRecorder(e)
{
gZeroEvent = e;
}
function triggerKeyPressOnNextSiblingFromWithinKeyPress(TTT)
{
if(typeof(gZeroEvent) != ''undefined'') {
TTT.currentTarget.nextElementSibling.dispatchEvent(gZeroEvent);
keyPressHandler(TTT);
}
}
function keyPressHandler(TTT)
{
if(typeof(gZeroEvent) != ''undefined'') {
TTT.currentTarget.value+= gZeroEvent.key;
event.preventDefault();
event.stopPropagation();
}
}
</script>
puede configurar el KeyCode si crea su propio evento, puede copiar los parámetros existentes de cualquier evento de teclado real (ignorando los objetivos ya que es el trabajo de dispatchEvent) y:
ta = new KeyboardEvent(''keypress'',{ctrlKey:true,key:''Escape''})
Un inspector web de Javascript de una sola fila listo para la consola en una copia + pegar (este tipo ya es atractivo para la mayoría de los desarrolladores, así que no intentes pretenderlo, se supone que es soltero .. remado)
var pressthiskey = "q"/* <--- :) !? q for example */; var e = new Event("keydown"); e.key=pressthiskey; e.keyCode=e.key.charCodeAt(0); e.which=e.keyCode; e.altKey=false; e.ctrlKey=true; e.shiftKey=false; e.metaKey=false; e.bubbles=true; document.dispatchEvent(e);
Una versión no jquery que funciona tanto en webkit como en gecko:
var keyboardEvent = document.createEvent("KeyboardEvent");
var initMethod = typeof keyboardEvent.initKeyboardEvent !== ''undefined'' ? "initKeyboardEvent" : "initKeyEvent";
keyboardEvent[initMethod](
"keydown", // event type : keydown, keyup, keypress
true, // bubbles
true, // cancelable
window, // viewArg: should be window
false, // ctrlKeyArg
false, // altKeyArg
false, // shiftKeyArg
false, // metaKeyArg
40, // keyCodeArg : unsigned long the virtual key code, else 0
0 // charCodeArgs : unsigned long the Unicode character associated with the depressed key, else 0
);
document.dispatchEvent(keyboardEvent);
solo usa CustomEvent
Node.prototype.fire=function(type,options){
var event=new CustomEvent(type);
for(var p in options){
event[p]=options[p];
}
this.dispatchEvent(event);
}
4 ex quieren simular ctrl + z
window.addEventListener("keyup",function(ev){
if(ev.ctrlKey && ev.keyCode === 90) console.log(ev); // or do smth
})
document.fire("keyup",{ctrlKey:true,keyCode:90,bubbles:true})