Is het mogelijk om toetsaanslagen programmatisch te simuleren?

Is het mogelijk om toetsaanslagen programmatisch in JavaScript te simuleren?


Antwoord 1, autoriteit 100%

Een niet-jQuery-versie die zowel in webkit als in gekko werkt:

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

Antwoord 2, autoriteit 36%

Als je toestemming hebt om jQuery 1.3.1 te gebruiken:

   function simulateKeyPress(character) {
      jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
    }
    $(function() {
      $('body').keypress(function(e) {
        alert(e.which);
      });
      simulateKeyPress("e");
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>

Antwoord 3, autoriteit 31%

Je kunt toetsenbordgebeurtenissen verzenden op een element als dit

element.dispatchEvent(new KeyboardEvent('keydown',{'key':'a'}));

Het is echter mogelijk dat dispatchEvent de waarde van het invoerveld niet bijwerkt


Voorbeeld:

let element = document.querySelector('input');
element.onkeydown = e => alert(e.key);
element.dispatchEvent(new KeyboardEvent('keydown',{'key':'a'}));
  
<input/>

Antwoord 4, autoriteit 26%

Wat u kunt doen, is programmatisch keyevent-listenersactiveren door keyeventsaf te vuren. Het is logisch om dit toe te staan vanuit een sandbox-beveiligingsperspectief. Met deze mogelijkheid kun je een typisch observer-patroontoepassen. Je zou deze methode “simuleren” kunnen noemen.

Hieronder ziet u een voorbeeld van hoe u dit kunt bereiken in de W3C DOM-standaard samen met 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...
  }
}

Dit voorbeeld is aangepast van: HTPS: // 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*/)      
   });

Maar vanaf recent is er geen [DOM]-manier om KeyEvents daadwerkelijk te activeren die de browser-sandbox verlaten. en alle belangrijke browserverkopers zullen zich houden aan dat beveiligingsconcept.

Wat betreft plug-ins zoals Adobe Flash – die zijn gebaseerd op de NPAP- en Permit Bypassing the Sandbox: deze zijn phasing-out ; firefox .

Gedetailleerde uitleg:

U kunt niet en u moet niet om veiligheidsredenen (zoals Pekka al opmerkt). U hebt altijd een gebruikersinteractie nodig tussen. Bovendien stel je voor dat de kans dat de browserverkopers door gebruikers worden aangegaan, omdat verschillende programmatische toetsenbordgebeurtenissen hebben geleid tot spoofing-aanvallen.

Zie deze post voor alternatieven en meer details. Er is altijd de op Flash gebaseerde kopie-en-pasta. Hier is een elegante voorbeeld . Tegelijkertijd is het een getuigenis waarom het web weggaat van pluginverkopers.

Er wordt een vergelijkbare beveiligingsmindset toegepast in het geval van de opt -in CORS-beleidom programmatisch toegang te krijgen tot externe inhoud.

Het antwoord is:
Er is onder normale omstandigheden geen manier om invoertoetsen programmatisch te activeren in de sandbox-browseromgeving.

Bottomline:ik zeg niet dat het in de toekomst niet mogelijk zal zijn, onder speciale browser-modi en/of privileges voor het einddoel van gamen, of soortgelijke gebruikerservaringen. Voordat dergelijke modi worden geactiveerd, wordt de gebruiker echter om toestemming en risico’s gevraagd, vergelijkbaar met de API-model op volledig scherm.

Handig:in de context van KeyCodes, dezetool en keycode mapping zal van pas komen.

Openbaarmaking:het antwoord is gebaseerd op het antwoord hier.


Antwoord 5, autoriteit 15%

Vanaf 2019 heeft deze oplossing voor mij gewerkt:

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

Ik heb dit in mijn browsergame gebruikt om mobiele apparaten met een gesimuleerd toetsenbord te ondersteunen.

Verduidelijking:deze code verzendt een enkele keydown-gebeurtenis, terwijl een echte toetsdruk één keydown-gebeurtenis zou activeren (of meerdere als het wordt langer vastgehouden), en dan één keyup-gebeurtenis wanneer u die toets loslaat. Als u ook keyup-gebeurtenissen nodig heeft, is het ook mogelijk om keyup-gebeurtenissen te simuleren door "keydown"te wijzigen in "keyup"in het codefragment.

Dit stuurt de gebeurtenis ook naar de hele webpagina, vandaar het document. Als u wilt dat alleen een specifiek element de gebeurtenis ontvangt, kunt u het gewenste element vervangen door document.


Antwoord 6, autoriteit 13%

U kunt dispatchEvent()gebruiken:

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

Ik heb dit niet getest, maar het is aangepast van de code op dispatchEvent()’ s documentatie. Je zult dat waarschijnlijk willen doorlezen, en ook de documenten voor createEvent() en initKeyEvent().


Antwoord 7, autoriteit 12%

Je kunt toetsenbordgebeurtenissen maken en verzenden, en ze zullen de juiste geregistreerde gebeurtenishandlers activeren, maar ze produceren geen tekst, als ze bijvoorbeeld naar een invoerelement worden verzonden.

Om tekstinvoer volledig te simuleren, moet u een reeks toetsenbordgebeurtenissen produceren en de tekst van het invoerelement expliciet instellen. De volgorde van gebeurtenissen hangt af van hoe grondig u tekstinvoer wilt simuleren.

De eenvoudigste vorm zou zijn:

$('input').val('123');
$('input').change();

Antwoord 8, autoriteit 8%

In sommige gevallen kan de gebeurtenis keypressde vereiste functionaliteit niet bieden. Uit mozilla docskunnen we zien dat de functie is verouderd :

Deze functie wordt niet langer aanbevolen. Hoewel sommige browsers het nog steeds ondersteunen, is het mogelijk al verwijderd uit de relevante webstandaarden, wordt het misschien verwijderd of wordt het alleen bewaard voor compatibiliteitsdoeleinden. Vermijd het gebruik ervan en update indien mogelijk bestaande code; zie de compatibiliteitstabel onderaan deze pagina om uw beslissing te begeleiden. Houd er rekening mee dat deze functie op elk moment kan ophouden te werken.

Dus, aangezien de keypress-gebeurtenis wordt gecombineerd uit de twee consequent geactiveerde gebeurtenissen keydown, en de daaropvolgende keyupvoor dezelfde toets, genereer de gebeurtenissen één voor één:

element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'}));
element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));

Antwoord 9, autoriteit 7%

Voortbouwend op het antwoord van alex2k8, is hier een herziene versie die werkt in alle browsers die jQuery ondersteunt (het probleem was het ontbreken van argumenten voor jQuery.event.trigger, wat gemakkelijk te vergeten is bij het gebruik van die interne functie).

p>

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

Je zou dit zelfs nog verder kunnen pushen en het niet alleen de gebeurtenis laten simuleren, maar het karakter ook daadwerkelijk laten invoegen (als het een invoerelement is), maar er zijn veel cross-browser problemen wanneer je dat probeert. Gebruik beter een uitgebreidere plug-in zoals SendKeys.


Antwoord 10, autoriteit 5%

Voor degenen die geïnteresseerd zijn, kunt u op betrouwbare wijze toetsenbordinvoergebeurtenissen opnieuw creëren. Om tekst in het invoergebied te wijzigen (verplaats cursors of de pagina via een invoerteken) moet u het DOM-gebeurtenismodel nauwlettend volgen: http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents

Het model zou moeten doen:

  • focus (verzonden op de DOM met het doel ingesteld)

Vervolgens voor elk teken:

  • keydown (verzonden op de DOM)
  • beforeinput (verzonden naar het doel als het een textarea of input is)
  • toetsdruk (verzonden op de DOM)
  • invoer (verzonden naar het doel als het een tekstgebied of invoer is)
  • wijzig (verzonden naar het doel als het een select is)
  • keyup (verzonden op de DOM)

Dan, optioneel voor de meesten:

  • Blur (verzonden op de DOM met de doelwit)

Hierdoor wijzigt u de tekst in de pagina via JavaScript (zonder waardeafschriften te wijzigen) en zet de JavaScript-luisteraars / handlers op de juiste manier in. Als u de Sequence-JavaScript hebt ingeschakeld in de juiste volgorde, zal de tekst in het invoervak ​​niet veranderen, de selecties zullen niet veranderen of de cursor zal niet naar de volgende ruimte in het tekstgebied gaan.

Helaas is de code geschreven voor een werkgever onder een NDA, dus ik kan het niet delen, maar het is absoluut mogelijk, maar u moet de volledige toets-ingang “Stack” voor elk element in de juiste volgorde opnieuw maken.


11, Autoriteit 3%

Deze aanpak ondersteunt dwarsbrowser de waarde van sleutelcode .
bron

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

12, Autoriteit 3%

Gebruik gewoon 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 wil ctrl+z simuleren

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

Antwoord 13, autoriteit 2%

Het was ooit een keer geroeid vanwege het eenvoudige gebruik in een console-context. Maar waarschijnlijk toch nuttig.

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

14, Autoriteit 2%

Hier is een bibliotheek die echt helpt: https: / /cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js

Ik weet niet van waar deden het vandaan kwam, maar het is nuttig. Het voegt een .simulate()methode window.KeyEvent, zodat je het gebruikt gewoon met KeyEvent.simulate(0, 13)voor het simuleren een enterof KeyEvent.simulate(81, 81)voor een 'Q'.

Ik heb het op https://github.com/ccampbell/mousetrap/tree/ master / testen .


15, Autoriteit 2%

Het cruciale onderdeel om dit te laten werken is om te beseffen dat charCode, keyCodeen whichalle verouderde methoden. Daarom, als de code verwerkingde toetsaanslaggebeurtenis een van deze drie gebruikt, ontvangt deze een nepantwoord (bijvoorbeeld een standaardwaarde van 0).

Zolang u de toetsdrukgebeurtenis opent met een niet-afgekeurde methode, zoals key, zou u in orde moeten zijn.

Ter voltooiing heb ik de basis Javascript-code toegevoegd om de gebeurtenis te activeren:

const rightArrowKey = 39
const event = new KeyboardEvent('keydown',{'key':rightArrowKey})
document.dispatchEvent(event)

Antwoord 16

Native JavaScript met TypeScript-ondersteunde oplossing:

Typ de keyCode of welke eigenschap je ook gebruikt en cast deze naar KeyboardEventInit

Voorbeeld

   const event = new KeyboardEvent("keydown", {
              keyCode: 38,
            } as KeyboardEventInit);

Antwoord 17

Ik wilde een ‘Tab’-pers simuleren… Voortbordurend op Trevors antwoord, kunnen we zien dat een speciale toets zoals ‘tab’ wordt wel ingedrukt, maar we zien niet het werkelijke resultaat dat een ‘tab’-druk zou hebben…

geprobeerd met het verzenden van deze gebeurtenissen voor ‘ActiveElement’, evenals het wereldwijde documentobject, zowel – code voor beide toegevoegd;

fragment hieronder:

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>

Antwoord 18

Hier is een oplossing die werkt in Chrome en Chromium (heb alleen deze platforms getest). Het lijkt erop dat Chrome een bug of eigen benadering heeft voor het verwerken van sleutelcodes, dus deze eigenschap moet afzonderlijk worden toegevoegd aan de 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);
    }
    simulateKeydown(39, false, false, false);

Antwoord 19

Dat heb ik geprobeerd met js/typescript in chrome. Dankzij
dit antwoordter inspiratie.

var x = document.querySelector('input');
var keyboardEvent = new KeyboardEvent("keypress", { bubbles: true });
// you can try charCode or keyCode but they are deprecated
Object.defineProperty(keyboardEvent, "key", {
  get() {
    return "Enter";
  },
});
x.dispatchEvent(keyboardEvent);

Antwoord 20

Ik weet dat de vraag vraagt om een javascript-manier om een toetsaanslag te simuleren. Maar voor degenen die op zoek zijn naar een jQuery-manier om dingen te doen:

var e = jQuery.Event("keypress");
e.which = 13 //or e.keyCode = 13 that simulates an <ENTER>
$("#element_id").trigger(e); 

Antwoord 21

zodra de gebruiker op de betreffende toets drukt, kunt u zelfs een verwijzing naar die toets opslaan en deze op elk ander HTML-element gebruiken:

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>

Antwoord 22

Dit is wat ik heb kunnen vinden:

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)

Other episodes