Lampirkan event listener ke node menggunakan addEventListener

106

Saya telah melihat pertanyaan-pertanyaan ini:

namun tidak satupun dari mereka menjawab bagaimana mendapatkan daftar event listener yang dilampirkan ke sebuah node menggunakan addEventListener, tanpa memodifikasi addEventListenerprototipe sebelum event listener dibuat.

VisualEvent tidak menampilkan semua pendengar acara (yang khusus iPhone) dan saya ingin melakukan ini (agak) secara terprogram.

Tyilo
sumber
"agak terprogram" dan fakta bahwa jawaban yang diterima untuk pertanyaan ini adalah fitur devtools menjadikan ini duplikat dari pertanyaan yang tercantum. Bagi mereka yang mencari solusi JS, jawabannya adalah "tidak ada"
Nickolay

Jawaban:

135

Chrome DevTools, Safari Inspector, dan Firebug mendukung getEventListeners (node) .

getEventListeners (dokumen)

NVI
sumber
6
Saya ingin mencatat bahwa metode getEventListeners tidak mendukung versi Firefox 35.
MURATSPLAT
Ini mungkin tidak berfungsi di Firefox, tetapi sekali lagi pengembang berkembang di beberapa browser / Ini pasti MEMBANTU jika seseorang perlu memodifikasi situs yang ada ... BANYAK!
JasonXA
1
Bukan itu Firefox 69.
Vitaly Zdanevich
65

Tidak boleh.

Satu-satunya cara untuk mendapatkan daftar semua event listener yang dilampirkan ke node adalah dengan mencegat panggilan lampiran listener.

DOM4 addEventListener

Says

Tambahkan event listener ke daftar terkait event listener dengan tipe set ke tipe, listener diatur ke listener, dan set capture ke capture, kecuali sudah ada event listener dalam daftar itu dengan tipe, listener, dan capture yang sama.

Artinya pendengar acara ditambahkan ke "daftar pendengar acara". Itu saja. Tidak ada gagasan tentang apa daftar ini seharusnya atau bagaimana Anda harus mengaksesnya.

Raynos
sumber
12
Adakah peluang untuk memberikan beberapa pembenaran atau alasan mengapa itu harus bekerja seperti ini? Jelas browser mengetahui semua pendengarnya.
Darth Egregious
3
@ user973810: Bagaimana Anda ingin dia membenarkan hal ini? API DOM tidak menyediakan cara untuk melakukannya dan tidak ada cara non-standar untuk melakukannya di browser saat ini. Tentang mengapa ini terjadi, saya tidak begitu tahu. Sepertinya hal yang wajar untuk ingin dilakukan.
Tim Down
Saya telah melihat beberapa utas tentang menambahkan API ke DOM untuk ini.
Raynos
@TimDown bantuan edit. Melihat bahwa tidak ada spesifikasi untuk sesuatu seperti "getEventListeners" membenarkan mengapa hal seperti itu tidak ada.
Darth Egregious
24

Karena tidak ada cara asli untuk melakukan ini, Berikut adalah solusi yang tidak terlalu mengganggu yang saya temukan (jangan tambahkan metode prototipe 'lama'):

var ListenerTracker=new function(){
    var is_active=false;
    // listener tracking datas
    var _elements_  =[];
    var _listeners_ =[];
    this.init=function(){
        if(!is_active){//avoid duplicate call
            intercep_events_listeners();
        }
        is_active=true;
    };
    // register individual element an returns its corresponding listeners
    var register_element=function(element){
        if(_elements_.indexOf(element)==-1){
            // NB : split by useCapture to make listener easier to find when removing
            var elt_listeners=[{/*useCapture=false*/},{/*useCapture=true*/}];
            _elements_.push(element);
            _listeners_.push(elt_listeners);
        }
        return _listeners_[_elements_.indexOf(element)];
    };
    var intercep_events_listeners = function(){
        // backup overrided methods
        var _super_={
            "addEventListener"      : HTMLElement.prototype.addEventListener,
            "removeEventListener"   : HTMLElement.prototype.removeEventListener
        };

        Element.prototype["addEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["addEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=useCapture?1:0;

            if(!listeners[useCapture][type])listeners[useCapture][type]=[];
            listeners[useCapture][type].push(listener);
        };
        Element.prototype["removeEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["removeEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=useCapture?1:0;
            if(!listeners[useCapture][type])return;
            var lid = listeners[useCapture][type].indexOf(listener);
            if(lid>-1)listeners[useCapture][type].splice(lid,1);
        };
        Element.prototype["getEventListeners"]=function(type){
            var listeners=register_element(this);
            // convert to listener datas list
            var result=[];
            for(var useCapture=0,list;list=listeners[useCapture];useCapture++){
                if(typeof(type)=="string"){// filtered by type
                    if(list[type]){
                        for(var id in list[type]){
                            result.push({"type":type,"listener":list[type][id],"useCapture":!!useCapture});
                        }
                    }
                }else{// all
                    for(var _type in list){
                        for(var id in list[_type]){
                            result.push({"type":_type,"listener":list[_type][id],"useCapture":!!useCapture});
                        }
                    }
                }
            }
            return result;
        };
    };
}();
ListenerTracker.init();
yorg
sumber
Anda juga harus membuatnya menghalangi pemroses kejadian jendela. Selain itu, ini berfungsi dengan baik!
2

Anda bisa mendapatkan semua kejadian jQuery menggunakan $ ._ data ($ ('[selector]') [0], 'events'); ubah [selector] menjadi apa yang Anda butuhkan.

Ada sebuah plugin yang mengumpulkan semua event yang dilampirkan oleh jQuery yang disebut eventsReport.

Juga saya menulis plugin saya sendiri yang melakukan ini dengan format yang lebih baik.

Tapi bagaimanapun tampaknya kami tidak bisa mengumpulkan acara yang ditambahkan dengan metode addEventListener. Mungkin kita bisa membungkus panggilan addEventListener untuk menyimpan acara yang ditambahkan setelah panggilan bungkus kita.

Tampaknya cara terbaik untuk melihat peristiwa ditambahkan ke elemen dengan alat pengembang.

Tetapi Anda tidak akan melihat acara yang didelegasikan di sana. Jadi di sana kita membutuhkan jQuery eventsReport.

PEMBARUAN: SEKARANG Kita BISA melihat acara yang ditambahkan dengan metode addEventListener LIHAT JAWAB KANAN UNTUK PERTANYAAN INI.

Rantiev
sumber
Ini adalah antarmuka pribadi dan usang & mungkin akan segera hilang jadi jangan mengandalkan itu.
mgol
1
Ya, tapi saat saya menjawab, tidak ada kemampuan seperti itu di alat Dev. Jadi, tidak ada yang bisa dipilih.
Rantiev
@Rantiev sudah usang, bisakah Anda menghapus jawaban itu?
Julio Marins
2

Saya tidak dapat menemukan cara untuk melakukan ini dengan kode, tetapi di Firefox 64 stok, acara dicantumkan di sebelah setiap entitas HTML di Developer Tools Inspector seperti yang tercantum di halaman Periksa Event Listeners MDN dan seperti yang ditunjukkan dalam gambar ini:

screen shot dari FF Inspector

Adam Katz
sumber