Uruchamianie zdarzenia klawiatury w przeglądarce Safari przy użyciu JavaScript

79

Próbuję zasymulować zdarzenie klawiatury w Safari przy użyciu JavaScript.

Próbowałem tego:

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

... a także to:

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

Jednak po wypróbowaniu obu podejść mam ten sam problem: po wykonaniu kodu właściwości keyCode/ whichobiektu zdarzenia są ustawione na 0, nie 115.

Czy ktoś wie, jak niezawodnie tworzyć i wysyłać zdarzenia klawiatury w Safari? (Wolałbym to osiągnąć w zwykłym JavaScript, jeśli to możliwe).

Steve Harrison
źródło
Czy próbujesz wykonać kod, który zdefiniowałeś lub jakąś kombinację klawiszy, którą rozumie przeglądarka? Jeśli jest to Twój własny kod, najlepiej byłoby skonfigurować opakowanie zdarzenia, które można wywołać za pomocą „prawdziwego” interfejsu klawiatury lub innego generatora zdarzeń, jak opisano tutaj. W razie potrzeby refaktoryzacja.
Nolte
1
W tym przykładzie próbuję zasymulować naciśnięcie klawisza „s” przez użytkownika. Ostatecznie próbuję zasymulować naciśnięcie przez użytkownika Command-R w widżecie Apple Dashboard.
Steve Harrison
2
Twój kod rozwiązał mój problem :)
@ acidzombie24: Z przyjemnością! :)
Steve Harrison,
4
Duplikat Simulate JavaScript Key Events
Dan Dascalescu

Odpowiedzi:

43

Pracuję nad polyfillem DOM Keyboard Event Level 3 . W najnowszych przeglądarkach lub z tym polyfillem możesz zrobić coś takiego:

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

AKTUALIZACJA:

Teraz mój polyfill obsługuje starsze właściwości „keyCode”, „charCode” i „which”

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

Przykłady tutaj

Dodatkowo tutaj jest initKeyboardEvent dla różnych przeglądarek niezależnie od mojego polyfill: ( streszczenie )

Demo Polyfill

termi
źródło
Wydaje się, że nie działa przy tworzeniu przewijanego obszaru przewijanego w dół za pomocą strzałek lub klawiszy strona w górę / w dół ...
Michael
Zmieniono twoje jsfiddle, aby wysyłało wydarzenie w polu tekstowym zamiast w dokumencie @ jsfiddle.net/vnathalye/yjc5F/974 . Mimo że uruchamia obsługę naciśnięcia klawisza, tekst nie jest wyświetlany w polu tekstowym. Dowolny pomysł?
Vivek Athalye
1
@termi Twój link demo nie działa
Sebastian
Wydaje się, że nie działa również przy zmianie wartości elementu wejściowego (tekstowego).
Michael,
Operand operatora delete nie może być właściwością tylko do odczytu.
nircraft
30

Czy wysłałeś wydarzenie poprawnie?

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

Jeśli używasz jQuery, możesz zrobić:

function simulateKeyPress(character) {
  jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}
tyronegcarter
źródło
3
Czy można w ten sposób zasymulować Ctrl + C (skrót do kopiowania)?
John John Pichler
1
@claudiopro Tak, masz rację(evt.initKeyEvent || evt.initKeyboardEvent).call(evt, // etc.
tyronegcarter
12
InitKeyboardEvent również nie działa w Chromium. event.keyCodei event.whichzawsze zwraca 0. To znany błąd i obejściem jest użycie zwykłego zdarzeniavar event = document.createEvent('Event'); event.initEvent('keydown', true, true); event.keyCode = 76;
lluft
5
Głosowano w dół : initKeyEventi initKeyboardEventWYCOFANE .
Константин Ван
2
@ K._ zamiast głosować w dół na poprzednio działającą odpowiedź, stwierdzenie, że jest ona przestarzała, powinno wystarczyć, aby dać każdemu heads-up bez negatywnego wpływu na tyronegcarter. Ta odpowiedź stackoverflow.com/questions/961532/ ... używa nowoczesnego programu KeyboardEvent developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/ ...
bit-less
17

Wynika to z błędu w Webkit.

Możesz obejść błąd Webkita używając createEvent('Event')zamiast createEvent('KeyboardEvent'), a następnie przypisując keyCodewłaściwość. Zobacz tę odpowiedź i ten przykład .

Jan
źródło
8

Witryna Mozilla Developer Network zapewnia następujące wyjaśnienie:

  1. Utwórz wydarzenie za pomocą event = document.createEvent("KeyboardEvent")
  2. Zainicjuj keyevent

za pomocą:

event.initKeyEvent (type, bubbles, cancelable, viewArg, 
       ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, 
           keyCodeArg, charCodeArg)
  1. Wyślij zdarzenie za pomocąyourElement.dispatchEvent(event)

Nie widzę ostatniego w Twoim kodzie, może właśnie tego brakuje. Mam nadzieję, że to działa również w IE ...

Javache
źródło
2
Niestety implementacja Mozilli jest niestandardowa. Jeśli chodzi o punkt 3, moim problemem jest utworzenie prawidłowego zdarzenia - po tym następuje wysłanie zdarzenia. Ponadto, ponieważ tworzę dla Dashboard firmy Apple, nie muszę w ogóle martwić się o IE! (Whoopee!)
Steve Harrison
5
.initKeyEventjest teraz przestarzały
Hampus Ahlgren
1

Nie radzę sobie z tym zbyt dobrze, ale KeyboardEvent=> zobacz, że KeyboardEvent jest inicjowany za pomocą initKeyEvent.
Oto przykład emitowania zdarzenia na <input type="text" />elemencie

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
źródło
7
to widać 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)na safari :(
He Yifei 何 一 非
Powinien to być: var kEvent = document.createEvent ("KeyboardEvent"); kEvent.initKeyboardEvent ("keypress", true, true, null, false, false, false, false, 74, 74); document.dispatchEvent (kEvent);
Любопытный