Thursday, May 13, 2010

jQuery Selectors - Adding a :contains exact match


This post has been updated to make these selectors work with jQuery 1.8


I have included a demo to show you the utility of two selectors that you can easily add to your jQuery library.

The standard ":contains()" selector matches the contents of the element in a case sensitive manner. But it is limited and there have been many times that I've needed to exactly match the contents of an element, so I threw together these two useful selectors.

In this demo, you can see the difference when you see what "td:contains(2)" matches - doing so will match all table cells that contain a "2" including dates that begin and end with "2" and the event titles that contains a "2".

":containsExact()" will grab the innerHTML from the element (the date span in this case) and exactly match it. I made this selector case-insensitve so you won't have to worry about the text case.

":containsExactCase()" will grab the innerHTML from the element (the event span in this case) and exactly match the contents in a case-sensitive manner. Try both "Vacation" and "vacation" in the demo.

":containsRegex()" will grab the innerHTML from the element (also the event span in this case) and use regex to match the contents in either a case-sensitive or insensitive manner (depending on the regex "i" flag). NOTE: because of the way jQuery 1.8 handles the text inside this selector, if parenthesis are used, the text must be wrapped in quotes, e.g. /(red|blue|yellow)/gi will now cause an error, so wrap it in quotes "/(red|blue|yellow)/gi" see the example below:


To include these selectors, just add the following code outside of any $(document).ready(function(){...})
$.extend( $.expr[":"], {
 containsExact: $.expr.createPseudo ?
  $.expr.createPseudo(function(text) {
   return function(elem) {
    return $.trim(elem.innerHTML.toLowerCase()) === text.toLowerCase();
   };
  }) :
  // support: jQuery <1.8
  function(elem, i, match) {
   return $.trim(elem.innerHTML.toLowerCase()) === match[3].toLowerCase();
  },

 containsExactCase: $.expr.createPseudo ?
  $.expr.createPseudo(function(text) {
   return function(elem) {
    return $.trim(elem.innerHTML) === text;
   };
  }) :
  // support: jQuery <1.8
  function(elem, i, match) {
   return $.trim(elem.innerHTML) === match[3];
  },

 containsRegex: $.expr.createPseudo ?
  $.expr.createPseudo(function(text) {
   var reg = /^\/((?:\\\/|[^\/]) )\/([mig]{0,3})$/.exec(text);
   return function(elem) {
    return RegExp(reg[1], reg[2]).test($.trim(elem.innerHTML));
   };
  }) :
  // support: jQuery <1.8
  function(elem, i, match) {
   var reg = /^\/((?:\\\/|[^\/]) )\/([mig]{0,3})$/.exec(match[3]);
   return RegExp(reg[1], reg[2]).test($.trim(elem.innerHTML));
  }

});