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


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,

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


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

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 .


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 ...


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" />


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);
Любопытный
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.