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

首先,这里是由W3C标准定义的事件types列表。 (这个列表基于HTML5标准中定义的onevent属性,我假设有几十个其他的事件types,但是这个列表足够长。)

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

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

如果这是不可能的,是否至less有可能定义一个事件处理程序,当任何事件冒泡到DOM树的根(这是document对象或window对象 – 都应该工作)时调用? (我知道可以通过编程来停止冒泡,但是我会在页面上使用这个事件处理程序,在其他任何元素上都没有定义其他处理程序。)(另外,我相信有些事件不会冒泡,但是我们忽略它们为了这个论点的缘故。)

我知道我可以做到这一点(使用jQuery):

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

但这对我来说是一个相当不受欢迎的解决scheme。

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

此外, Firebug能够logging事件 ,但我希望能够以编程方式(通过JavaScript)捕捉事件,而不是让他们只是login控制台。

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

您可以迭代DOM元素的所有属性,并select与/on(.*)/模式匹配的模式(例如onclick或onmousemove):

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

我非常怀疑有一种方法可以在Firefox中执行此操作。 看看Firebug的源代码 (特别是attachAllListeners方法),事实certificate,迭代事件名称列表显然是一种方式,但这并不能解决冒泡问题。

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

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

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

祝你好运。

对于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:'); })();