Симуляция Keydown в Chrome срабатывает нормально, но не правильный ключ

Я хочу симулировать события keydown для данного элемента textarea на странице html. Поскольку я использую chrome, я вызывал initKeyboardEvent в моей переменной, и я передал keyCode, который я хочу ввести в текстовое поле. Вот что я пробовал:

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

В этом коде я печатаю букву m, однако текстовое поле получает только keyCode 13, который является ключом Enter. Итак, я попробовал переопределить код, который я видел в Интернете, который устанавливает значение keyCodeVal, но без успеха

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

Есть ли у кого-нибудь идея, как установить значение keyCode?

Ответ 1

Так очень очень близко...

Вам просто нужно переопределить свойство "which". Вот пример кода:

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

Использование образца:

Podium.keydown(65);

Примечание. Этот код не предназначен для работы в IE, Safari или других браузерах. Ну, может быть, с Firefox. YMMV.

Ответ 2

Овервольфильное решение действительно работает.

  • Сначала: 'keyCode', 'charCode' и 'which' только для чтения в Safari и IE9 + (по крайней мере).
  • Во-вторых: initKeyboardEvent - это беспорядочно. Все браузеры реализуют его по-другому. Даже в webkit существует несколько различных реализаций initKeyboardEvent. И нет "хороших", путь к initKeyboardEvent в Opera.
  • В-третьих: initKeyboardEvent устарел. Вам нужно использовать конструктор initKeyEvent или KeyboardEvent.

Здесь я написал кросс-браузерную функцию initKeyboardEvent (gist):

Пример:

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

И вот мой DOM Keyboard Event Level 3 polyfill с кросс-браузерным конструктором KeyboardEvent.

Пример:

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

Пример 2

Пример 3

Важное примечание 1: charCode, keyCode и какие свойства устарели. Поэтому ни мой конструктор crossBrowser_initKeyboardEvent, ни конструктор KeyboardEvent абсолютно не гарантируют правильные значения этих свойств в некоторых браузерах. Вместо этого вы можете использовать свойства "ключ" и "char" или отредактировать gist, чтобы принудительно использовать initEvent в браузерах с charCode для чтения, keyCode и какие свойства.

Важное примечание 2: событие нажатия клавиши устарело и на данный момент не поддерживается в Уровень 3-го уровня клавиатуры polyfill. Это означает, что ключевые и char свойства в событии keypress могут иметь случайные значения. Я работаю над устранением этой проблемы для обратной совместимости.

Ответ 3

Чтобы получить @Orwellophile script для работы с Google Chrome 26.0.1410.65 (в случае с Mac OS X 10.7.5, если это имеет значение), мне пришлось изменить одну строку: его script, похоже, имеет параметры initKeyboardEvent в другом порядке, чем документация MDN для initKeyboardEvent.

Измененная строка выглядит так:

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

Ответ 4

Ну, вышеупомянутые решения действительно работали, также благодаря @dland для подсказки параметра. Вот что я нашел полезным, если вы не можете запустить события в нужном месте.

@Orwellophile script запускает событие в документе. Возможно, прослушиватель событий не всегда зарегистрирован на document. Я изменил последнюю строку на следующую, и теперь она очень много работает каждый раз.

document.activeElement.dispatchEvent(oEvent);

document.activeElement всегда запускает событие в элементе, в котором пользователь в данный момент фокусируется.

Ответ 5

Все вышеперечисленные решения работают, но я обнаружил, что один случай они не будут.

Если используется Dart, код Dart, который использует KeyboardEvents, не будет работать в общем событии.

Вы получите что-то вроде get $keyCode undefined.

после того, как я часами стучал головой, я нашел следующий трюк:

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

} 

Перехватчик Dool-Dart для того, что наше Событие на самом деле является KeyboardEvent, сделал трюк.

Оставив его здесь, для бедного парня, который пытается протестировать приложение Дарт в браузере на основе webkit.