いくつかのイベントリスナーが入力ボックスと選択ボックスに接続されているページがあります。どのイベントリスナーが特定のDOMノードを監視しているのか、またどのイベントを監視しているのかを調べる方法はありますか?
イベントは以下を使用して添付されます。
Event.observe
;addEventListener
。element.onclick
。ページで何が起こっているのかを調べるだけの場合は、 ビジュアルイベント のブックマークレットを試してください。
更新 : ビジュアルイベント2 available;
イベントがどのように関連付けられているかによって異なります。説明のために、次のクリックハンドラがあるとします。
var handler = function() { alert('clicked!') };
検査を可能にするものとそうでないものを使用して、さまざまな方法を使用して要素に添付します。
方法A)シングルイベントハンドラ
element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"
方法B)複数のイベントハンドラ
if(element.addEventListener) { // DOM standard
element.addEventListener('click', handler, false)
} else if(element.attachEvent) { // IE
element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers
方法C):jQuery
$(element).click(handler);
1.3.x
// inspect
var clickEvents = $(element).data("events").click;
jQuery.each(clickEvents, function(key, value) {
alert(value) // alerts "function() { alert('clicked!') }"
})
1.4.x(ハンドラをオブジェクト内に格納)
// inspect
var clickEvents = $(element).data("events").click;
jQuery.each(clickEvents, function(key, handlerObj) {
alert(handlerObj.handler) // alerts "function() { alert('clicked!') }"
// also available: handlerObj.type, handlerObj.namespace
})
( jQuery.fn.data
および jQuery.data
を参照)
方法D):プロトタイプ(乱雑)
$(element).observe('click', handler);
1.5.x
// inspect
Event.observers.each(function(item) {
if(item[0] == element) {
alert(item[2]) // alerts "function() { alert('clicked!') }"
}
})
1.6〜1.6.0.3、包括的(ここでは非常に困難になりました)
// inspect. "_eventId" is for < 1.6.0.3 while
// "_prototypeEventID" was introduced in 1.6.0.3
var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
clickEvents.each(function(wrapper){
alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
})
1.6.1(やや良い)
// inspect
var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
clickEvents.each(function(wrapper){
alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
})
Chrome、Firefox、Vivaldi、およびSafariは、Developer ToolsコンソールでgetEventListeners(domElement)
をサポートしています。
デバッグ目的の大部分では、これを使用できます。
以下はそれを使用するための非常に良い参考資料です: https://developers.google.com/chrome-developer-tools/docs/commandline-api#geteventlistenersobject
ChromeまたはSafariブラウザのWebKit Inspectorはこれを行います。 [要素]ペインでDOM要素を選択すると、DOM要素のイベントリスナーが表示されます。
すべてのイベントリスナを一覧表示することは可能です JavaScriptで:それほど難しくありません。 HTML要素のprototype
メソッドをハックするだけです( before リスナーの追加)。
function reportIn(e){
var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
console.log(a)
}
HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;
HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
this.realAddEventListener(a,reportIn,c);
this.realAddEventListener(a,b,c);
if(!this.lastListenerInfo){ this.lastListenerInfo = new Array()};
this.lastListenerInfo.Push({a : a, b : b , c : c});
};
すべてのアンカー要素(a
)は、そのすべてのリスナーを含むlastListenerInfo
プロパティを持ちます。匿名関数を使ってリスナーを削除することもできます。
Google Chrome :でgetEventListenerを使用します。
getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));
(これはここで関連しているので、 this question から答えを書き換えてください。)
デバッグ時にイベントを見たいだけなら、どちらかをお勧めします。
自分のコードでイベントを使用したいが、jQuery バージョン1.8より前を使用している場合は、次のように使用できます。
$(selector).data("events")
イベントを取得する。 バージョン1.8以降、.data( "events")の使用は廃止されました ( このバグチケット を参照)。あなたが使用することができます:
$._data(element, "events")
別の例:コンソールへの特定のリンク上のすべてのクリックイベントを書く:
var $myLink = $('a.myClass');
console.log($._data($myLink[0], "events").click);
(実用的な例は http://jsfiddle.net/HmsQC/ をご覧ください)
残念ながら、 $ ._ dataを使用することは、jQueryの内部構造であり将来のリリースで変更される可能性があるため、デバッグを除いて推奨されません 。残念ながら、他の簡単な方法でイベントにアクセスする方法はありません。
1:Prototype.observe
はElement.addEventListenerを使用します( ソースコードを参照 )
2:追加されたリスナーを記憶するためにElement.addEventListener
をオーバーライドすることができます(便利なプロパティEventListenerList
はDOM3仕様の提案から削除されました)。イベントが添付される前にこのコードを実行してください。
(function() {
Element.prototype._addEventListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = function(a,b,c) {
this._addEventListener(a,b,c);
if(!this.eventListenerList) this.eventListenerList = {};
if(!this.eventListenerList[a]) this.eventListenerList[a] = [];
this.eventListenerList[a].Push(b);
};
})();
次の方法ですべてのイベントを読む。
var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
alert("I listen to this function: "+f.toString());
});
そして、カスタムのElement.removeEventListener
からイベントを削除するためにElement.eventListenerList
をオーバーライドすることを忘れないでください。
3:Element.onclick
プロパティは特別な注意が必要です。
if(someElement.onclick)
alert("I also listen tho this: "+someElement.onclick.toString());
4:Element.onclick
のcontent属性を忘れないでください。これらは2つの異なることです。
someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute
だからあなたもそれを処理する必要があります:
var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);
Visual Eventのブックマークレット(最も一般的な回答で言及されています)は、カスタムライブラリハンドラのキャッシュを盗むだけです。
どのイベントリスナーが特定の要素にアタッチされているかを調べるためにW3Cが推奨するDOMインターフェースによって提供される標準的な方法はないことがわかりました。これは見落としに見えるかもしれませんが、eventListenerListというプロパティをレベル3のDOM仕様に含める提案がありましたが、残念ながら後のドラフトでは削除されました。そのため、私たちは個々のJavascriptライブラリを調べることを余儀なくされています。それらは通常添付されたイベントのキャッシュを保持しています(そのためそれらは後で削除され他の有用な抽象化を実行できます).
そのため、Visual Eventがイベントを表示するには、Javascriptライブラリからイベント情報を解析できなければなりません。
要素のオーバーライドは疑わしいかもしれません(つまり、ライブコレクションのような、JSではコーディングできないDOM固有の機能がいくつかあるからです)が、eventListenerListのサポートはネイティブであり、Chrome、Firefox、およびOperaでは機能します(IE7では機能しません)。 ).
これをあなたの<head>
の先頭に置くことで、イベントリスナーを管理するためのネイティブDOMメソッドをラップすることができます。
<script>
(function(w){
var originalAdd = w.addEventListener;
w.addEventListener = function(){
// add your own stuff here to debug
return originalAdd.apply(this, arguments);
};
var originalRemove = w.removeEventListener;
w.removeEventListener = function(){
// add your own stuff here to debug
return originalRemove.apply(this, arguments);
};
})(window);
</script>
H/T @ les2
Firebug がある場合は、JavaScriptのスカラ、配列、またはオブジェクトのコンソールログにNiceツリーを出力するためにconsole.dir(object or array)
を使用できます。
試してください:
console.dir(clickEvents);
または
console.dir(window);
Jan Turonによる回答に基づいた完全に機能する解決策 - は、コンソールからのgetEventListeners()
のように動作します。
(重複したものには少しバグがあります。とにかく壊れることはほとんどありません。)
(function() {
Element.prototype._addEventListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = function(a,b,c) {
if(c==undefined)
c=false;
this._addEventListener(a,b,c);
if(!this.eventListenerList)
this.eventListenerList = {};
if(!this.eventListenerList[a])
this.eventListenerList[a] = [];
//this.removeEventListener(a,b,c); // TODO - handle duplicates..
this.eventListenerList[a].Push({listener:b,useCapture:c});
};
Element.prototype.getEventListeners = function(a){
if(!this.eventListenerList)
this.eventListenerList = {};
if(a==undefined)
return this.eventListenerList;
return this.eventListenerList[a];
};
Element.prototype.clearEventListeners = function(a){
if(!this.eventListenerList)
this.eventListenerList = {};
if(a==undefined){
for(var x in (this.getEventListeners())) this.clearEventListeners(x);
return;
}
var el = this.getEventListeners(a);
if(el==undefined)
return;
for(var i = el.length - 1; i >= 0; --i) {
var ev = el[i];
this.removeEventListener(a, ev.listener, ev.useCapture);
}
};
Element.prototype._removeEventListener = Element.prototype.removeEventListener;
Element.prototype.removeEventListener = function(a,b,c) {
if(c==undefined)
c=false;
this._removeEventListener(a,b,c);
if(!this.eventListenerList)
this.eventListenerList = {};
if(!this.eventListenerList[a])
this.eventListenerList[a] = [];
// Find the event in the list
for(var i=0;i<this.eventListenerList[a].length;i++){
if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
this.eventListenerList[a].splice(i, 1);
break;
}
}
if(this.eventListenerList[a].length==0)
delete this.eventListenerList[a];
};
})();
使用法:
someElement.getEventListeners([name])
- nameが設定されている場合、イベントリスナのリストを返します、そのイベントのリスナの配列を返します
someElement.clearEventListeners([name])
- nameが設定されている場合、全てのイベントリスナーを削除します、そのイベントのリスナーのみ削除します
Opera 12(最新のChrome Webkitエンジンベースではありません) Dragonfly はしばらくこれを持っていて、明らかにDOM構造で表示されています。私の意見では、それは優れたデバッガであり、私がまだOpera 12ベースのバージョンを使用している唯一の理由です(v13、v14バージョンとv15 WebkitベースはまだDragonflyを欠いている)
プロトタイプ1.7.1の方法
function get_element_registry(element) {
var cache = Event.cache;
if(element === window) return 0;
if(typeof element._prototypeUID === 'undefined') {
element._prototypeUID = Element.Storage.UID++;
}
var uid = element._prototypeUID;
if(!cache[uid]) cache[uid] = {element: element};
return cache[uid];
}
NicejQuery Eventsエクステンションが存在します。
(トピック ソース )
私はjQuery 2.1でそれをやろうとしています、そして、 "$().click() -> $(element).data("events").click;
"メソッドでそれはうまくいきません。
私の場合は、$。data()関数だけが機能することに気付きました。
$(document).ready(function(){
var node = $('body');
// Bind 3 events to body click
node.click(function(e) { alert('hello'); })
.click(function(e) { alert('bye'); })
.click(fun_1);
// Inspect the events of body
var events = $._data(node[0], "events").click;
var ev1 = events[0].handler // -> function(e) { alert('hello')
var ev2 = events[1].handler // -> function(e) { alert('bye')
var ev3 = events[2].handler // -> function fun_1()
$('body')
.append('<p> Event1 = ' + eval(ev1).toString() + '</p>')
.append('<p> Event2 = ' + eval(ev2).toString() + '</p>')
.append('<p> Event3 = ' + eval(ev3).toString() + '</p>');
});
function fun_1() {
var txt = 'text del missatge';
alert(txt);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
</body>
これらの機能を変更すると、追加されたリスナーをログに記録できます。
EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent
リスナーの残りの部分を
console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));
私は最近イベントに取り組んでいて、ページ内のすべてのイベントを表示/制御したいと思いました。考えられる解決策を検討した結果、私は自分のやり方でイベントを監視するためのカスタムシステムを作成することにしました。それで、私は3つのことをしました。
まず、ページ内のすべてのイベントリスナー用のコンテナが必要でした。それがEventListeners
オブジェクトです。 add()
、remove()
、get()
の3つの便利なメソッドがあります。
次に、イベントに必要な情報(EventListener
、target
、type
、callback
、options
、useCapture
)を保持するwantsUntrusted
オブジェクトを作成し、リスナーを削除するためのメソッドremove()
を追加しました。
最後に、私が作成したオブジェクト(EventListener
およびEventListeners
)と連携するように、ネイティブのaddEventListener()
およびremoveEventListener()
メソッドを拡張しました。
使用法:
var bodyClickEvent = document.body.addEventListener("click", function () {
console.log("body click");
});
// bodyClickEvent.remove();
addEventListener()
はEventListener
オブジェクトを作成し、それをEventListeners
に追加してEventListener
オブジェクトを返すので、後で削除できます。
EventListeners.get()
はページ内のリスナーを見るために使用することができます。 EventTarget
または文字列(イベントタイプ)を受け入れます。
// EventListeners.get(document.body);
// EventListeners.get("click");
デモ
この現在のページのすべてのイベントリスナーを知りたいとしましょう。私たちはそれをすることができます(あなたがスクリプトマネージャ拡張、この場合はTampermonkeyを使っていると仮定して)。次のスクリプトはこれを行います。
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @include https://stackoverflow.com/*
// @grant none
// ==/UserScript==
(function() {
fetch("https://raw.githubusercontent.com/akinuri/js-lib/master/EventListener.js")
.then(function (response) {
return response.text();
})
.then(function (text) {
eval(text);
window.EventListeners = EventListeners;
});
})(window);
そして、すべてのリスナーをリストすると、299のイベントリスナーがいることがわかります。いくつかの重複があるようですが、それらが本当に重複しているかどうかはわかりません。すべてのイベントタイプが重複しているわけではないので、それらの「重複している」すべてが個々のリスナーになる可能性があります。
コードは私の repositoryにあります。 かなり長いのでここには投稿したくありませんでした。
更新: これはjQueryではうまくいかないようです。 EventListenerを調べると、コールバックは次のようになっています。
function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}
私はこれがjQueryに属していると信じており、実際のコールバックではありません。 jQueryはEventTargetのプロパティに実際のコールバックを格納します。
$(document.body).click(function () {
console.log("jquery click");
});
イベントリスナを削除するには、実際のコールバックをremoveEventListener()
メソッドに渡す必要があります。そのため、これをjQueryで機能させるためには、さらに変更が必要です。私は将来それを修正するかもしれません。