javascript डीबगिंग या जावास्क्रिप्ट कोड से जब डीओएम नोड पर ईवेंट श्रोताओं को कैसे ढूंढें?




events dom (11)

( इस प्रश्न से उत्तर को फिर से लिखना क्योंकि यह यहां प्रासंगिक है।)

डीबगिंग करते समय, यदि आप सिर्फ घटनाओं को देखना चाहते हैं, तो मैं या तो अनुशंसा करता हूं ...

  1. दृश्य कार्यक्रम
  2. क्रोम के डेवलपर टूल्स के तत्व अनुभाग: एक तत्व का चयन करें और नीचे दाईं ओर "ईवेंट श्रोताओं" की तलाश करें (फ़ायरफ़ॉक्स में समान)

यदि आप अपने कोड में ईवेंट का उपयोग करना चाहते हैं, और आप संस्करण 1.8 से पहले jQuery का उपयोग कर रहे हैं, तो आप इसका उपयोग कर सकते हैं:

$(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/ देखें)

दुर्भाग्यवश, $ ._ डेटा का उपयोग करके यह डिबगिंग को छोड़कर अनुशंसित नहीं है क्योंकि यह एक आंतरिक jQuery संरचना है, और भविष्य में रिलीज़ में बदल सकता है। दुर्भाग्य से मैं घटनाओं तक पहुंचने के किसी अन्य आसान साधन के बारे में नहीं जानता।

https://code.i-harness.com

मेरे पास एक पृष्ठ है जहां कुछ ईवेंट श्रोताओं इनपुट बॉक्स और चयन बॉक्स से जुड़े हुए हैं। क्या यह पता लगाने का कोई तरीका है कि कौन सा ईवेंट श्रोताओं एक विशेष डोम नोड देख रहे हैं और किस घटना के लिए?

घटनाओं का उपयोग कर संलग्न हैं:

  1. Prototype's Event.observe ;
  2. डोम का addEventListener ;
  3. तत्व विशेषता element.onclick । क्लिक करें।

1: Prototype.observe Element.addEventListener का उपयोग करता है ( स्रोत कोड देखें)

2: आप अतिरिक्त श्रोताओं को याद रखने के लिए Element.addEventListener को ओवरराइड कर सकते हैं (आसान संपत्ति EventListenerList को DOM3 spec प्रस्ताव से हटा दिया गया था)। किसी भी घटना संलग्न होने से पहले इस कोड को चलाएं:

(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.eventListenerList से ईवेंट को निकालने के लिए Element.removeEventListener को ओवरराइड करना न भूलें।

3: Element.onclick संपत्ति को यहां विशेष देखभाल की आवश्यकता है:

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

4: Element.onclick सामग्री विशेषता को न भूलें: ये दो अलग-अलग चीजें हैं:

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

विजुअल इवेंट बुकमार्लेट (सबसे लोकप्रिय उत्तर में उल्लिखित) केवल कस्टम लाइब्रेरी हैंडलर कैश चुराता है:

यह पता चला है कि W3C द्वारा किसी विशेष तत्व से कौन सा ईवेंट श्रोताओं को संलग्न किया गया है, यह जानने के लिए W3C अनुशंसित डीओएम इंटरफ़ेस द्वारा प्रदान की गई कोई मानक विधि नहीं है। हालांकि यह एक निरीक्षण प्रतीत हो सकता है, इवेंट लिस्टनरलिस्ट नामक एक संपत्ति को स्तर 3 डीओएम विनिर्देश में शामिल करने का प्रस्ताव था, लेकिन दुर्भाग्यवश बाद में ड्राफ्ट में हटा दिया गया था। ऐसे में हमें व्यक्तिगत जावास्क्रिप्ट पुस्तकालयों को देखने के लिए मजबूर होना पड़ता है, जो आम तौर पर संलग्न घटनाओं के कैश को बनाए रखते हैं (इसलिए उन्हें बाद में हटाया जा सकता है और अन्य उपयोगी अवशेषों को निष्पादित किया जा सकता है)।

इस प्रकार, विज़ुअल इवेंट को ईवेंट दिखाने के लिए, यह किसी जावास्क्रिप्ट लाइब्रेरी से ईवेंट जानकारी को पार्स करने में सक्षम होना चाहिए।

एलिमेंट ओवरराइडिंग संदिग्ध हो सकती है (यानी क्योंकि लाइव संग्रह जैसे कुछ डीओएम विशिष्ट विशेषताएं हैं, जिन्हें जेएस में कोड नहीं किया जा सकता है), लेकिन यह ईवेंट लिस्टनरलिस्ट समर्थन को मूल रूप से देता है और यह क्रोम, फ़ायरफ़ॉक्स और ओपेरा में काम करता है (आईई 7 में काम नहीं करता है )।


आप ईवेंट श्रोताओं को अपने <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>

एच / टी @ les2


ओपेरा 12 (नवीनतम क्रोम वेबकिट इंजन आधारित नहीं) Dragonfly ने थोड़ी देर के लिए यह किया है और जाहिर है कि डीओएम संरचना में प्रदर्शित किया गया है। मेरी राय में यह एक बेहतर डीबगर है और यही कारण है कि मैं अभी भी ओपेरा 12 आधारित संस्करण का उपयोग क्यों करता हूं (वहां कोई v13, v14 संस्करण नहीं है और v15 वेबकिट आधारित ड्रैगनफ्लाई की कमी है)


क्रोम, फ़ायरफ़ॉक्स, विवाल्डी और सफारी समर्थन उनके डेवलपर टूल्स कंसोल में getEventListeners(domElement) प्राप्त करते हैं।

अधिकांश डिबगिंग उद्देश्यों के लिए, इसका उपयोग किया जा सकता है।

नीचे इसका उपयोग करने के लिए एक बहुत अच्छा संदर्भ है: https://developers.google.com/chrome-developer-tools/docs/commandline-api#geteventlistenersobject


जावास्क्रिप्ट में सभी ईवेंट श्रोताओं को सूचीबद्ध करना संभव है : यह मुश्किल नहीं है; आपको बस HTML तत्वों (श्रोताओं को जोड़ने से पहले ) के prototype की विधि को हैक करना होगा।

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 संपत्ति होगी जिसमें इसके सभी श्रोताओं को शामिल किया जाएगा। और यह अज्ञात कार्यों के साथ श्रोताओं को हटाने के लिए भी काम करता है।


फ़ायरफ़ॉक्स डेवलपर टूल अब यह करता है। ईवेंट प्रत्येक jQuery के प्रदर्शन के दाईं ओर "ev" बटन पर क्लिक करके दिखाए जाते हैं, जिसमें jQuery और DOM ईवेंट शामिल हैं।


मैं इसे jQuery 2.1 में और " $().click() -> $(element).data("events").click; साथ करने की कोशिश कर रहा हूं $().click() -> $(element).data("events").click; " विधि यह काम नहीं करती है।

मुझे एहसास हुआ कि केवल $ ._ डेटा () फ़ंक्शन मेरे मामले में काम करता है:

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


यदि आपको किसी पृष्ठ पर क्या हो रहा है, इसका निरीक्षण करने की आवश्यकता है, तो आप विजुअल इवेंट बुकमार्लेट को आजमा सकते हैं।

अद्यतन : दृश्य घटना 2 उपलब्ध;


यह इस बात पर निर्भर करता है कि घटनाएं कैसे जुड़ी हुई हैं। उदाहरण के लिए हमारे पास निम्नलिखित क्लिक हैंडलर है:

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

हम इसे विभिन्न तरीकों का उपयोग करके हमारे तत्व में संलग्न करने जा रहे हैं, कुछ जो निरीक्षण की अनुमति देते हैं और कुछ जो नहीं करते हैं।

विधि ए) एकल घटना हैंडलर

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

विधि बी) एकाधिक घटना हैंडलर

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

विधि सी): 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.data और jQuery.data देखें)

विधि डी): प्रोटोटाइप (गन्दा)

$(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!') }"
    })
    

जन getEventListeners() द्वारा उत्तर के आधार पर पूरी तरह से काम करने वाला समाधान - कंसोल से 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]) - ईवेंट श्रोताओं की वापसी सूची, अगर नाम उस घटना के लिए श्रोताओं की वापसी सरणी सेट है

someElement.clearEventListeners([name]) - सभी ईवेंट श्रोताओं को हटा दें, अगर नाम सेट है तो केवल उस ईवेंट के लिए श्रोताओं को हटा दें






dom