views:

137

answers:

3

What is the best way to keep track of eventListener functions on DOM elements? Should I add a property to the element which references the function like this:

var elem = document.getElementsByTagName( 'p' )[0];
function clickFn(){};
elem.listeners = { click: [clickFn, function(){}] };
elem.addEventListener( 'click', function(e){ clickFn(e); }, false );

Or should I store it in my own variable in my code like below:

var elem = document.getElementsByTagName( 'p' )[0];
function clickFn(){};
// Using window for the sake of brevity, otherwise I wouldn't =D
// DOM elements and their listeners are referenced here in a paired array
window.listeners = [elem, { click: [clickFn, function(){}] }];
elem.addEventListener( 'click', function(e){ clickFn(e); }, false );

Obviously the second method would be less obtrusive, but it seems it could get intensive iterating through all those possibilities.

Which is the best way and why? Is there a better way?

A: 

There is a better way, called "jQuery" (or any other js framework that deals with event handlers in an obtrusive way).

Since you tagged this question to jQuery as well, it's my best answer.

Kind Regards

--Andy

jAndy
A: 

This is a slightly odd question, considering it's also tagged as "jQuery".

In jQuery, event handlers are made extremely simple. Your first example can be rewritten as the following:

function clickFn(){};

$("p:first").click(function(e) {
  clickFn(e)
});

That, or I've wildly misunderstood the question.

GlenCrawford
A: 

As the other answers have mentioned, since you tagged this question with jQuery, it doesn't make sense that you're trying to add and track events with plain JavaScript like this. In addition, the way you seem to be doing it doesn't really track anything, because you're manually adding a function reference to your listeners properties, independent of actually assigning them to event handlers on the elements. When you do that there's no way to ensure that the ones you're "tracking" are actually what's going to be called when the event fires.

If you're insistent on avoiding jQuery, here's an example of how you could add multiple handlers to multiple events and keep track of which functions have been assigned to handle which events later:

function addTrackedListener(element, type, handler) {
  if (!element.trackedEvents) {
    element.trackedEvents = {};
  }

  if (!element.trackedEvents[type]) {
    element.trackedEvents[type] = [];
  }

  element.trackedEvents[type].push(handler);

  element[type] = function () {
    handleAllEvents(element.trackedEvents[type]);
  };
}


function handleAllEvents(events) {
  for (var i = 0, l = events.length; i < l; i++) {
    events[i]();
  }
}

Example usage:

// grab some element
var div = document.getElementById('test');

// add a click handler to it
addTrackedListener(div, 'onclick', function() {
  console.log('first handler');
});

// add another click handler to it
addTrackedListener(div, 'onclick', function() {
  console.log('second handler');
});

When the click event fires, you'd see this in your console:

first handler
second handler

And if you inspect div.trackedEvents, you'll see a property for each type of event, whose value will be an array of all the functions that will execute when that event is triggered.

Jimmy Cuadra