Bagaimana untuk menemukan acara pendengar pada DOM node ketika debugging atau dari kode JavaScript?

Saya memiliki sebuah halaman di mana beberapa acara pendengar yang melekat pada kotak input dan pilih kotak. Apakah ada cara untuk mengetahui hal mana pendengar mengamati tertentu DOM node dan untuk acara apa?

Acara yang terpasang menggunakan:

  1. Prototipe's Acara.mengamati;
  2. DOM's addEventListener;
  3. Sebagai atribut elemen elemen.onclick.
Mengomentari pertanyaan (2)
Larutan

Jika anda hanya perlu untuk memeriksa apa yang's terjadi di sebuah halaman, anda bisa mencoba Visual bookmarklet.

Update: Visual Event 2 tersedia;

Komentar (13)

Hal ini tergantung pada bagaimana peristiwa yang terpasang. Untuk ilustrasi kira kami memiliki berikut klik handler:

var handler = function() { alert('clicked!') };

Kami're akan melampirkan itu untuk elemen kami menggunakan metode yang berbeda, beberapa yang memungkinkan inspeksi dan beberapa yang don't.

Metode A) single event handler

element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"

Metode B) beberapa event handler

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

Metode C): jQuery

$(element).click(handler);
  • 1.3.x

// periksa var clickEvents = $(elemen).data("peristiwa").klik; jQuery.masing-masing(clickEvents, fungsi(key, value) { alert(nilai) // tanda "function() { alert('diklik!') " })

  • 1.4.x (toko handler di dalam objek)

// periksa var clickEvents = $(elemen).data("peristiwa").klik; jQuery.masing-masing(clickEvents, fungsi(tombol, handlerObj) { alert(handlerObj.handler) // tanda "function() { alert('diklik!') " // tersedia juga: handlerObj.jenis, handlerObj.namespace })

(Lihat jQuery.fn.data dan jQuery.data)

Metode D): Prototipe (berantakan)

$(element).observe('click', handler);
  • 1.5.x

// periksa Peristiwa.pengamat.masing-masing(function(item) { if(item[0] == element) { alert(item2) // tanda "function() { alert('diklik!') " } })

  • 1.6 untuk 1.6.0.3, inklusif (punya sangat sulit di sini)

// memeriksa. "_eventId" untuk < 1.6.0.3 sementara // "_prototypeEventID" diperkenalkan di 1.6.0.3 var clickEvents = Event.cache[elemen._eventId || (elemen._prototypeEventID|| [])[0]].klik; clickEvents.masing-masing(fungsi(wrapper){ alert(wrapper.handler) // tanda "function() { alert('diklik!') " })

  • 1.6.1 (sedikit lebih baik)

// periksa var clickEvents = elemen.getStorage().mendapatkan('prototype_event_registry').mendapatkan('klik'); clickEvents.masing-masing(fungsi(wrapper){ alert(wrapper.handler) // tanda "function() { alert('diklik!') " })

Komentar (8)

Chrome, Firefox, Vivaldi dan Safari mendukung getEventListeners(domElement) di Alat Pengembang konsol.

Untuk sebagian besar keperluan debugging, ini bisa digunakan.

Di bawah ini adalah referensi yang sangat baik untuk menggunakannya: https://developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners

Komentar (9)

WebKit Inspektur di Chrome atau Safari browser sekarang ini. Ini akan menampilkan acara pendengar untuk elemen DOM ketika anda pilih dalam unsur-Unsur pane.

Komentar (3)

Hal ini dimungkinkan untuk membuat daftar semua hal pendengar dalam JavaScript: It's tidak sulit, anda hanya perlu untuk hack prototipe's metode elemen HTML (sebelum menambahkan pendengar).

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

Sekarang setiap elemen anchor (a) akan memiliki lastListenerInfo properti yang berisi semua pendengarnya. Dan bahkan bekerja untuk menghapus pendengar dengan fungsi anonim.

Komentar (8)

Gunakan getEventListeners di Google Chrome:

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));
Komentar (3)

(Menulis ulang jawaban dari pertanyaan ini]1 sejak itu's relevan di sini.)

Ketika debugging, jika anda hanya ingin melihat acara ini, saya sarankan baik...

  1. Visual
  2. Yang unsur-Unsur ** bagian dari Chrome's Alat Pengembang: pilih elemen dan mencari "Pendengar Event" di kanan bawah (mirip di Firefox)

Jika anda ingin menggunakan kejadian-kejadian dalam kode anda, dan anda menggunakan jQuery sebelum versi 1.8, anda dapat menggunakan:

$(selector).data("events")

untuk mendapatkan acara. Sebagai versi 1.8, menggunakan .data("peristiwa") dihentikan (lihat bug ini tiket). Anda dapat menggunakan:

$._data(element, "events")

Contoh lain: Menulis semua peristiwa klik pada link tertentu untuk konsol:

var $myLink = $('a.myClass');
console.log($._data($myLink[0], "events").click);

(lihat http://jsfiddle.net/HmsQC/ untuk contoh kerja)

Sayangnya, menggunakan $._data ini tidak dianjurkan kecuali untuk debugging karena itu adalah internal jQuery struktur, dan bisa berubah di masa depan pers. Sayangnya aku tahu tidak ada yang lain berarti mudah untuk mengakses acara.

Komentar (2)

1: Prototipe.mengamati menggunakan Elemen.addEventListener (lihat source code)

2: Anda dapat mengganti Elemen.addEventListener untuk mengingat menambahkan pendengar (handy properti EventListenerList telah dihapus dari DOM3 spec proposal). Menjalankan kode ini sebelum acara terlampir:

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

Baca semua peristiwa dengan:

var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

Dan don't lupa untuk mengganti Elemen.removeEventListener untuk menghapus acara dari kebiasaan Elemen.eventListenerList.

3: Elemen.onclick property membutuhkan perawatan khusus, berikut ini:

if(someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4: don't melupakan Elemen.onclick konten atribut: ini adalah dua hal yang berbeda:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

Jadi, anda perlu untuk menangani hal itu, terlalu:

var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);

Visual Acara bookmarklet (yang disebutkan dalam jawaban yang paling populer) hanya mencuri perpustakaan kustom handler cache:

ternyata bahwa ada tidak ada metode standar yang disediakan oleh W3C direkomendasikan DOM antarmuka untuk mencari tahu apa yang terjadi pendengar melekat pada elemen tertentu. Sementara ini mungkin tampak seperti sebuah pengawasan, ada usulan untuk memasukkan properti yang disebut eventListenerList ke tingkat 3 DOM spesifikasi, tapi sayangnya telah dihapus di kemudian draft. Seperti kita dipaksa untuk memandang individu perpustakaan Javascript, yang biasanya mempertahankan cache terpasang peristiwa (sehingga mereka nantinya dapat dihapus dan melakukan bermanfaat lainnya abstraksi).

dengan demikian, dalam rangka untuk Visual Acara untuk acara acara, ia harus mampu mengurai informasi acara keluar dari perpustakaan Javascript.

Elemen utama yang dapat dipertanyakan (yaitu karena ada beberapa DOM fitur khusus seperti live koleksi, yang tidak dapat dikodekan dalam JS), tetapi memberikan eventListenerList dukungan native dan bekerja di Chrome, Firefox dan Opera (doesn't bekerja di IE7).

Komentar (0)

Anda bisa membungkus asli DOM metode untuk mengelola acara pendengar dengan menempatkan ini di atas <head>:

<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

Komentar (2)

Firefox developer tools sekarang ini. Peristiwa-peristiwa ditampilkan dengan mengklik "ev" tombol di sebelah kanan dari masing-masing elemen's tampilan, termasuk jQuery dan DOM peristiwa.

Komentar (2)

Jika anda memiliki Firebug, anda dapat menggunakan konsol.dir(object atau array) untuk mencetak sebuah pohon yang bagus di console log dari setiap JavaScript skalar, array, atau objek.

Coba:

console.dir(clickEvents);

atau

console.dir(window);
Komentar (1)

Sepenuhnya bekerja solusi berdasarkan [jawaban oleh Jan Turon][1] - berperilaku seperti getEventListeners() dari konsol:

(Ada sedikit bug dengan duplikat. Itu doesn't istirahat banyak pula.)


(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
Komentar (5)

Opera 12 (bukan Chrome terbaru mesin Webkit-based) Belt memiliki ini untuk sementara dan lebih jelas ditampilkan dalam struktur DOM. Menurut pendapat saya itu adalah segala debugger dan merupakan satu-satunya alasan yang tersisa mengapa saya masih menggunakan Opera 12 versi (tidak ada v13, v14 versi dan v15 berbasis Webkit kekurangan Capung masih)

Komentar (0)

Saya baru-baru ini bekerja sama dengan peristiwa dan ingin melihat/mengontrol semua acara di halaman. Setelah melihat solusi yang mungkin, saya've memutuskan untuk pergi dengan cara saya sendiri dan membuat sistem untuk memantau peristiwa-peristiwa. Jadi, saya melakukan tiga hal.

Pertama, saya membutuhkan sebuah wadah untuk semua acara pendengar dalam halaman: yang's'EventListenersobjek. Ia memiliki tiga metode yang berguna:add(),hapus(), danget()`.

Berikutnya, saya membuat sebuah EventListener objek untuk menyimpan informasi yang diperlukan untuk acara tersebut, yaitu: target, jenis, balik, pilihan, useCapture, wantsUntrusted, dan menambahkan metode hapus() untuk menghapus pendengar.

Terakhir, saya diperpanjang asli addEventListener() dan removeEventListener() metode untuk membuat mereka bekerja dengan benda-benda I've dibuat (EventListener dan EventListeners).

Penggunaan:

var bodyClickEvent = document.body.addEventListener("click", function () {
    console.log("body click");
});

// bodyClickEvent.remove();

addEventListener() menciptakan EventListener objek, menambahkan ke EventListeners kembali EventListener objek, sehingga dapat dihapus kemudian.

EventListeners.get() dapat digunakan untuk melihat pendengar di halaman. Ia menerima sebuah EventTarget atau string (jenis kegiatan).

// EventListeners.get(document.body);
// EventListeners.get("click");

Demo

Let's mengatakan kami ingin tahu setiap pendengar acara ini di halaman saat ini. Kami bisa melakukan itu (dengan asumsi anda're menggunakan script manager ekstensi, Tampermonkey dalam kasus ini). Script berikut ini:

// ==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);

Dan ketika kita daftar semua pendengar, ia mengatakan ada 299 acara pendengar. Ada "tampaknya" untuk beberapa duplikat, tapi aku don't tahu jika mereka're benar-benar duplikat. Tidak setiap jenis peristiwa diduplikasi, sehingga semua orang "duplikat" mungkin individu pendengar.

Kode dapat ditemukan di repository. saya didn't ingin posting di sini karena itu's agak panjang.


Update: Ini doesn't tampaknya bekerja dengan jQuery. Ketika saya memeriksa EventListener, saya melihat bahwa callback

function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}

Saya percaya ini termasuk jQuery, dan tidak aktual callback. jQuery toko-toko yang sebenarnya di balik sifat-sifat EventTarget:

$(document.body).click(function () {
    console.log("jquery click");
});

Untuk menghapus pendengar acara, sebenarnya callback kebutuhan untuk diteruskan ke removeEventListener() metode. Jadi dalam rangka untuk membuat ini bekerja dengan jQuery, perlu modifikasi lebih lanjut. Saya bisa memperbaikinya di masa depan.

Komentar (1)

Prototipe 1.7.1 cara

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];
}
Komentar (0)

Saya mencoba untuk melakukan itu di jQuery 2.1, dan dengan "$().klik() -> $(elemen).data("peristiwa").klik;" metode itu doesn't bekerja.

Saya menyadari bahwa hanya $._data() fungsi yang bekerja dalam kasus saya :

    $(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>


Komentar (0)

perubahan fungsi ini akan memungkinkan anda untuk log pendengar menambahkan:

EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent

baca sisa dari pendengar dengan

console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));
Komentar (0)