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+$
).
// Select all elements with an ID starting a vowel: $(':regex(id,^[aeiou])'); // Select all DIVs with classes that contain numbers: $('div:regex(class,[0-9])'); // Select all SCRIPT tags with a SRC containing jQuery: $('script:regex(src,jQuery)'); // Yes, I know the last example could be achieved with // CSS3 attribute selectors; it's just an example... |
Note: All searches are case insensitive; you can change this by removing the ‘i’ flag in the plugin.
This plugin also allows you to query CSS styles with regular expressions, for example:
// Select all elements with a width between 100 and 300: $(':regex(css:width, ^[1-3]\\d{2}px$)'); // Select all NON block-level DIVs: $('div:not(:regex(css:display, ^block$))'); |
Additionally it allows you to query data strings added to elements via jQuery’s ‘data’ method:
// Add data property to all images (just an example); $('img').each(function(){ $(this).data('extension', $(this)[0].src.match(/.(.{1,4})$/)[1]); }); // Select all images with PNG or JPG extensions: $('img:regex(data:extension, png|jpg)'); |
Have fun!
Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!
Badass! I love RegEx and I love jQuery. Way to put them together!
This is most excellent. Great work, James.
Also I think after
regexFlags = 'ig';
you meant that to be a comma, rather than a semicolon. 🙂@Ben, Thanks!
@Paul, Thanks! I’ve corrected the error.
This is the awesomeness of jQuery 🙂
thanks James
Very neat. I haven’t thought of a good use for this yet. At first I thought I could use it namespace/categorize my markup, but then I realized I already do that using the class selectors.
Good job!
Interesting, I’m not sure how much need there is for this in practise but a useful technique to remember nonetheless. Thanks for sharing!
Does this script test each element in the document against the regular expression? If so I should think this method is fairly slow. Has anyone done any testing to see how fast this performs versus a normal jQuery selection.
@Ibrahim, indeed; the awesomeness of jQuery!!
@Jerry, lol, don’t pressure yourself to come up with some way to use it. It’s just meant to be an experimental proof of concept…
@Thomas, that was my original concern but regardless of how useful it is I think it’s still worth putting it out there for people to use if they need to. 🙂
You’re correct about it being quite slow, although it really depends on how many elements you’re testing against and the complexity of the regular expression. It will test against all elements specified in the first part of the selection:
It would be unfair to test it against “normal jQuery selections” because it has so much more power. Admittedly, if you’re only going to use it once then there’s not much point; it would be better to use jQuery’s filter method (
$('*').filter(function(){...})
) but if you’re planning on doing quite a bit of regex-testing then using the regex selector may be the better option.One of the most useful things, in my view, is its ability to query element data; added through
jQuery(elem).data()
.Good job man. I like this 😉
Great idea!
Got any performance benchmarks comparing to stock selectors?
awesome dude! thanks for this!
Thanks for the comments!
The performance isn’t great Zach, but that wasn’t really my intention with this extension. It was more of a proof of concept. Plus it adds additional power to selectors; it allows you to query CSS properties and element data! (
$(elem).data(...)
)As far as attribute selectors go you should stick with the CSS3 stuff (
$('[href^=whatever]')
) because, on newer browsers wherequerySelectorAll
is supported, that’ll be much faster!This is really amazing, thanks!
Wow, that’s actually really awesome… Thanks! I’m sure, eventually, down the road, I will come across a situation where it will prove useful. It’s at least to know that I have a good well-thought-out option available to me.
Hi !
The article just has been translated to French on jquery.info : http://www.jquery.info/spip.php?article91
I find this very useful. Especially the ability to query CSS.
Is it also possible to find elements by its text content?
Like instead of a filter function like this:
Pretty slick. Just what I was looking for and works sweet. Thanks for the post.
Great code, Hate to nit-pick, but wouldn’t your second usage example select all items between 100 and 399? not 100-300.
Very handy, thanks!
Finally a useful jQuery post. Thanks!
I am using this great jquery extension and I love how it works, but I think I have found a bug in it and I’m not sure how or why it happens.
On my site, I have this extension, and it works great, but when I leave the site open for a long time in IE8, it throws a js error that says this “‘3’ is null or not an object” on line 2 of the extension.
I can consistently reproduce this error, but I don’t know much about it. I’m not sure how long the page has to be open for or what causes it to happen, but I do need a fix for it. Basically, as I work, I just leave IE8 open in the background on my website until the js error is thrown.
Does this script constantly run even when the page isn’t doing anything? Any ideas?
I was wondering whether this can be used to find “backgroundImage”‘s url’s…
For example I have div#header with css element backgroundImage = images/backgrounds/background_1.jpg
What I need is to find out the current image, if its 1,2,3 or etc… and then change to a different one if thats the case, like increment the number or alternate between 1 and 2.
Thanks!! 🙂
Nice one mate. I have also added the link to your post in my Ultimate collection of top jQuery tutorials, tips-tricks and techniques to improve performance. Have a check below:
http://technosiastic.wordpress.com/2009/09/24/collection-of-top-jquery-tutorials-tips-tricks-techniques-to-improve-performance/