aaronbnb
aaronbnb

Reputation: 69

How to use JavaScript to find all elements which have event listeners?

<div id="test1" onlick="testFunction()" role="button" tabindex="0">A custom button</div>

<div id="test2" role="button" tabindex="0">Another custom button</div>

<button class="test3">A final button</button>

<ul id="test4">
  <li>Cookies</li>
  <li>Cream</li>
</ul>

<div id="test5">Just a div, not clickable </div>
document.getElementById('test2').addEventListener('keypress', function() { 
    console.log("foo");
  }
)
document.querySelectorAll('.test3').forEach(item => {
    item.addEventListener('click', event => {
      console.log("bar");
    })
  })

document.getElementById('test4').onclick = function(event) {
  let target = event.target;

  if (target.tagName != 'li') {
     event.target.addClass('highlight');
  }
};

I'm interested in using JavaScript (preferably no jQuery or other library) to find all DOM elements which have events attached to them. There are many ways to find elements that have HTML event attributes like #test1. But it is unclear how to find elements that have events added via a script like #test2 or .test3 or the <ul id="test4">. A correct answer would return an array with four elements.

An even better response would additionally find the elements using event delegation like the <li> but it seems like that may not be possible.

EDIT: querySelectorAll() now selects the test3 class instead of test3 tag

Upvotes: 1

Views: 3333

Answers (3)

Rounin
Rounin

Reputation: 29511

You can extend EventTarget.addEventListener so that any element to which you add an EventListener then declares that EventListener in an HTML5 custom data-* attribute in its own markup.

When declared, the custom attribute will look like this:

data-eventlisteners="['mouseover:showButton','mouseout:fadeButton','click:animateButton']"

Once one or more elements have such custom attributes, you may query the elements via JavaScript.

e.g.

  1. document.querySelectorAll('[data-eventlisteners]') will reveal which elements on the page have EventListeners attached

  2. document.querySelectorAll('[data-eventlisteners*=","]') will reveal which elements on the page have more than one EventListener attached

  3. document.querySelectorAll('[data-eventlisteners*="mouseover:"]') will reveal which elements on the page have a mouseover EventListener attached

  4. document.querySelectorAll('[data-eventlisteners*="click:"][data-eventlisteners*="mouseout:"]') will reveal which elements on the page have both a click and a mouseout EventListener attached

etc.


Working Example:

const declareEventListeners = () => {

  EventTarget.prototype._addEventListener = EventTarget.prototype.addEventListener;

  EventTarget.prototype.addEventListener = function(eventType, eventFunction, eventOptions) {
  
    // REINSTATE ORIGINAL FUNCTIONALITY FOR addEventListener() METHOD
    let _eventOptions = (eventOptions === undefined) ? false : eventOptions;
    this._addEventListener(eventType, eventFunction, _eventOptions);
   
    // THEN, IF EVENTTARGET IS NOT WINDOW OR DOCUMENT
    if (this.nodeType === 1) {
      let eventAction = eventFunction.name || 'anonymousFunction';
      let eventListenerLabel = `${eventType}:${eventAction}`;
      let eventListenerLabelsArray = (this.dataset.eventlisteners) ? JSON.parse(this.dataset.eventlisteners.replaceAll( "'", '"')) : [];
      eventListenerLabelsArray.push(eventListenerLabel);
      let eventListenerLabelsString = JSON.stringify(eventListenerLabelsArray).replaceAll('"', "'");
      this.dataset.eventlisteners = eventListenerLabelsString;
    }
  }
};

const clickMe = (e) => {
  e.target.classList.toggle('circle');
}

const mouseoverMe = (e) => {
  e.target.style.setProperty('background-color', 'rgb(255, 127, 0)');
}

const mouseoutMe = (e) => {
  e.target.removeAttribute('style');
}

const logMarkup = () => {
  
  console.log(document.querySelector('section').innerHTML);
}

declareEventListeners();
document.querySelector('.div1').addEventListener('click', clickMe, false);
document.querySelector('.div2').addEventListener('mouseover', mouseoverMe, false);
document.querySelector('.div2').addEventListener('mouseout', mouseoutMe, false);
logMarkup();
.div1,
.div2 {
  float: left;
  width: 100px;
  height: 100px;
  line-height: 50px;
  margin-right: 12px;
  text-align: center;
  color: rgb(255, 255, 255);
  background-color: rgb(255, 0, 0);
}

.div1 {
  line-height: 100px;
  cursor: pointer;
}

.div1.circle {
  border-radius: 50%;
}
<section>
  <div class="div1">click</div>
  <div class="div2">mouseover<br />mouseout</div>
</section>

You'll see in the example above:

  • .div1 reveals itself as having a single EventListener which listens for click and fires the function clickMe()

  • .div2 reveals itself as having two EventListeners which listen for mouseover and mouseout, which, respectively, fire the functions mouseoverMe() and mouseoutMe()


N.B. I've modified the script above quite a lot but it was originally inspired by:

Upvotes: 1

ehab
ehab

Reputation: 8064

There is no native javascript api that allows you to find event listeners that were added using eventTarget.addEventListener.

You can still get events added using the onclick attribute whether the attribute was set using javascript or inline through html - in this case u are not getting the event listener, but you are getting the value of the onclickattribute which are two different things.

Javascript offers no api for doing so, because dom elements can be removed while event listeners still referencing them.

If you want to keep track of event listeners attached to dom elements you have to do that yourself.

Apart from that chrome has getEventListeners command line api which works with dom elements, however it is a developer tools command line api and so it only works when called from developer tools.

Upvotes: 2

Pranav Rustagi
Pranav Rustagi

Reputation: 2721

There is no way, to do so directly with JavaScript.

However, you can use this approach and add an attribute while binding events to the elements.

document.getElementById('test2').addEventListener('keypress', function() { 
    this.setAttribute("event", "yes");
    console.log("foo");
  }
)
document.querySelectorAll('test3').forEach(item => {
    item.addEventListener('click', event => {
      this.setAttribute("event", "yes");
      console.log("bar");
    })
  })

document.getElementById('test4').onclick = function(event) {
  let target = event.target;
  this.setAttribute("event", "yes");

  if (target.tagName != 'li') {
     event.target.addClass('highlight');
  }
};

And this is how you can find the elements having events bind to them :

var eventElements = document.querySelectorAll("[event='yes']");
var countEventElements = eventElements.length;

Upvotes: 0

Related Questions