I have always missed a traverse function in jQuery, and I thinking that there might be one but I missed it. Say we have the following markup:
<ul>
<li><a href="#">Foo</a></li>
<li><a href="#">Bar</a></li>
<li><a href="#">John</a></li>
<li><a href="#">Doe</a></li>
</ul>
Now, if I want to add an active class to the anchor I clicked and deactivate the others, I would normally have to do this:
$('a').click(function() {
$(this).addClass('active')
.parent()
.siblings()
.find('a.active')
.removeClass('active');
});
But what I want is to do is this:
var relation = function() {
return $(this).parent().siblings().find('a.active');
};
$('a').click(function() {
$(this).addClass('active').find(relation).removeClass('active');
});
See the difference? Now, find doesn’t take a function as argument, so I wrote something like this:
$.fn.traverse = function(fn) {
return $.isFunction(fn) ? fn.call(this) : this;
};
As an example, this simple method makes it possible to create an "activate" plugin that lets the author specify the relationship to the deactivations:
$.fn.activate = function(fn) {
return this.each(function() {
$(this).addClass('active').traverse(fn || function() {
return $(this).siblings();
}).removeClass('active');
});
});
And use it like this:
$('a').activate(function() {
return $(this).parent().siblings().find('.active');
});
// or
$('a').activate(function() {
return $(this).closest('ul').find('a.active').not(this);
});
// or
$('li').activate();
This will do the job. But my question is that there really should be something like this included in jQuery somewhere, no? I was looking at .map but it doesn’t work that way.
$("ul a").each(function() { doStuff(this); });?