Подтвердить что ты не робот

Можно ли программно уловить все события на странице в браузере?

Прежде всего, вот список типов событий, которые определены стандартами W3C. (Этот список основан на атрибутах onevent, определенных в стандарте HTML5. Я предполагаю, что существуют десятки других типов событий, но этот список достаточно длинный, как есть.)

  • прерывани
  • afterprint
  • BeforePrint
  • beforeunload
  • Размытие
  • canplay
  • canplaythrough
  • изменить
  • выберите
  • ContextMenu
  • Копия
  • cuechange
  • вырезать
  • DblClick
  • DOMContentLoaded
  • перетащить
  • dragend
  • DragEnter
  • DragLeave
  • DragOver
  • dragstart
  • капля
  • durationchange
  • опустели
  • закончилась
  • Ошибка
  • фокус
  • focusin
  • focusout
  • formchange
  • forminput
  • hashchange
  • вход
  • недействителен
  • KeyDown
  • нажатие клавиши
  • KeyUp
  • нагрузки
  • loadeddata​​li >
  • loadedmetadata​​li >
  • loadstart
  • сообщение
  • MouseDown
  • MouseEnter
  • MouseLeave
  • MouseMove
  • MouseOut
  • Наведите курсор мыши на
  • MouseUp
  • MouseWheel
  • отсутствует
  • онлайн
  • pagehide
  • pageshow
  • паста
  • пауза
  • игра
  • играет
  • popstate
  • прогресс
  • ratechange
  • readystatechange
  • Повторить
  • reset
  • изменить размер
  • прокрутки
  • добившиеся
  • ищет
  • выберите
  • показать
  • застопорился
  • хранения
  • представить
  • приостановить
  • timeupdate
  • Отменить
  • выгрузить
  • volumechange
  • ждет

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

Если это невозможно, возможно ли, по крайней мере, определить обработчик событий, который вызывается, когда событие any пузырится до корня дерева DOM (которое является либо объектом document или объект window - оба должны работать)? (Я знаю, что это можно остановить программным путем, но я использовал бы этот обработчик событий на странице, у которой нет других обработчиков, определенных для любых других элементов.) (Также, я считаю, что некоторые события не пузырятся, но пусть игнорируют эти случаев для этого аргумента.)

Я знаю, что могу это сделать (используя jQuery):

$(document).bind('abort afterprint beforeprint beforeunload etc.', function() {
    // handle event
});

но это было бы довольно нежелательным решением для меня.

btw Мне не нужно решение для кросс-браузера. Если он работает только в одном браузере, я в порядке.

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

4b9b3361

Ответ 1

/*

function getAllEventTypes(){

  if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;

  var types = {};
  $('.standard-table:eq(0) tr').find('td:eq(1)').map(function(){
    var type = $.trim(this.innerText) || 'OtherEvent';
    types[type] = types[type] || [];     
    var event = $.trim(this.previousElementSibling.innerText);
    if(event) types[type].push(event);
  });
  for(var t in types) types[t] = types[t].join(' ');
  return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
}

*/

var DOMEvents = {
UIEvent: "abort DOMActivate error load resize scroll select unload",
ProgressEvent: "abort error load loadend loadstart progress progress timeout",
Event: "abort afterprint beforeprint cached canplay canplaythrough change chargingchange chargingtimechange checking close dischargingtimechange DOMContentLoaded downloading durationchange emptied ended ended error error error error fullscreenchange fullscreenerror input invalid languagechange levelchange loadeddata loadedmetadata noupdate obsolete offline online open open orientationchange pause pointerlockchange pointerlockerror play playing ratechange readystatechange reset seeked seeking stalled submit success suspend timeupdate updateready visibilitychange volumechange waiting",
AnimationEvent: "animationend animationiteration animationstart",
AudioProcessingEvent: "audioprocess",
BeforeUnloadEvent: "beforeunload",
TimeEvent: "beginEvent endEvent repeatEvent",
OtherEvent: "blocked complete upgradeneeded versionchange",
FocusEvent: "blur DOMFocusIn  Unimplemented DOMFocusOut  Unimplemented focus focusin focusout",
MouseEvent: "click contextmenu dblclick mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup show",
SensorEvent: "compassneedscalibration Unimplemented userproximity",
OfflineAudioCompletionEvent: "complete",
CompositionEvent: "compositionend compositionstart compositionupdate",
ClipboardEvent: "copy cut paste",
DeviceLightEvent: "devicelight",
DeviceMotionEvent: "devicemotion",
DeviceOrientationEvent: "deviceorientation",
DeviceProximityEvent: "deviceproximity",
MutationNameEvent: "DOMAttributeNameChanged DOMElementNameChanged",
MutationEvent: "DOMAttrModified DOMCharacterDataModified DOMNodeInserted DOMNodeInsertedIntoDocument DOMNodeRemoved DOMNodeRemovedFromDocument DOMSubtreeModified",
DragEvent: "drag dragend dragenter dragleave dragover dragstart drop",
GamepadEvent: "gamepadconnected gamepaddisconnected",
HashChangeEvent: "hashchange",
KeyboardEvent: "keydown keypress keyup",
MessageEvent: "message message message message",
PageTransitionEvent: "pagehide pageshow",
PopStateEvent: "popstate",
StorageEvent: "storage",
SVGEvent: "SVGAbort SVGError SVGLoad SVGResize SVGScroll SVGUnload",
SVGZoomEvent: "SVGZoom",
TouchEvent: "touchcancel touchend touchenter touchleave touchmove touchstart",
TransitionEvent: "transitionend",
WheelEvent: "wheel"
}

var RecentlyLoggedDOMEventTypes = {};

for(DOMEvent in DOMEvents){

  var DOMEventTypes = DOMEvents[DOMEvent].split(' ');

  DOMEventTypes.filter(function(DOMEventType){
    var DOMEventCategory = DOMEvent + ' '+DOMEventType;  
    document.addEventListener(DOMEventType, function(e){
      if(RecentlyLoggedDOMEventTypes[DOMEventCategory]) return;
      RecentlyLoggedDOMEventTypes[DOMEventCategory] = true;
      setTimeout(function(){ RecentlyLoggedDOMEventTypes[DOMEventCategory] = false }, 5000);
      var isActive = e.target==document.activeElement;
      if(isActive) {
        console.info(DOMEventCategory, 
          ' target=', e.target, 
          ' active=', document.activeElement, 
          ' isActive=', true );
      } else {
        console.log(DOMEventCategory, 
          ' target=', e.target,
          ' active=', document.activeElement, 
          ' isActive=', false );
      }

    }, true);
  });

}

Ответ 2

Вы можете перебирать все свойства элемента dom и выбирать те, которые соответствуют /on (.*)/pattern (например, onclick или onmousemove):

var events = [];
for (var property in element) {
    var match = property.match(/^on(.*)/)
    if (match) { 
        events.push(match[1]);
    }
}
console.log(events.join(' '))

Ответ 3

Я очень сомневаюсь, что есть способ сделать это в Firefox. Глядя на исходный код Firebug (в частности, метод attachAllListeners), выясняется, что итерации по списку имен событий - это, очевидно, путь, но это не решает проблемы пузырей.

Ответ 4

Кажется, что для этого не существует "простого способа".

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

var events =
[   
    "onabort",
    "onafterprint",
    "onbeforeprint",
    "onbeforeunload",
    ...

];

var root = document.body;
var elms = root.childNodes;

for(var i = 0; i < elms.length; i++)
{
    for(var j = 0; j < events.length; j++)
    {
        elms[i][events[j]] = globalHandler;
    }
}

function globalHandler()
{
    alert("Global handler called");
}

Это "интуитивная идея", но, похоже, не очень эффективна. Однако он должен работать.

Удачи.

Ответ 5

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

https://codepen.io/phreaknation/pen/QmJjEa

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

Надеюсь, это поможет

Код класса

class EventSystem {
  constructor(element) {
    this._ = {
      element: null
    }

    return this;
  }

  getAllEventTypes({blacklist = [], whitelist = []} = {}) {
    const events = [];
    for (let property in this._.element) {
      const match = property.match(/^on(.*)/);
      if (match) {
        if ((whitelist.length > 0 ? whitelist.indexOf(match) !== -1 : true) &&
            (blacklist.length > 0 ? blacklist.indexOf(match) === -1 : true)) {
          events.push(match[1]);
        }          
      }
    }
    return events;
  }

  getElementType() {
    return this._.element.tagName.toLowerCase();
  }

  setElement(element) {
    this._.element = element;
    return this;
  }

  applyEvents(events, callback) {
    events.forEach((event) => {
      this._.element.addEventListener(event, (ev) => {
        if (typeof callback === 'function') {
          callback(event, ev);
        }
      })
    })
  }
}

Ответ 6

Для последней версии веб-сайта MDN:

(function getAllEventTypes(){
  if(location.href !='https://developer.mozilla.org/en-US/docs/Web/Events') return;

  var types = {};
  $('.standard-table').map(function(){
    if($(this).find('caption').length > 0){
        var type = $(this).find('caption')[0].innerHTML || 'OtherEvent';
    types[type] = types[type] || [];     
    $(this).find('tbody tr td code a').each(function(el){
        if(this.innerText) types[type].push(this.innerText);
    });
    }
  });
  for(var t in types) types[t] = types[t].join(' ');
  return "var DOMEvents = "+JSON.stringify(types, null, 4).replace(/"(\w+)\":/ig, '$1:');
})();