How to create a custom filter selector with jQuery

A little jQuery trick I learned recently, was how to create a reusable, custom filter to target specific elements based on their characteristics.

I was kind of surprised that I hadn’t heard of this before, so thought I’d jot it down here, in case it is of use to anyone else.

A quick refresher

By way of a refresher, the filter() method in jQuery reduces the set of matched elements to those that match the selector or pass the function’s test.

For example, you can apply a specific style to evenly indexed items in a list, thus:

$("li").filter(":even").css("background-color", "red");

or, using the shorthand version:

$("li:even").css("background-color", "red");

Filters are handy for a whole bunch of things, such as selecting hidden elements:

$("div:hidden").show();

Or selecting an element’s first child:

$("div.myClass div:first-child").fadeIn("slow");

And you can even filter against a function rather than a selector. For each element, if the function returns true (or a “truthy” value), the element will be included in the filtered set; otherwise, it will be excluded:

$("li").filter(function(index) {
  return index % 2 === 0;
}).addClass("green");

Rolling your own

You can extend jQuery’s selector expressions under the jQuery.expr[':'] object (an alias for Sizzle.selectors.filters). Each new filter expression is defined as a property of this object, like so:

jQuery.expr[':'].myFilter = function(elem, index, match){
  // Return true or false
};

The function will be run on all elements in the current collection. Returning true will keep the element in the collection, whereas false will remove it.

As you can see, the function receives three parameters: the element in question, the index of this element in the collection, and a match array which is useful for more complex expressions.

You can read more about creating custom filters in the following links:

A proper example

Armed with this new and dangerous knowledge, I decided to make a filter to select all green elements on a page.

Admittedly, this is rather pointless, but hey, you never know …

The filter itself looks like this:

jQuery.expr[':'].green = function(elem, index, match) {
  return $(elem).css("background-color") === "rgb(0, 128, 0)";
};

You might notice that I am using the rgb value to determine the colour. This works great in Chrome and Firefox, but YMMV using IE.

You can apply it to all of the elements on a page thus:

$(":green")

or to a subset of elements (which is a better idea performance-wise), thus:

$("#myDiv:green")

And finally, here’s a working demo to play around with:

I hope this proved useful for people. If you have any questions, I’d be glad to hear them in the comments.

If you made it this far then you might consider following me on Twitter:

I'm on Twitter:

Categories