Question

How to remove duplicate from addEventListener.

I have site which uses ajax to populate different divs when user makes certain calls. I also have a Javascript function which grabs all the links and make an addEventListener so that I can filter the url and if the user clicked on certain links give an alert. Below is my Javascript function which creates the addEventListener:

function supportFunction() {
   var myFunction = function(e) { 
     var regExp = new RegExp('//'+location.hostname+'($|/)');
     var href = this.href; 

     if (regExp.test(href)) {
       e.preventDefault();
       alert('same domain link');
     } 
   }
   var links = document.querySelectorAll('a');

   for (var i = 0; i < links.length; i++) {
     links[i].addEventListener('click', myFunction);
   }
}

The problem I am facing is, as some of the content gets populated using ajax after the supportfunction() is called, if any links are there in the newly populated content it wont be added to the addEventListener. I tried calling the supportfunction whenever an ajax call is made but in that case duplicates are added to eventlistener. That is, if someone clicks on the same domain link they will get 2 alerts, and some case 3-4 alert depending upon how many time the supportfunction() is called.

I guess I explained, what my problem is. Let me know if you want more explanation about the problem.

I tried googleing for an answer and found this link http://dean.edwards.name/weblog/2005/10/add-event/ but couldn't figure out how to use it in my case.

Note : I am looking for a pure Javascript solution not a jQuery solution. (I hope I am not demanding here :) )

Was it helpful?

Solution

You expect that every link be event-binded to only once. You can make a flag to mark if it has been event-binded. so the code is as below.

function supportFunction() {
   var myFunction = function(e) { 
       var regExp = new RegExp('//'+location.hostname+'($|/)');
       var href = this.href; 
       if (regExp.test(href)) {
           e.preventDefault(); 
           alert('same domain link'); } 
   }
   var links = document.querySelectorAll('a');
   for (var i = 0, len = links.length; i < len; i++) {
       var link = links[i];
       // make sure add-event only once
       if(!link.getAttribute('data-added')) {
           link.setAttribute('data-added', 1);
           link.addEventListener('click', myFunction); 
       }
   }
}

OTHER TIPS

If you are only adding one listener and there are no others, you can do:;

links[i].onclick = myFunction;

and run the function every time you add elements. That way if there is a listener already on the link, it will be replaced by myFunction. Or you could do:

if (!links[i].onclick) {
  links[i].onclick = myFunction;
}

but delegation is likely the best solution: put a click listener on a parent of all the subject links (maybe a div) and test the event target (W3C DOM model) or srcElement (IE model) to see if it came from a link you care about.

Related MDN article: event.target.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top