Можно ли программным образом моделировать ключевые события пресса?

Можно ли программным образом моделировать события нажатия клавиш в JavaScript?

Ответ 1

Версия не-jquery, которая работает как в webkit, так и в gecko:

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

Ответ 2

Если вам удобно использовать jQuery 1.3.1:

function simulateKeyPress(character) {
  jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}

$(function() {
  $('body').keypress(function(e) {
    alert(e.which);
  });

  simulateKeyPress("e");
});

Ответ 3

То, что вы можете сделать, это программно запускать слушатели ключевых событий путем запуска ключевых событий. Имеет смысл разрешить это с точки зрения безопасности. Используя эту способность, вы можете применить типичный шаблон наблюдателя. Вы можете назвать этот метод "имитацией".

Ниже приведен пример того, как этого добиться в стандарте W3C DOM вместе с 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...
  }
}

Этот пример адаптирован из: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

В jQuery:

jQuery('input[type=submit][name=btnK]')
  .trigger({
    type: 'keypress',
    which: character.charCodeAt(0 /*the key to trigger*/)      
   });

Но в последнее время [DOM] не существует способа вызвать события, оставляющие браузер-песочницу. И все основные поставщики браузеров будут придерживаться этой концепции безопасности.

Что касается плагинов, таких как Adobe Flash, которые основаны на NPAPI- и позволяют обходить песочницу: это постепенный отказ; Firefox.

Детальное объяснение:

Вы не можете и не должны по соображениям безопасности (как уже указывал Пекка). Вы всегда будете требовать взаимодействия пользователя между ними. Кроме того, представьте, что пользователи браузеров могут подать в суд на пользователей, поскольку различные программные события на клавиатуре приведут к подделке атак.

Смотрите этот пост для альтернатив и более подробной информации. Всегда есть флэш на основе копирования и вставки. Вот элегантный пример. В то же время это свидетельство того, почему Интернет отодвигается от поставщиков плагинов.

В случае политики CORS opt-in применяется аналогичный подход к безопасности для программного доступа к удаленному контенту.

Ответ:
В нормальных условиях нет возможности программно запускать клавиши ввода в изолированной среде браузера.

Итог: я не говорю, что это не будет возможно в будущем, при специальных режимах браузера и/или привилегиях для достижения конечной цели игры или подобного пользовательского опыта. Однако до входа в такие режимы у пользователя будут запрашиваться разрешения и риски, аналогичные модели полноэкранного API.

Полезно: в контексте KeyCodes этот инструмент и сопоставление кодов ключей пригодятся.

Раскрытие: ответ основан на ответе здесь.

Ответ 4

Вы можете отправлять события клавиатуры на элемент вроде этого

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

Ответ 5

Вы можете использовать dispatchEvent():

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

Я не тестировал это, но он был адаптирован из кода в документации dispatchEvent(). Вы, вероятно, захотите прочитать это, а также документы для createEvent() и initKeyEvent().

Ответ 6

Вы можете создавать и отправлять события клавиатуры, и они будут запускать соответствующие зарегистрированные обработчики событий, однако они не будут выводить текст, если отправлено, например, в элемент ввода.

Чтобы полностью имитировать ввод текста, вам нужно создать последовательность событий клавиатуры и явно задать текст элемента ввода. Последовательность событий зависит от того, насколько тщательно вы хотите имитировать ввод текста.

Простейшая форма:

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

Ответ 7

Основываясь на ответе от alex2k8, здесь пересмотренная версия, которая работает во всех браузерах, поддерживаемых jQuery (проблема заключалась в отсутствии аргументов в jQuery.event.trigger, что легко забыть при использовании этой внутренней функции).

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

Вы можете даже нажать это дальше и позволить ему не только имитировать событие, но и фактически вставлять символ (если это элемент ввода), однако при попытке сделать это есть много кросс-браузеров. Лучше использовать более сложный плагин, например SendKeys.

Ответ 8

В некоторых случаях событие keypress не может обеспечить требуемую функциональность. Из документов Mozilla мы видим, что эта функция устарела:

Эта функция больше не рекомендуется. Хотя некоторые браузеры могут по-прежнему поддерживать его, он, возможно, уже удален из соответствующих веб-стандартов, может быть в процессе удаления или может храниться только в целях совместимости. Избегайте его использования и обновляйте существующий код, если это возможно; см. таблицу совместимости внизу этой страницы, чтобы принять решение. Имейте в виду, что эта функция может перестать работать в любое время.

Таким образом, поскольку событие keypress объединено из двух последовательно запускаемых событий keydown и следующих за ним keyup для одного и того же ключа, просто генерируйте события по одному:

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

Ответ 9

Для желающих вы можете, на самом деле, повторно воссоздать события ввода с клавиатуры. Чтобы изменить текст во входной области (перемещать курсоры или страницу через входной символ), вы должны внимательно следить за моделью событий DOM: http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents

Модель должна делать:

  • focus (отправлено на DOM с заданным набором)

Затем для каждого символа:

  • keydown (отправлено на DOM)
  • beforeinput (отправляется в цель, если это текстовая область или вход)
  • keypress (отправлено на DOM)
  • (отправляется в цель, если ее текстовая область или вход)
  • изменить (отправлено в цель, если ее выбрать)
  • keyup (отправлено на DOM)

Затем, необязательно для большинства:

  • размытие (отправлено на DOM с заданным набором)

Это фактически изменяет текст на странице с помощью javascript (без изменения инструкций значения) и соответствующим образом отсылает слушателей/обработчиков javascript. Если вы испортите последовательность, javascript не будет срабатывать в соответствующем порядке, текст в поле ввода не изменится, выбор не изменится или курсор не переместится в следующее пространство в текстовой области.

К сожалению, код был написан для работодателя под NDA, поэтому я не могу его разделить, но это определенно возможно, но вы должны воссоздать весь ключевой ввод "стек" для каждого элемента в правильном порядке.

Ответ 10

Этот подход поддерживает кросс-браузер, изменяя значение кода ключа. Источник

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

Ответ 11

просто используйте 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 хотите имитировать ctrl + z

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

Ответ 12

Вот библиотека, которая действительно помогает: https://cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js

Я не знаю, откуда он пришел, но это полезно. Он добавляет метод .simulate() к window.KeyEvent, поэтому вы используете его просто с KeyEvent.simulate(0, 13) для моделирования enter или KeyEvent.simulate(81, 81) для 'Q'.

Я получил его на https://github.com/ccampbell/mousetrap/tree/master/tests.

Ответ 13

Это сработало для меня, и оно имитирует keyup для моей textaera. если вы хотите, чтобы на всей странице просто поместили KeySimulation() на <body> как этот <body onmousemove="KeySimulation()"> или если не onmousemove то onmouseover работает onmouseover или onload.

<script>
function KeySimulation()
{
var e = document.createEvent("KeyboardEvent");
if (e.initKeyboardEvent) {  // Chrome, IE
    e.initKeyboardEvent("keyup", true, true, document.defaultView, "Enter", 0, "", false, "");
} else { // FireFox
    e.initKeyEvent("keyup", true, true, document.defaultView, false, false, false, false, 13, 0);
}
document.getElementById("MyTextArea").dispatchEvent(e);
}
</script>

<input type="button" onclick="KeySimulation();" value=" Key Simulation " />
<textarea id="MyTextArea" rows="15" cols="30"></textarea>

Ответ 14

Вот решение, которое работает в Chrome и Chromium (тестировали только эти платформы). Кажется, у Chrome есть некоторая ошибка или собственный подход к обработке ключевых кодов, поэтому это свойство нужно добавить отдельно к 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);
}

Ответ 15

Единственный ванильный парень веб-инспектора Javascript, готовый для консоли в копировании + вставке (этот парень уже привлекателен для большинства разработчиков, поэтому не пытайтесь его подтекстировать - он должен быть одиноким.. гребным)

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

Ответ 16

Вот что мне удалось найти:

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)

Ответ 17

Я знаю, что вопрос требует javascript способ имитации нажатия клавиш. Но для тех, кто ищет способ сделать jQuery:

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

Ответ 18

как только пользователь нажмет клавишу, о которой идет речь, вы можете сохранить ссылку на нее и использовать ее на любом другом HTML-элементе:

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>

Ответ 19

Собственный JavaScript с поддержкой TypeScript:

Введите keyCode или любое другое свойство, которое вы используете, и приведите его к KeyboardEventInit.

пример

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

Ответ 20

Важная часть для того, чтобы заставить это работать, - осознать, что charCode, keyCode и which являются всеми устаревшими методами. Поэтому, если код, обрабатывающий событие нажатия клавиши, использует любое из этих трех, он получит поддельный ответ (например, по умолчанию 0).

Пока вы получаете доступ к событию нажатия клавиши не устаревшим методом, таким как key, вы должны быть в порядке.

Для завершения я добавил основной код Javascript для запуска события:

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

Ответ 21

Вы должны использовать некоторую JS-библиотеку с поддержкой для переноса модели событий DOM. Оттуда вы можете запускать и тестировать своих обработчиков.