jQuery CSS Selectors? I usually do this by extending Sizzle

Not just because that produces a solution that is much more usable (and also definitely very snazzy JavaScript) which is always a “good thing”.

Update 2013-DEC-12

Fiddles made to work. dbjSAS download you are looking for is HERE.

 But let me start from the beginning.

I stumbled upon this little post, describing one somewhat simplistic but effective way to filter down what was selected by jQuery. This time by looking into the selected elements (HTML5) data-* properties.

Since I am recently very much involved into jQuery element selecting by peeking into css properties, I naturally transformed this little plugin  (aka filterByData ) using the same idea but this time applied to css properties, and naturally named it filterByCSS. Here it is in all of its simplicity:

[jsfiddle url=”http://jsfiddle.net/dbjdbj/jTqSu/” style=”width:100%;height:400px;border:solid #4173A0 1px;”]

This “fiddle” is qUnit “enabled” so please go ahead and add more tests.

This is simple and useful, but not very useful. First. Functionality is somewhat limited by non-existence of operators to be applied when comparing with css property values. Like we can do in jQuery/Sizzle when we query for Attrib values:

In filterByCSS() equality operator is implied.

One easy way towards minor improvement might be to transform this plugin into data/css/prop/attr filter. Let me call it filterBy. Usage will be then something like this

I don’t know about you, but for me this is not very elegant.

Can we use Sizzle for this ?

filterByCSS() is useful. But limited. Not necessarily a “bad thing” but It is just an jQuery plugin after all. Yet another of dozens or even more you are already using. So, where next? Where there is a need for special filter there is always a solution using Sizzle itself. The next step “onwards and upwards”, towards ultimate solution is not to use filtering but  selecting. Instead of the plugin two steps approach: selecting and then filtering, we will do it in a single querying step. To be able to query (aka select) by using css style values, the easiest is to use Sizzle pseudo selectors extension mechanism. I think this is introduced in jQuery 1.6.1. I googled around and found that Mr J. Padolsey has presented :regex pseudo selector which is almost exactly what I want. Here is a small set of  examples:

:regex() pseudo selector  works for attributes, data and css values. It is looking into their content and on top of that allows the use of regular expressions, to filter further down on the values obtained.

But alas. There was a bug inside, and this inspired me to debug and extend and deliver new version of my :rx selector

[jsfiddle url=”http://jsfiddle.net/dbjdbj/W4HZR/” style=”width:100%;height:400px;border:solid #4173A0 1px;”]

The bug in :regex() was that code was also returning true on non existent names. And my extension is that ‘prop’ label is also possible. Therefore, now the selection is looking specifically into element style, data or properties (not attributes), if possible. In rx:(), as before in :regex() if not label is given, attributes are searched. That is: attribute selection is implied.

Now, let’s make Sizzle sweat!

:rx() Sizzle pseudo selector is  perhaps nice, clever and useful. But. First of all, for 90% of JavaScript population,  regular expressions are not exactly the most understood or beloved feature of JavaScript. Second we have now yet another new pseudo selector with its quirky new syntax. Introduced into already volatile world of jQuery CSS selectors. All in all, I am not very hopeful my :rx() might win any popularity contest.

And third and most important, we still have no operators. Would it not be much more useful, and elegant, if one could write:

This extended querying would be rather nice would it not? Imagine, (for example) you want to “right align”, all of your special elements. Certainly you can do that without any special jQuery extensions today. Here is one quick and dirty snippet solution:

Perhaps I could do this with filterByCSS() ? No, I could not, because (remember) there are no operators for filters. :rx() is also not good here for the same reason too. Hmm … I am sure you are by now (almost) convinced? How much better would it be if you could just do this instead:

No pseudo selectors, regular expressions and no filter plugin required. Just familiar attribute selection syntax with very little changes to remember. I am sure I do not have to convince you any more, about this approach, with more ‘clever’ and complex use cases.

Now. I have some experience with Sizzle extensions, of this kind. Me and Mr Balazs Endres got this working, but way back (was it 2009 ?) when jQuery 1.4.2, “ruled the land”.  Now it is 2013 and things in  jQuery 1.9.1 (and above) are very different. Our code from 2009 is not working anymore. So these days, I am working on new implementation of Sizzle Attribute Selectors Extended. That will allow (you) to simply and efficiently query the DOM by taking into account elements data, properties and css style values.

[jsfiddle url=”http://jsfiddle.net/dbjdbj/PPTED/” style=”width:100%;height:400px;border:solid #4173A0 1px;”]

My Sizzle Attribute Selection (aka dbj*SAS, or just SAS) syntax:

  • data querying
    •  “[:name operator value]”
  • css style querying
    • “[~name operator value]”
  • properties querying
    • “[::name operator value]”

If SAS syntax is used four new operators can be applied: >, <, <=, >=
in which case,before comparison, parseFloat() is applied to both value to be checked and the value obtained.Example:

Above will select any div element that has a ‘id’ attribute and css bottom property
bigger or equal to “10px” or “10%” or any other number/unit combination stored in css style. Effectively, for element style properties values, units are ignored. if value or check value can not be parsed into float (aka ‘NaN situation’) they will NOT be compared and the result will be false. When using operators think of that.

This Sizzle extensions opens (wide) all sorts of possibilities.  Of course, all you can do with dbj*SAS, you can do without it; that is without composing selectors using SAS. All uses cases I could think of are doable without dbj*SAS, but are not pretty. Some of them can be done with the help of filtering plugins, like (my own) filterByCSS() or even by using Sizzle pseudo selectors, like :rx(). But nothing, I think, beats simplicity and functionality of SAS extensions.

Now please understand this. This dbj*SAS extensions provide more functionality. And, inevitably more functionality is less speed. Ultimately It is up to you, dear user, to do the balancing act. Apply this extensions only if you are convinced your use case is a good candidate for dbj*SAS. You can not-use dbj*SAS in two ways. First of all you can simply avoid including jquery.dbjSAS.js, or you can include it and either not use SAS (then why including it?) or simply use SAS judiciously.  This will still make standard attribute selectors a bit slower, although not much. I still have not focused on, or tested the dbj*SAS performance. It is too early for optimizations, before the full functionality is developed.

This is work-in-progress, but, I think, already very usable. And (dare I write) elegant way to select elements based on values of their css properties.

More to come. Stay tuned :)