Custom Selector in jQuery

With jQuery’s custom selectors, you may expand the library’s functionality beyond that of regular CSS selectors and discover elements on a page in new ways. They are very helpful for increasing readability and condensing intricate code logic into a reusable section.
What are Custom Selectors?
The CSS selector expressions used with the $() function are parsed by Sizzle, the main selector engine of jQuery, which has been a component of jQuery since version 1.3. You can create your own “custom selectors” with jQuery in addition to the normal CSS specs (1 through 3). By allowing you to find page items in new ways, these custom selectors expand on the already remarkable possibilities of CSS selectors. Additional selector expressions, like the :paused selector provided by the Cycle plugin, can be provided by plugins.
Enhancing code legibility and encapsulating code fragments into reusable components are two of the main motivations for developing custom selectors. Custom selectors let you abstract intricate element-finding logic, just like you may build functions or plugin methods to reuse logic. This implies that you can use a straightforward, descriptive custom selector in place of writing a long or repetitive selector expression each time, which will clear up and simplify your code.
How to Create Custom Selectors (Pseudo-classes)
A pseudo-class, or expression that begins with a colon (:), is the simplest kind of custom selector to add. The built-in pseudo-classes :checked and :nth-child() are two examples.
You expand the internal $.expr[‘:’] object of jQuery to create a new pseudo-class. Values in this object work similarly to filtering functions that are provided to methods like.filter() and.not(). $() runs your custom selector function in $.expr[‘:’] for every element.If the element is in the result set, this function returns true; if not, it is excluded.
Four parameters are supplied to the function you specify for your custom selector:
- element: The unprocessed DOM element under consideration.
- index is the DOM element’s 0-based index in the iterated collection.
- matches: An array that holds the output of the selector’s parsing regular expression. Matches for selectors such as :group(2) would have the value enclosed in parenthesis (e.g., ‘2’).
- set: Up until that time, every single DOM element matched.
These arguments are used by your pseudo-class selector function to decide if the element is part of the result set.
Performance Considerations
Performance must be considered while using flexible, understandable custom selectors. Sizzle, jQuery’s selector engine, cannot use the browser’s native DOM selector engine (document.querySelectorAll()) when a selector expression contains a custom jQuery selector (:eq(), :odd, :even, or your own :group()) without a CSS counterpart. Instead, it employs a slower “loop-and-test” method to iterate through objects and test them.
Consequently, if performance is a major consideration, you should generally use selectors that are included in the CSS specification rather than jQuery’s own selectors. But give priority to simplicity of developing and maintaining code, and only optimise when benchmarking tools such as jsPerf reveal a quantifiable performance issue.
Code Example:
To demonstrate this, let’s create a pseudo-class named :group() that contains the logic for choosing alternate groups of table rows. The explanation of row striping in tables served as the basis for this example.
<!DOCTYPE html>
<html>
<head>
<title>Custom Selector Example</title>
<style>
.alt {
background-color: #f0f0f0;
}
table, td {
border: 1px solid #000;
border-collapse: collapse;
padding: 5px;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
(function($) {
$.extend($.expr[':'], {
group: function(el, i, match, elems) {
var num = parseInt(match[3], 10);
return (i % (num * 2)) < num;
}
});
})(jQuery);
$(function() {
// Apply 'alt' class to table rows in groups of 2
$('#news tr:group(2)').addClass('alt');
});
</script>
</head>
<body>
<h3>News Table (Striped in Groups of 2)</h3>
<table id="news">
<tr><td>Row 1</td></tr>
<tr><td>Row 2</td></tr>
<tr><td>Row 3</td></tr>
<tr><td>Row 4</td></tr>
<tr><td>Row 5</td></tr>
<tr><td>Row 6</td></tr>
</table>
</body>
</html>
Output:
News Table (Striped in Groups of 2)
Row 1
Row 2
Row 3
Row 4
Row 5
Row 6
Explanation of the Code
$(function($) { … })(jQuery);: This function expression is Immediately Invoked (IIFE). Establishing a local scope for your code is a standard practice in the creation of jQuery plugins. In order to guarantee that $ refers to jQuery even in cases where other libraries have called $.noConflict(), it passes the global jQuery object as the $ parameter.
$.extend($.expr[‘:’], { … });: To add a new custom selector, use this line. The object where pseudo-class selectors are defined is $.expr[‘:’]. You give this object a new attribute, in this example a group.
group: function(element, index, matches, set) { … }: To find out if an element matches your :group() selector, this method will be run for every element.
Here, matches are quite important. The X portion of a selection such as :group(X) is captured by matches and processed as an integer (num). Using the fundamental logic (index % (num * 2)) < num, one can ascertain which items are part of the “group.” If num is 2, for instance, then (index % 4) < 2 indicates that entries at index 0, 1, 4, 5, etc., will be chosen, hence choosing the first two elements in each set of four.
The purpose is succinctly stated here: “select news table rows in groups of three and add the ‘alt’ class.” Your reusable custom selector now conceals the intricate filtering mechanism, simplifying and maintaining your application’s code. Simply altering the number included in parenthesis will change the grouping; for instance, $(‘#news tr:group(2)’) would group by two.