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




events dom (14)

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

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

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

Answers

अच्छा jQuery घटनाक्रम एक्सटेंशन मौजूद है:

(विषय source )


जावास्क्रिप्ट में सभी ईवेंट श्रोताओं को सूचीबद्ध करना संभव है : यह मुश्किल नहीं है; आपको बस 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 संपत्ति होगी जिसमें इसके सभी श्रोताओं को शामिल किया जाएगा। और यह अज्ञात कार्यों के साथ श्रोताओं को हटाने के लिए भी काम करता है।


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

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(domElement) प्राप्त करते हैं।

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

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


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


क्रोम या सफारी ब्राउज़र में वेबकिट इंस्पेक्टर अब यह करता है। जब आप एलिमेंट फलक में इसे चुनते हैं तो यह ईवेंट श्रोताओं को एक DOM तत्व के लिए प्रदर्शित करेगा।


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


Google क्रोम में getEventListeners का उपयोग करें:

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

मैं इसे 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>


जन 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]) - सभी ईवेंट श्रोताओं को हटा दें, अगर नाम सेट है तो केवल उस ईवेंट के लिए श्रोताओं को हटा दें


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


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

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


प्रोटोटाइप 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];
}

तो, मैंने अपने स्वयं के समाधान को बर्तन में फेंकने का फैसला किया। यहाँ एक कामकाजी पहेली है । ध्यान दें कि यह केवल बहुत ही आधुनिक ब्राउज़रों पर चलता है।

यह क्या उपयोग करता है

यह कार्यान्वयन बहुत आधुनिक है - इसमें एक (बहुत) आधुनिक ब्राउज़र और उपयोगकर्ता की दो नई तकनीकें आवश्यक हैं:

  • MutationObservers को डोम में परिवर्तन का पता लगाने के लिए (ईवेंट श्रोताओं का भी उपयोग किया जाता है)
  • ऑब्जेक्ट में परिवर्तन का पता लगाने और डोम को सूचित करने के लिए Object.observeखतरे, चूंकि यह उत्तर लिखा गया है, ओओएमएस्क्रिप्ट टीसी द्वारा ओओ पर चर्चा और निर्णय लिया गया है, एक पॉलीफिल पर विचार करें

यह काम किस प्रकार करता है

  • तत्व पर, एक domAttribute:objAttribute मैपिंग - उदाहरण के लिए bind='textContent:name'
  • डेटा बाइंड फ़ंक्शन में पढ़ें। तत्व और वस्तु दोनों में परिवर्तनों का निरीक्षण करें।
  • जब कोई परिवर्तन होता है - प्रासंगिक तत्व को अद्यतन करें।

समाधान

यहां dataBind फ़ंक्शन है, ध्यान दें कि यह कोड की केवल 20 पंक्तियां है और यह छोटा हो सकता है:

function dataBind(domElement, obj) {    
    var bind = domElement.getAttribute("bind").split(":");
    var domAttr = bind[0].trim(); // the attribute on the DOM element
    var itemAttr = bind[1].trim(); // the attribute the object

    // when the object changes - update the DOM
    Object.observe(obj, function (change) {
        domElement[domAttr] = obj[itemAttr]; 
    });
    // when the dom changes - update the object
    new MutationObserver(updateObj).observe(domElement, { 
        attributes: true,
        childList: true,
        characterData: true
    });
    domElement.addEventListener("keyup", updateObj);
    domElement.addEventListener("click",updateObj);
    function updateObj(){
        obj[itemAttr] = domElement[domAttr];   
    }
    // start the cycle by taking the attribute from the object and updating it.
    domElement[domAttr] = obj[itemAttr]; 
}

यहां कुछ उपयोग है:

HTML:

<div id='projection' bind='textContent:name'></div>
<input type='text' id='textView' bind='value:name' />

जावास्क्रिप्ट:

var obj = {
    name: "Benjamin"
};
var el = document.getElementById("textView");
dataBind(el, obj);
var field = document.getElementById("projection");
dataBind(field,obj);

यहाँ एक कामकाजी पहेली है । ध्यान दें कि यह समाधान बहुत सामान्य है। Object.observe और उत्परिवर्तन पर्यवेक्षक shimming उपलब्ध है।







javascript events dom