È possibile simulare gli eventi di stampa chiave a livello di codice in JavaScript?
È possibile simulare gli eventi di stampa chiave a livello di codice in JavaScript?
Risposte:
Una versione non jquery che funziona sia in webkit che in 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, // view: should be window
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
40, // keyCode: unsigned long - the virtual key code, else 0
0 // charCode: unsigned long - the Unicode character associated with the depressed key, else 0
);
document.dispatchEvent(keyboardEvent);
keyCode
è sempre 0 e non posso cambiarlo.
event.which
sempre 0
quando si utilizza document.createEvent("KeyboardEvent")
. @lluft ha condiviso i dettagli e una soluzione alternativa, che ha funzionato per me, in questo commento su un thread diverso. Fondamentalmente, è necessario utilizzare document.createEvent('Event')
per creare un evento generico e quindi impostare il tipo su keydown
e assegnare una keyCode
proprietà uguale al codice di accesso alla chiave.
Se stai bene usare 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");
});
trigger
non può essere utilizzato per imitare gli eventi del browser nativo .
Quello che puoi fare è attivare a livello di codice ascoltatori keyevent sparando keyevent . Ha senso consentirlo dal punto di vista della sicurezza in modalità sandbox. Usando questa abilità, puoi quindi applicare un tipico modello di osservatore . È possibile chiamare questo metodo "simulazione".
Di seguito è riportato un esempio di come eseguire ciò nello standard DOM W3C insieme a 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...
}
}
Questo esempio è adattato da: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
In jQuery:
jQuery('input[type=submit][name=btnK]')
.trigger({
type: 'keypress',
which: character.charCodeAt(0 /*the key to trigger*/)
});
Ma di recente, non esiste un modo [DOM] per attivare effettivamente eventi chiave che escono dal browser-sandbox. E tutti i principali fornitori di browser aderiranno a questo concetto di sicurezza.
Per quanto riguarda i plug-in come Adobe Flash, che sono basati su NPAPI, e consentono di bypassare il sandbox: questi sono in fase di eliminazione ; Firefox .
Spiegazione dettagliata:
Non è possibile e non è necessario per motivi di sicurezza (come già sottolineato da Pekka). Sarà sempre necessaria l'interazione dell'utente tra. Immagina inoltre la possibilità che i venditori di browser vengano citati in giudizio dagli utenti, poiché vari eventi programmatici della tastiera avranno portato a attacchi di spoofing.
Vedi questo post per alternative e maggiori dettagli. C'è sempre il copia e incolla basato su flash. Ecco un esempio elegante . Allo stesso tempo è una testimonianza del perché il Web si sta allontanando dai fornitori di plug-in.
Esiste una mentalità di sicurezza simile applicata nel caso della politica di opt-in CORS per accedere al contenuto remoto a livello di codice .
La risposta è:
non esiste alcun modo per attivare a livello di codice le chiavi di input nell'ambiente browser in modalità sandbox in circostanze normali .
In conclusione: non sto dicendo che non sarà possibile in futuro, in speciali modalità browser e / o privilegi verso l'obiettivo finale del gioco o esperienze utente simili. Tuttavia, prima di accedere a tali modalità, all'utente verranno richiesti autorizzazioni e rischi, in modo simile al modello di API a schermo intero .
Utile: nel contesto di KeyCodes, questo strumento e la mappatura dei codici chiave saranno utili.
Divulgazione: la risposta si basa sulla risposta qui .
Puoi inviare eventi da tastiera su un elemento come questo
element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));
keypress
deprecato, usando keydown
invece -> developer.mozilla.org/en-US/docs/Web/Events/keypress
Puoi usare 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");
}
}
Non ho provato questo, ma è adattato dal codice sulla documentazione di dispatchEvent () . Probabilmente vorrai leggere questo, e anche i documenti per createEvent () e initKeyEvent ().
initKeyEvent
o initKeyboardEvent()
. Entrambi sono deprecati a favore dell'utilizzo del costruttore KeyboardEvent () .
È possibile creare e inviare eventi da tastiera e questi attiveranno i gestori di eventi registrati appropriati, tuttavia non produrranno alcun testo , ad esempio se inviati all'elemento di input.
Per simulare completamente l'immissione di testo è necessario produrre una sequenza di eventi da tastiera e impostare esplicitamente il testo dell'elemento di input. La sequenza degli eventi dipende dalla precisione con cui si desidera simulare l'immissione di testo.
La forma più semplice sarebbe:
$('input').val('123');
$('input').change();
In alcuni casi l' keypress
evento non può fornire la funzionalità richiesta. Dai documenti di mozilla possiamo vedere che la funzione è obsoleta:
Questa funzione non è più consigliata. Anche se alcuni browser potrebbero ancora supportarlo, potrebbe essere già stato rimosso dagli standard web pertinenti, potrebbe essere in procinto di essere eliminato o potrebbe essere conservato solo per motivi di compatibilità. Evita di usarlo e aggiorna il codice esistente se possibile; vedere la tabella di compatibilità in fondo a questa pagina per guidare la tua decisione. Tieni presente che questa funzione potrebbe smettere di funzionare in qualsiasi momento.
Quindi, poiché l' keypress
evento è combinato dai due eventi di conseguenza generati keydown
e il seguente keyup
per la stessa chiave, genera gli eventi uno a uno:
element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'}));
element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));
Sulla base della risposta di alex2k8, ecco una versione rivista che funziona in tutti i browser supportati da jQuery (il problema era negli argomenti mancanti a jQuery.event.trigger, che è facile dimenticare quando si utilizza quella funzione 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');
});
Potresti anche spingerlo oltre e lasciare che non solo simuli l'evento, ma in realtà inserisca il carattere (se è un elemento di input), tuttavia ci sono molti gotcha tra browser quando provano a farlo. Meglio usare un plugin più elaborato come SendKeys .
A partire dal 2019, questa soluzione ha funzionato per me:
document.dispatchEvent(
new KeyboardEvent("keydown", {
key: "e",
keyCode: 69, // example values.
code: "KeyE", // put everything you need in this object.
which: 69,
shiftKey: false, // you don't need to include values
ctrlKey: false, // if you aren't going to use them.
metaKey: false // these are here for example's sake.
})
);
L'ho usato nel mio browser game, al fine di supportare i dispositivi mobili con una tastiera simulata.
Chiarimento: questo codice invia un singolo keydown
evento, mentre la pressione di un tasto reale innescherebbe un keydown
evento (o più di essi se viene trattenuto più a lungo), quindi un keyup
evento quando si rilascia quel tasto. Se avete bisogno di keyup
eventi troppo, è anche possibile simulare keyup
eventi modificando "keydown"
a "keyup"
nel frammento di codice.
Questo invia anche l'evento a tutta la pagina web, quindi il document
. Se desideri che solo un elemento specifico riceva l'evento, puoi sostituire document
l'elemento desiderato.
Trusted
?)
Per gli interessati, è possibile, infatti, ricreare in modo affidabile eventi di input da tastiera. Per modificare il testo nell'area di input (spostare i cursori o la pagina tramite un carattere di input) è necessario seguire da vicino il modello di eventi DOM: http://www.w3.org/TR/DOM-Level-3-Events/ # h4_events-inputevents
Il modello dovrebbe fare:
Quindi per ogni personaggio:
Quindi, facoltativamente per la maggior parte:
Questo in realtà cambia il testo nella pagina tramite javascript (senza modificare le dichiarazioni di valore) e attiva in modo appropriato tutti i listener / gestori javascript. Se sbagli la sequenza javascript non si attiverà nell'ordine appropriato, il testo nella casella di input non cambierà, le selezioni non cambieranno o il cursore non si sposterà nello spazio successivo nell'area di testo.
Sfortunatamente il codice è stato scritto per un datore di lavoro in base a un NDA, quindi non posso condividerlo, ma è sicuramente possibile ma è necessario ricreare l'intero "stack" di input chiave per ciascun elemento nell'ordine corretto.
Questo approccio supporta il cross-browser modificando il valore del codice chiave . fonte
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);
basta usare 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 vogliono simulare 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})
Ecco una libreria che aiuta davvero: https://cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js
Non so da dove provenga, ma è utile. Aggiunge un .simulate()
metodo a window.KeyEvent
, quindi lo usi semplicemente con KeyEvent.simulate(0, 13)
per simulare un enter
o KeyEvent.simulate(81, 81)
per un 'Q'
.
L'ho preso su https://github.com/ccampbell/mousetrap/tree/master/tests .
Questo ha funzionato per me e simula un keyup per la mia textaera. se lo vuoi per l'intera pagina appena messo il KeySimulation()
su <body>
come questo <body onmousemove="KeySimulation()">
o, se non onmousemove
allora onmouseover
o onload
lavori troppo.
<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>
initKeyboardEvent
è deprecato. ( Fonte )
È stato remato una sola volta a causa del facile utilizzo in un contesto console. Ma probabilmente utile ancora.
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);
Ecco una soluzione che funziona in Chrome e Chromium (hanno testato solo queste piattaforme). Sembra che Chrome abbia qualche bug o un proprio approccio alla gestione dei codici chiave, quindi questa proprietà deve essere aggiunta separatamente 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);
}
Questo è quello che sono riuscito a trovare:
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)
JavaScript nativo con soluzione supportata da TypeScript:
Digita il keyCode o la proprietà che stai utilizzando e esegui il cast su KeyboardEventInit
Esempio
const event = new KeyboardEvent("keydown", {
keyCode: 38,
} as KeyboardEventInit);
Questo è quello che ho provato con js / typescript in Chrome. Grazie a questa risposta per l'ispirazione.
const x = document.querySelector('input');
const keyboardEvent = new KeyboardEvent("keypress", { bubbles: true });
Object.defineProperty(keyboardEvent, "charCode", {
get() {
return 13;
},
});
x.dispatchEvent(keyboardEvent);
non appena l'utente preme il tasto in questione è possibile memorizzare un riferimento anche a quello e usarlo su qualsiasi altro 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>
puoi impostare il keyCode se crei il tuo evento, puoi copiare i parametri esistenti da qualsiasi evento della tastiera reale (ignorando le destinazioni dal momento che è il lavoro di dispatchEvent) e:
ta = new KeyboardEvent('keypress',{ctrlKey:true,key:'Escape'})
So che la domanda richiede un modo javascript per simulare un tasto premuto. Ma per coloro che sono alla ricerca di un modo jQuery di fare le cose:
var e = jQuery.Event("keypress");
e.which = 13 //or e.keyCode = 13 that simulates an <ENTER>
$("#element_id").trigger(e);
La parte fondamentale per far funzionare tutto questo è rendersene conto charCode
, keyCode
e which
sono tutti metodi deprecati . Pertanto, se il codice che elabora l'evento key press utilizza uno di questi tre, allora riceverà una risposta fasulla (ad esempio un valore predefinito di 0).
Finché si accede all'evento premere il tasto con un metodo non deprecato, ad esempio key
, si dovrebbe essere OK.
Per il completamento, ho aggiunto il codice Javascript di base per l'attivazione dell'evento:
const rightArrowKey = 39
const event = new KeyboardEvent('keydown',{'key':rightArrowKey})
document.dispatchEvent(event)
Volevo simulare una stampa "Tab" ... Espandendo la risposta di Trevor, possiamo vedere che viene premuto un tasto speciale come "tab" ma non vediamo il risultato effettivo che avrebbe una pressa "tab". .
ho provato a inviare questi eventi per "activeElement" e per l'oggetto documento globale entrambi - codice per entrambi aggiunti di seguito;
frammento di seguito:
var element = document.getElementById("firstInput");
document.addEventListener("keydown", function(event) {
console.log('we got key:', event.key, ' keyCode:', event.keyCode, ' charCode:', event.charCode);
/* enter is pressed */
if (event.keyCode == 13) {
console.log('enter pressed:', event);
setTimeout(function() {
/* event.keyCode = 13; event.target.value += 'b'; */
theKey = 'Tab';
var e = new window.KeyboardEvent('focus', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('keydown', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('beforeinput', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('keypress', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('input', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('change', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('keyup', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
}, 4);
setTimeout(function() {
theKey = 'Tab';
var e = new window.KeyboardEvent('focus', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('keydown', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('beforeinput', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('keypress', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('input', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('change', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('keyup', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
}, 100);
} else if (event.keyCode != 0) {
console.log('we got a non-enter press...: :', event.key, ' keyCode:', event.keyCode, ' charCode:', event.charCode);
}
});
<h2>convert each enter to a tab in JavaScript... check console for output</h2>
<h3>we dispatchEvents on the activeElement... and the global element as well</h3>
<input type='text' id='firstInput' />
<input type='text' id='secondInput' />
<button type="button" onclick="document.getElementById('demo').innerHTML = Date()">
Click me to display Date and Time.</button>
<p id="demo"></p>