是否可以以编程方式捕获浏览器中页面上的所有事件?

问题描述 投票:46回答:5

首先,这里是W3C标准定义的事件类型列表。 (此列表基于HTML5标准中定义的onevent属性。我假设有许多其他事件类型,但此列表足够长。)

  • 流产
  • 打印后
  • beforeprint
  • beforeunload
  • 模糊
  • 可以玩
  • canplaythrough
  • 更改
  • 点击
  • 上下文菜单
  • 复制
  • cue change
  • DBLCLICK
  • DOMContentLoaded
  • 拖动
  • 轴承
  • 的dragenter
  • dragleave
  • 的dragover
  • 的dragstart
  • 下降
  • durationchange
  • 清空
  • 结束
  • 错误
  • 焦点
  • 专注于
  • 事件的内容
  • formchange
  • 的formInput
  • hashchange
  • 输入
  • 无效
  • KEYDOWN
  • 按键
  • KEYUP
  • 加载
  • loadeddata
  • 等待loadedmetadata
  • loadstart
  • 信息
  • 鼠标按下
  • 的mouseenter
  • 鼠标离开
  • 鼠标移动
  • 鼠标移开
  • 鼠标移到
  • 鼠标松开
  • 鼠标滚轮
  • 离线
  • 线上
  • pagehide
  • pageshow
  • 暂停
  • 播放
  • popstate
  • 进展
  • ratechange
  • readystatechange
  • 准备
  • 重启
  • 调整
  • 滚动
  • seeked
  • 选择
  • 节目
  • 停滞
  • 存储
  • 提交
  • 暂停
  • timeupdate
  • 解开
  • 卸下
  • volumechange
  • 等候

现在,是否可以定义在页面上任何元素上最初发生任何事件时调用的全局事件处理程序? (在这种情况下,我不想计算元素上发生的事件,因为它们从后代元素冒出来 - 这就是我写“最初发生”的原因。)

如果那是不可能的,那么至少可以定义一个事件处理程序,当任何事件冒泡到DOM树的根目录(它是document对象或window对象 - 两者都应该工作)时调用它吗? (我知道可以以编程方式停止冒泡,但我会在没有其他任何元素上定义的其他处理程序的页面上使用此事件处理程序。)(另外,我相信某些事件不会冒泡,但让我们忽略这些为了这个论点的例子。)

我知道我可以这样做(使用jQuery):

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

但这对我来说是一个相当不理想的解决方案。

顺便说一句我不需要跨浏览器的解决方案。如果它只在一个浏览器中工作,我很好。

另外,Firebug is able to log events,但我希望能够以编程方式(通过JavaScript)捕获事件,而不是让它们只是登录控制台。

javascript events dom browser
5个回答
19
投票
/*

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

}

7
投票

您可以遍历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(' '))

5
投票

我非常怀疑在Firefox中有一种方法可以做到这一点。看看Firebug's source code(特别是attachAllListeners方法),结果显示迭代事件名称列表显然是要走的路,但这并不能解决冒泡问题。


2
投票

似乎没有任何“简单方法”可以做到这一点。

我的想法:你知道哪些是所有事件,所以你可以处理每个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");
}

这是“直观的想法”,但似乎并不是非常有效。但是,它应该工作。

祝好运。


-1
投票

对于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:');
})();
© www.soinside.com 2019 - 2024. All rights reserved.