I recently began writing my own jQuery selectors more and more as I realized it’s a very nice and clean way to accomplish some specific tasks that I may normally have used an iterator for. It’s one of those things that if you’re not looking for you’ll never see, so I decided to write a little tutorial on it as setting up your own selectors is extremely easy with jQuery.
Here is a little boiler plate for creating your own jQuery selectors and pretty much all you’ll need:
$.extend($.expr[':'],
{
selectorName: function(el, i, m)
{
return true/false;
},
selectorName2: function(el, i, m)
{
return true/false;
}
});
Below are two ways to call a selector, one with an argument and one without.
$("#container :selectorName");
$("#conainert :selectorName(#element)");
$("#conainert :selectorName(>300)");
The “i” and “m” paramaters you won’t always need, they are just the current index of the element since it passes in a collection and the match for an argument. The matcher comes in when you are passing an argument, it’s a regular expression matcher and returns something like this:
[":width(>100)", "width", "", ">100"]You will mostly be using the m[3] value, from there it’s up to you to do whatever you like with the value you pass in. I’ve given a bunch of examples below to give you a better idea of the range and flexibility you can go with creating your own selectors. I basically just keep a little selectors.js file handy and toss whatever I need for the current project in there.
Also note that we can chain all these selectors together along with the existing jQuery selectors which is where it gets really interesting.
$("#container :isBold:even");
$("#container :leftOf(#element):width(>100):height(>100)");
You can download the library and checkout documentation for it here.Also feel free to submit your own selectors here
Here is a list of 12 custom selector samples I have created and used in my own projects. You can pretty much put anything in these selectors as long as you return a true or false value based on whether the current element passes the selector test.
-
:loaded
Select all loaded images.
$.extend($.expr[':'], { loaded: function(el) { return $(el).data('loaded'); } } $('img').load(function(){ $(this).data('loaded', true); }); $('img:loaded'); -
:width
Select all elements with width greater/less than the specified value.
$.extend($.expr[':'], { width: function(el, i, m) { if(!m[3]||!(/^(<|>)\d+$/).test(m[3])) {return false;} return m[3].substr(0,1) === '>' ? $(el).width() > m[3].substr(1) : $(el).width() < m[3].substr(1); } } $('#container :width(>100)'); -
:height
Select all elements with height greater/less than the specified value.
$.extend($.expr[':'], { height: function(el, i, m) { if(!m[3]||!(/^(<|>)\d+$/).test(m[3])) {return false;} return m[3].substr(0,1) === '>' ? $(el).height() > m[3].substr(1) : $(el).height() < m[3].substr(1); } } $('#container :height(<100)'); -
:leftOf
Select all elements left of the specified element.
$.extend($.expr[':'], { leftOf: function(el, i, m) { var oe = $(el).offset(); var om = $(m[3]).offset(); return oe.left + $(el).width() < om.left; } } $('#container :leftOf(#element)'); -
:rightOf
Select all elements right of the specified element.
$.extend($.expr[':'], { rightOf: function(el, i, m) { var oe = $(el).offset(); var om = $(m[3]).offset(); return oe.left > om.left + $(m[3]).width(); } } $('#container :rightOf(#element)'); -
:external
Select all anchor tags with links to domains other than the current domain.
$.extend($.expr[':'], { external: function(el) { if(!el.href) {return false;} return el.hostname && el.hostname !== window.location.hostname; } } $('#container :external'); -
:target
Select all anchor tags with the specified target.
$.extend($.expr[':'], { target: function(el, i, m) { if(!m[3]) {return false;} return (m[3] === '_self' && ($(el).attr('target') == '' || !el.target)) || (m[3] === $(el).attr('target')); } } $('#container :target(_self)'); -
:inView
Select all elements that have any part in the viewable window.
$.extend($.expr[':'], { inView: function(el) { var offset = $(el).offset(); return !( (offset.top > $(window).height() + $(document).scrollTop()) || (offset.top + $(el).height() < $(document).scrollTop()) || (offset.left > $(window).width() + $(document).scrollLeft()) || (offset.left + $(el).width() < $(document).scrollLeft()) ) } } $('#container :inView'); -
:largerThan
Select all elements larger than the specified one.
$.extend($.expr[':'], { largerThan: function(el, i, m) { if(!m[3]) {return false;} return $(el).width() * $(el).height() > $(m[3]).width() * $(m[3]).height(); } } $('#container :largerThan(#element)'); -
:isBold
Select all elements that have a font-weight of 700.
$.extend($.expr[':'], { isBold: function(el) { return $(el).css("fontWeight") === '700'; } } $('#container :isBold'); -
:color
Select elements with specified color in rgb format.
$.extend($.expr[':'], { color: function(el, i, m) { if(!m[3]) {return false;} return $(el).css('color') === m[3]; } } $("#container :color(rgb(255, 0, 0))"); -
:hasId
Select elements that have an id attribute specified.
$.extend($.expr[':'], { hasId: function(el) { return $(el).attr('id') !== undefined && $(el).attr('id') !== ''; } } $("#container :hasId");
jQuery Plugin Development Boilerplate
10 Coding Tips to Write Superior jQuery Plugins
Hi, nice selectors; I particularly like inView, width, height, leftOf, rightOf.
Also, I didn’t know about the hostName property. Thanks!
A performance tip on width/height. Don’t use regex, and dont validate. Instead, explicitly use parseInt in your comparison and the parseInt failure – comparing to NaN – will essentially do the same thing – no elements will be selected. Check charAt(0) instead of substr(0, 1).
The :loaded selector should use .live, if not one of the new event binders.
The :target selector is unnecessary, just use [target=\"...\"].
The :hasId is unnecessary, just use [id].
All in all, good work!
This would be a very useful edtioin, allowing much cleaner html with less serverside scripting. Right now we build css-classes into the server side scripts to achieve this kind of design, but as you say it could easily be done using CSS.Great idea!
//Sometimes you will find a variable DOM element is visible but the parent //dom element is Hidden that time say you need to check is it really visible //to the person who is viewing it or not
$.extend(
$.expr[\":\"],
{
reallyhidden: function (a) {
var obj = $(a);
while ((obj.css(“visibility”) == “inherit” && obj.css(“display”) != “none”) && obj.parent()) {
obj = obj.parent();
}
return (obj.css(“visibility”) == “hidden” || obj.css(‘display’) == ‘none’);
}
}
);
$(document).ready(function()
{
if($(‘#something’).is(‘:reallyhidden’)){
alert(‘yes’);
$(‘#something’).parent().show();
}
else{
alert(‘no’);
}
});
It looks VERY handy
I’ll give it a shot for sure.
I’m just a bit annoyed that you don’t manage equality in your width/height selectors