2012-05-04 33 views
25

Chcę symulować zdarzenia keydown na danym elemencie textarea na stronie html. Ponieważ używam chrome, nazwałem zmienną initKeyboardEvent i przekazałem kod keyCode, który chcę wpisać w textarea. Oto, co starałem:Symulacja Keydown w Chrome wystrzeliwuje normalnie, ale nie jest to właściwy klucz.

var keyEvent = document.createEvent('KeyboardEvent'); 
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0); 
inputNode.dispatchEvent(keyEvent); 

W tym kodzie piszę list m jednak textarea jest uzyskanie tylko keyCode 13 która jest kluczem Enter. Tak, próbowałem kodu nadpisywania widziałem w internecie, który ustawia wartość keyCodeVal, ale bez powodzenia

var keyEvent = document.createEvent('KeyboardEvent'); 
Object.defineProperty(keyEvent, 'keyCode', { 
         get : function() { 
           return this.keyCodeVal; 
         } 
         }); 
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0); 
keyEvent.keyCodeVal = 77; 
inputNode.dispatchEvent(keyEvent); 

Czy ktoś ma pomysł jak ustawić wartość keyCode?

+0

Uwaga: ręczne wystrzeliwanie zdarzenia nie generuje domyślnej akcji związanej z tym zdarzeniem. Na przykład ręczne wystrzeliwanie zdarzenia klucza nie powoduje, że ta litera będzie wyświetlana w ustawieniach tekstu skupionego. W przypadku zdarzeń interfejsu użytkownika jest to ważne ze względów bezpieczeństwa, ponieważ uniemożliwia skryptom symulowanie działań użytkowników, które wchodzą w interakcję z samą przeglądarką. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent –

+0

** EDYTOWANA **: Rozwiązanie Orwellophile działa. Sprawdź to demo, aby zobaczyć je w akcji + ogólne wydarzenie alternatywne: http://jsbin.com/awenaq/4 –

Odpowiedz

77

Tak bardzo, bardzo blisko ...

po prostu potrzebne, aby zastąpić „który” własności. Oto niektóre przykładowy kod: Wykorzystanie

Podium = {}; 
Podium.keydown = function(k) { 
    var oEvent = document.createEvent('KeyboardEvent'); 

    // Chromium Hack 
    Object.defineProperty(oEvent, 'keyCode', { 
       get : function() { 
        return this.keyCodeVal; 
       } 
    });  
    Object.defineProperty(oEvent, 'which', { 
       get : function() { 
        return this.keyCodeVal; 
       } 
    });  

    if (oEvent.initKeyboardEvent) { 
     oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, k, k); 
    } else { 
     oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, k, 0); 
    } 

    oEvent.keyCodeVal = k; 

    if (oEvent.keyCode !== k) { 
     alert("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ")"); 
    } 

    document.dispatchEvent(oEvent); 
} 

Próbka:

Podium.keydown(65); 

Uwaga: kod ten nie jest przeznaczony do pracy w IE, Safari lub innych przeglądarek. No, może z Firefoksem. YMMV.

+12

+1 To jedyne działające rozwiązanie na tym Stackoverflow.com –

+0

Użyłem tego w rozszerzeniu Chrome, aby uruchomić zdarzenie keydown na obszarze tekstowym (na Facebooku). Z jakiegoś powodu obsługa witryny nigdy nie jest uruchamiana, więc nie reaguje. Każdy pomysł, dlaczego? – freeall

+6

Nie wydaje się już działać. Sugerowana alternatywa. –

14

Rozwiązanie Orwellophile działa.

  • Po pierwsze: "keyCode", "charCode" i "which" są tylko do odczytu w Safari i IE9 + (przynajmniej).
  • Po drugie: initKeyboardEvent jest trochę nieporządny. Wszystkie przeglądarki implementują je w inny sposób. Nawet w webkitach istnieje kilka różnych implementacji initKeyboardEvent. I nie ma "dobrego" sposobu na initKeyboardEvent w Operze.
  • Po trzecie: initKeyboardEvent jest przestarzałe. Musisz użyć konstruktora initKeyEvent lub KeyboardEvent.

Tutaj napisałem cross-browser initKeyboardEvent function (GIST):

Przykład:

var a = window.crossBrowser_initKeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true}) 
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey) 

i tu jest mój DOM Keyboard Event Level 3 polyfill z cross-browser KeyboardEvent konstruktora.

przykład:

var a = new KeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true}) 
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey) 

Example 2

Example 3

Ważne Uwaga 1: charCode, kodu oraz właściwości, które jest zalecane. Tak więc żaden mój konstruktor CrossBrowser_initKeyboardEvent no KeyboardEvent nie ma absolutnie gwarancji prawidłowych wartości tych właściwości w niektórych przeglądarkach. Możesz użyć właściwości "klucz" i "znak" zamiast lub edytować moje gist, aby wymusić użycie initEvent w przeglądarkach z kodem znakowym tylko do odczytu, kodem klucza i właściwościami.

Ważna uwaga 2: Zdarzenie keypress jest przestarzałe i na razie nieobsługiwane w moim Keyboard Event Level 3 polyfill.Oznacza to, że właściwości klawiszy i char w zdarzeniu keypress mogą mieć losowe wartości. Pracuję nad rozwiązaniem tego problemu z kompatybilnością wsteczną.

+0

Najlepszy opis problemu, który do tej pory widziałem. +1 –

+0

@termi, próbowałem użyć Twojego źródła do symulacji wydarzenia w przeglądarce Chrome 36, ale nie działa !! –

+1

@AkashKava, czy wypróbowujesz "funkcję initKeyboardEvent w różnych przeglądarkach" lub polyfill? Polyfill jest nieaktualny. Nie mam zbyt wiele wolnego czasu, żeby to naprawić. Ale "cross-browser initKeyboardEvent function (gist)" działa dla mnie. Czy możesz podać przykład? – termi

4

Aby skrypt @ Orwellophile działał w przeglądarce Google Chrome 26.0.1410.65 (w systemie Mac OS X 10.7.5, jeśli to ma znaczenie), musiałem zmienić jedną linię: jego skrypt wydaje się mieć parametry: initKeyboardEvent w inną kolejność niż MDN documentation for initKeyboardEvent.

Zmieniona linia wygląda następująco:

oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, k, k, "", "", false, ""); 
0

Wszystkie rozwiązania powyżej pracują, ale znalazłem jeden przypadek nie będzie.

Jeśli używana jest funkcja Dart, kod Dart wykorzystujący KeyboardEvents nie będzie działał na ogólnym wydarzeniu.

Otrzymasz coś w stylu $ keyCode jest niezdefiniowany.

walić po głowie przez wiele godzin na to, znalazłem następujące trick:

function __triggerKeyboardEvent(el, keyCode) 
{ 
    var eventObj = document.createEventObject ? 
     document.createEventObject() : document.createEvent("Events"); 

    var tempKeyboardObj = document.createEvent("KeyboardEvents"); 

    if(eventObj.initEvent){ 
     eventObj.initEvent("keydown", true, true); 
    } 
    eventObj.___dart_dispatch_record_ZxYxX_0_ = tempKeyboardObj.___dart_dispatch_record_ZxYxX_0_ 
    eventObj.keyCode = keyCode; 
    eventObj.which = keyCode; 

    el.dispatchEvent ? el.dispatchEvent(eventObj) : el.fireEvent("onkeydown", eventObj); 

} 

oszukiwanie Dart przechwytujących na rzecz naszej imprezy jest rzeczywiście KeyboardEvent, załatwiło sprawę.

Zostawiając to tutaj, dla biednego gościa, który próbuje przetestować aplikację Dart w przeglądarce opartej na webkitach.

3

Cóż, powyższe rozwiązania zadziałały, również dzięki @dland dla wskazówki dotyczącej parametru. Oto coś, co uznałem za użyteczne, jeśli nie jesteś w stanie sprawić, by zdarzenia strzelały we właściwe miejsce.

Skrypt @ Orwellophile uruchamia zdarzenie na dokumencie. Możliwe, że detektor zdarzeń nie zawsze jest zarejestrowany na document. Zmieniłem ostatnią linię do następnej, a teraz działa za każdym razem.

document.activeElement.dispatchEvent(oEvent);

The document.activeElement zawsze odpala zdarzenie na elemencie, w którym użytkownik jest aktualnie koncentruje się na.

+0

Myślę, że brakuje ci punktu SO. Jeśli masz sugestię, umieść ją w komentarzu do odpowiedzi. Jeśli masz zmianę, zmodyfikuj kod. Jeśli nie masz uprawnień do robienia tych rzeczy, to zdecydowanie nie powinieneś publikować swoich doświadczeń i zmian jednej linii jako "Odpowiedzi". Teraz może się okazać, że to, co mówisz, jest poprawne, ale ten fragment kodu jest dostępny online i ma wiele odniesień od 2012 roku, prawie 5 lat temu. Od liczby ludzi, którzy używali tego i komentowali go, wiem, że to działa. Jeśli teraz zmienię tę zmianę, co wtedy? – Orwellophile

Powiązane problemy