Запустить все события браузера с помощью dispatchEvent

Я подумываю о создании инструмента, который преобразует все события браузера .click() или jQuery) в стандартную форму.

Стандартная форма: HTMLElement.dispatchEvent(new Event(eventType, eventInitDict))

Например, я хочу изменить HTMLElement.click() в HTMLElement.dispatchEvent(new Event("click", {"bubbles": true, ...})) для всех событий.

Мой вопрос:

  1. Есть ли полное сопоставление событий с этой стандартной формой, и если да, документировано ли это где-нибудь?
  2. Есть ли какие-либо события, которые могут быть запущены, которые не могут быть преобразованы в эту стандартную форму?
  3. Делает ли jQuery что-то необычное, если бы я не смог сделать это преобразование?

Крайне важно, чтобы я полностью преобразовал все события в этот формат... Никто не может быть сэкономлен!

Спасибо!


Почему я пытаюсь это сделать?

Я пытаюсь захватить все события, запущенные расширением Chrome. Чтобы сделать это, я решил изменить скрипт содержимого расширений перед его внедрением на страницу (мне не нужны фоновые страницы или всплывающие страницы), чтобы все инициируемые события были "помечены" как происходящие из расширения (это будет быть добавленным к eventInitDict в приведенных выше примерах. Я модифицирую Chromium, чтобы сделать это.


PS. Я не мог придумать лучшего названия вопроса, но если он у вас есть, пожалуйста, дайте мне знать / измените его.

1 ответ

Решение

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

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

Обычно в ответе SO рекомендуется помещать весь соответствующий текст в ответ, в данном случае из-за количества доступных событий я не собираюсь этого делать. Вы можете найти подробный список событий DOM здесь (MDN)

Теперь, к счастью для вас, события могут быть записаны независимо от того, что их вызывает. Ниже JQuery, скорее всего, запускает события DOM, хотя, поскольку я не смотрел на источник JQuery, я не могу сказать наверняка.

При добавлении прослушивателей событий вы захотите передать булево значение true для useCapture в функции addEventListener.

target.addEventListener(type, listener, useCapture);

Дальнейшая документация по addEventListener здесь

Вероятно, вы захотите объявить массив событий JSON, который вы хотите захватить, или статический массив в своем коде, чтобы вы могли поддерживать список событий, которые вы хотите захватить.

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

что-то вроде следующего

var eventList = ['click', 'keydown'];
for(var i = 0;i < eventList.length; i++) {
    var eventName = eventList[i];
    document.addEventListener(eventName, function (evt) {
        var selector = getElementSelector(evt.target); // where getElementSelector will be a function that returns an id, css path or xpath selector.
        var captured = { eventName: eventName, selector: selector };
    });
}

Чтобы вызвать захваченное событие, вы можете сделать следующее, предполагая, что вы используете структуру объекта выше

var eventObject = { eventName: 'click', selector: '#targetId'};
var target = document.querySelector(eventObject.selector);
var event = new Event(eventName, {
    view: window,
    bubbles: true,
    cancelable: true
});
target.dispatchEvent(event);

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

"Стандартной" формы нового события будет недостаточно. Некоторые события имеют разные словари инициализации, которые будут игнорироваться обычным событием, если свойства не являются стандартными для события, и именно поэтому вы должны создать экземпляр правильного типа объекта, например, новый MouseEvent, новый KeyboardEvent. и т.п.

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

Это не маленькая задача в любом случае.

Другие вопросы по тегам