まず、W3C標準で定義されているイベントタイプのリストを次に示します。 (このリストは、HTML5標準で定義されているonevent属性に基づいています。他にも数十のイベントタイプがあると想定していますが、このリストは十分に長いものです。)
今、anyイベントがページ上のany要素で最初に発生したときに呼び出されるグローバルイベントハンドラーを定義することは可能ですか? (この場合、要素で発生したイベントは子孫要素からバブルアップしたためカウントしません-だから「元々発生する」と書きました。)
それが不可能な場合、少なくともanyイベントがDOMツリーのルート(document
オブジェクトまたはwindow
オブジェクト-両方とも機能するはずです)? (プログラムでバブリングを停止できることは知っていますが、他の要素に他のハンドラが定義されていないページでこのイベントハンドラを使用します。)この議論のためのケース。)
私はこれを行うことができることを知っています(jQueryを使用して):
$(document).bind('abort afterprint beforeprint beforeunload etc.', function() {
// handle event
});
しかし、それは私にとってかなり望ましくない解決策でしょう。
ところで、クロスブラウザソリューションは必要ありません。 1つのブラウザでのみ動作する場合は、問題ありません。
また、 Firebugはイベントをログに記録できます ですが、単にコンソールにログを記録するのではなく、プログラムで(JavaScriptを介して)イベントをキャッチできるようにしたいと思います。
/*
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要素のすべてのプロパティを反復処理し、/ 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
メソッド)を見ると、イベント名のリストを反復処理することが明らかに道であることがわかりますが、これはバブルの問題を解決しません。
それを行うための「簡単な方法」はないようです。
私の考え:どのイベントがすべてであるかはわかっているので、すべての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");
}
これは「直感的なアイデア」ですが、あまり効率的ではないようです。ただし、動作するはずです。
幸運を。
パーティーに少し遅れましたが、私はここで他の人に役立つかもしれない何かを作りました。
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);
}
})
})
}
}
MDN Webサイトの最新バージョンの場合:
(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:');
})();