I wrote the following code for a project that I’m working on:
var clicky_tracking = [
['related-searches', 'Related Searches'],
['related-stories', 'Related Stories'],
['more-videos', 'More Videos'],
['web-headlines', 'Publication']
];
for (var x = 0, length_x = clicky_tracking.length; x < length_x; x++) {
links = document.getElementById(clicky_tracking[x][0])
.getElementsByTagName('a');
for (var y = 0, length_y = links.length; y < length_y; y++) {
links[y].onclick = (function(name, url) {
return function() {
clicky.log(url, name, 'outbound');
};
}(clicky_tracking[x][1], links[y].href));
}
}
What I’m trying to do is:
- define a two-dimensional array, with each instance the inner arrays containing two elements: an
idattribute value (e.g., “related-searches”) and a corresponding description (e.g., “Related Searches”); - for each of the inner arrays, find the element in the
documentwith the correspondingidattribute, and then gather a collection of all<a>elements (hyperlinks) within it; - loop through that collection and attach an
onclickhandler to each hyperlink, which should callclicky.log, passing in as parameters the description that corresponds to theid(e.g., “Related Searches” for theid“related-searches”) and the value of thehrefattribute for the<a>element that was clicked.
Hopefully that wasn’t thoroughly confusing! The code may be more self-explanatory than that.
I believe that what I’ve implemented here is a closure, but JSLint complains:
http://img.skitch.com/20100526-k1trfr6tpj64iamm8r4jf5rbru.png
So, my questions are:
- How can I refactor this code to make JSLint agreeable? Or, better yet, is there a best-practices way to do this that I’m missing, regardless of what JSLint thinks?
- Should I rely on event delegation instead? That is, attaching
onclickevent handlers to thedocumentelements with theidattributes in my arrays, and then looking atevent.target? I’ve done that once before and understand the theory, but I’m very hazy on the details, and would appreciate some guidance on what that would look like – assuming this is a viable approach.
Thanks very much for any help!
Delegation is a better approach. JSLint complains because you are creating a new function each time within the loop. However, instead of setting up a single event on the document to listen for all click events, I would rather setup a handler on all individual root elements that have id’s assigned to them. A single handler can be reused for all these elements.
Register the above handler with each root element.
Also to avoid searching through the array, I’ve changed
clicky_trackingfrom array to an object for easier keyed access.