Posts Tagged ‘Selectors’

A better data selector for jQuery

Posted in 'Code Snippets, JavaScript' by James on April 23rd, 2009

When I wrote “Extending jQuery’s selector capabilities” a few months ago I shared a custom selector that enabled you to select elements based on corresponding data held by jQuery. The syntax required was something like this:

$('body p > a:data(ABC=123)');

This all tied into jQuery’s native ‘data‘ method which enables you to add data to elements without creating expando properties.

So, what’s new?

I’ve been fiddling around with the innards of jQuery and Sizzle (jQuery’s default selector engine) and have something which I think is a tiny bit better, syntactically at least:

// Data is added to an element (nothing amazing here):
$('a#someLink').data('ABC', '123');
 
// Element is selected by querying data as if it were an attribute!!!
$('a[ABC=123]');
// Awesome!

From the above example it should be obvious that the jQuery’fied data is now directly tied into Sizzle’s attribute selectors. My first thought was that conflicts may occur where a data key is provided that also exists as an actual DOM property (what the attribute selector is intended for). For example, the consequence of the following action had to be considered:

// <a href="http://google.com" id="someLink">Google</a>
$('a#someLink').data('href', 'not the real href');
 
$('a[href=http://google.com]'); // This still has to work
$('a[href="not the real href"]'); // This should fail

When a DOM property exists the attribute selector will, as expected, return that DOM property (even if a matching data key exists). And when no DOM property of that name exists then the element’s data will be queried.

The magic:

Here’s the code that makes it possible:

(function($){
    var _dataFn = $.fn.data;
    $.fn.data = function(key, val){
        if (typeof val !== 'undefined'){ 
            $.expr.attrHandle[key] = function(elem){
                return $(elem).attr(key) || $(elem).data(key);
            };
        }
        return _dataFn.apply(this, arguments);
    };
})(jQuery);

This will work exactly as expected; all variations of the attribute selector seem to work successfully. You can read up on attribute selectors in jQuery here: http://docs.jquery.com/Selectors (scroll down to “attribute filters”).

Regex Selector for jQuery

Posted in 'Code Snippets, JavaScript' by James on January 28th, 2009

A while ago I published an article explaining the utter awesomeness of extending jQuery’s filter selectors. Building on that here’s something new; a regular expression selector. jQuery’s current attribute selectors (CSS3) do allow basic regex notation but no where near as much as this:

:regex

jQuery.expr[':'].regex = function(elem, index, match) {
    var matchParams = match[3].split(','),
        validLabels = /^(data|css):/,
        attr = {
            method: matchParams[0].match(validLabels) ? 
                        matchParams[0].split(':')[0] : 'attr',
            property: matchParams.shift().replace(validLabels,'')
        },
        regexFlags = 'ig',
        regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
    return regex.test(jQuery(elem)[attr.method](attr.property));
}

Usage

It’s pretty simple to use, you need to pass an attribute and a regular expression to match against. The regular expression must be in non-literal notation; so replace all backslashes with two backslashes (e.g. ^\w+$ -> ^\\w+$).

Extending jQuery’s selector capabilities

Posted in 'JavaScript, Twitter' by James on December 11th, 2008
Extending jQuery’s selector capabilities

I’m sure you all know that it’s possible to create plugins and extend various aspects of the jQuery JavaScript library but did you know you could also extend the capabilities of it’s selector engine?

Well, you can! For example, you might want to add a new ‘:inline’ selector which will return those elements that are displayed inline. Have a look:

$.extend($.expr[':'],{
    inline: function(a) {
        return $(a).css('display') === 'inline';
    }
});

Using the above code, when you want to select elements that are displayed inline you can simply include it within the selector:

$(':inline'); // Selects ALL inline elements
$('a:inline'); // Selects ALL inline anchors

That was a pretty simple example but I’m sure you can see the endless possibilites that this enables! And, creating a custom jQuery selector couldn’t really be simpler!