Jump to content

Creating a Custom Filter Selector with jQuery

0
  adfm's Photo
Posted Feb 04 2010 02:19 PM

In this excerpt from jQuery Cookbook the authors explain how to create a custom fiter selector to target specific elements when using the jQuery Javascript library.


If you need a reusable filter to target specific elements based on their characteristics, you can extend jQuery’s selector expressions under the jQuery.expr[':'] object; this is an alias for Sizzle.selectors.filters. Each new filter expression is defined as a property of this object, like so:

jQuery.expr[':'].newFilter = function(elem, index, match){

	return true; // Return true/false like you would on the filter() method

};

The function will be run on all elements in the current collection and needs to return true (to keep the element in the collection) or false (to remove the element from the collection). Three bits of information are passed to this function: the element in question, the index of this element among the entire collection, and a match array returned from a regular expression match that contains important information for the more complex expressions.

For example, you might want to target all elements that have a certain property. This filter matches all elements that are displayed inline:

jQuery.expr[':'].inline = function(elem) {

	return jQuery(elem).css('display') === 'inline';

};

Now that we have created a custom selector, we can use it in any selector expression:

// E.g. #1

jQuery('div a:inline').css('color', 'red');

// E.g. #2

jQuery('span').filter(':not(:inline)').css('color', 'blue')

jQuery’s custom selectors (:radio, :hidden, etc.) are created in this way.

As mentioned, the third parameter passed to your filter function is an array returned from a regular expression match that jQuery performs on the selector string. This match is especially useful if you want to create a filter expression that accepts parameters. Let’s say that we want to create a selector that queries for data held by jQuery:

jQuery('span').data('something', 123);



// We want to be able to do this:

jQuery('*:data(something,123)');

The purpose of the selector would be to select all elements that have had data attached to them via jQuery’s data() method—it specifically targets elements with a datakey of something, equal to the number 123.

The proposed filter (:data) could be created as follows:

jQuery.expr[':'].data = function(elem, index, m) {

 	

	// Remove ":data(" and the trailing ")" from

	// the match, as these parts aren't needed:

	m[0] = m[0].replace(/:data\(|\)$/g, '');

 	

	var regex = new RegExp('([\'"]?)((?:\\\\\\1|.)+?)\\1(,|$)', 'g'),

 	// Retrieve data key:

 	key = regex.exec( m[0] )[2],

 	// Retrieve data value to test against:

 	val = regex.exec( m[0] );

	

	if (val) {

 	val = val[2];

	}

	

	// If a value was passed then we test for it, otherwise

	// we test that the value evaluates to true:

	return val ? jQuery(elem).data(key) == val : !!jQuery(elem).data(key);

 

};

The reason for such a complex regular expression is that we want to make it as flexible as possible. The new selector can be used in a number of different ways:

// As we originally mused (above):

jQuery('div:data("something",123)');



// Check if 'something' is a "truthy" value

jQuery('div:data(something)');



// With or without (inner) quotes:

jQuery('div:data(something, "something else")');

Now we have a totally new way of querying data held by jQuery on an element.

If you ever want to add more than one new selector at the same time, it’s best to use jQuery’s extend() method:

jQuery.extend(jQuery.expr[':'], {

	newFilter1 : function(elem, index, match){

 	// Return true or false.

	},

	newFilter2 : function(elem, index, match){

 	// Return true or false.

	},

	newFilter3 : function(elem, index, match){

 	// Return true or false.

	}

});
jQuery Cookbook

Learn more about this topic from jQuery Cookbook.

Getting started with the jQuery library is easy, but it can take years to fully realize its breadth and depth; jQuery Cookbook shortens the learning curve considerably. You'll learn patterns and practices from 19 leading developers who use jQuery for everything from integrating simple components into websites and applications to developing complex, high-performance user interfaces. The recipes start with the basics and then move into practical use cases with tested solutions to common web development hurdles.

See what you'll learn


Tags:
0 Subscribe


0 Replies