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”).