0Pricing
jQuery Academy · Lesson

Building Custom Pseudo-Selectors

Learn to register your own custom pseudo-selectors with jQuery.expr[':'] to simplify complex element selection logic and improve code readability.

Building Custom Pseudo-Selectors is a free jQuery Academy lesson on CoddyKit — lesson 1 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the jQuery Academy learning path, one of 3 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Custom Selectors?

jQuery's built-in selectors are incredibly powerful, but sometimes you encounter specific filtering needs that are complex or repetitive.

This is where custom pseudo-selectors come in handy! They allow you to define your own specialized filters, simplifying complex selection logic and making your code cleaner and more readable.

When Default Selectors Fall Short

Imagine you often need to select all <div> elements that not only have a specific class but also a data-status attribute set to 'active'.

While you can combine standard selectors, this can become lengthy and less intuitive if the logic is more involved, or if you need to apply it frequently across your application.

Meet jQuery.expr[':']

jQuery.expr[':'] is the object where you register your custom pseudo-selectors. Think of it as extending jQuery's core selection engine.

When jQuery encounters a selector like :myCustomSelector, it looks up myCustomSelector in this object. You assign a function to a key (your selector's name) which jQuery then executes for each element it tests.

Defining `:has-tooltip`

Let's define a simple custom selector, :has-tooltip, that identifies elements with a title attribute. This is how you add it to jQuery.expr[':'].

The function you provide receives the current DOM elem being tested. It should return true if the element matches your criteria, and false otherwise.

jQuery.expr[':'].hasTooltip = function(elem) {
  // Check if the element has a 'title' attribute
  return !!$(elem).attr('title');
};

Using Your Custom Selector

Now that our :has-tooltip selector is defined, we can use it just like any other jQuery pseudo-selector! Try running the example below.

It will highlight all elements that have a title attribute, demonstrating the power of your new custom filter.

<!DOCTYPE html>
<html>
<head>
<title>Custom Selector Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<style>
  .highlight {
    border: 2px solid green;
    background-color: #e0ffe0;
  }
</style>
</head>
<body>
  <p title="This is a tooltip">Paragraph with tooltip</p>
  <div id="no-tooltip">Just a div</div>
  <span title="Another tooltip here">Span with tooltip</span>

  <script>
    jQuery.expr[':'].hasTooltip = function(elem) {
      return !!$(elem).attr('title');
    };

    $(document).ready(function() {
      $('p:has-tooltip, span:has-tooltip').addClass('highlight');
    });
  </script>
</body>
</html>

The `elem`, `i`, and `match` Args

When your custom selector function executes, it receives three important arguments:

  • elem: The current DOM element being tested.
  • i: The index of elem within the set of elements jQuery is currently iterating over.
  • match: An array containing results from the regular expression used to parse the selector. This is essential for selectors that accept arguments.

For simple selectors, you'll primarily use the elem argument.

Selector Based on Data Attributes

Let's create a selector :data-status(active) to find elements where a data-status attribute equals 'active'. This shows how to use the match argument.

The value 'active' (the argument inside the parentheses) will be found in match[3]. This allows your selector to be dynamic!

<!DOCTYPE html>
<html>
<head>
<title>Data Status Selector</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<style>
  .active-item {
    background-color: lightgreen;
    padding: 5px;
    margin: 3px;
  }
</style>
</head>
<body>
  <div data-status="active">Item 1 (Active)</div>
  <div data-status="inactive">Item 2 (Inactive)</div>
  <p data-status="active">Item 3 (Active)</p>
  <span>Item 4 (No Status)</span>

  <script>
    jQuery.expr[':'].dataStatus = function(elem, i, match) {
      const expectedStatus = match[3]; // e.g., 'active' from :data-status(active)
      const actualStatus = $(elem).data('status');
      return actualStatus === expectedStatus;
    };

    $(document).ready(function() {
      $(':data-status(active)').addClass('active-item');
    });
  </script>
</body>
</html>

Understanding `match[3]`

The match array is a result of jQuery's internal regular expression parsing of your selector string. For a selector like :yourSelector(argument), the argument part is typically captured in match[3].

This mechanism is crucial for creating dynamic and flexible custom selectors that can accept parameters, making them more reusable and powerful for various filtering scenarios.

Advanced Logic: `:containsExact`

Let's build a more advanced selector: :containsExact(text). Unlike jQuery's default :contains(), this will only match elements whose *entire* text content (excluding child elements) is exactly the provided text.

This often involves carefully comparing $(elem).text().trim() to ensure an exact match.

<!DOCTYPE html>
<html>
<head>
<title>Contains Exact Selector</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<style>
  .exact-match {
    font-weight: bold;
    color: blue;
    background-color: #e0f0ff;
    padding: 5px;
    margin: 3px;
  }
</style>
</head>
<body>
  <div>Hello World</div>
  <div>Hello there!</div>
  <p>Hello</p>
  <span>World</span>

  <script>
    jQuery.expr[':'].containsExact = function(elem, i, match) {
      const searchText = match[3]; // The text inside the parentheses
      const elementText = $(elem).text().trim();
      return elementText === searchText;
    };

    $(document).ready(function() {
      $(':containsExact(Hello World)').addClass('exact-match');
    });
  </script>
</body>
</html>

Tips for Custom Selectors

Keep these best practices in mind when creating your custom selectors:

  • Performance: Complex logic can impact performance, especially on large DOMs. Optimize your selector functions.
  • Clarity: Name your selectors clearly so their purpose is immediately obvious to anyone reading your code.
  • Reusability: Design them to be generic enough to be useful in various contexts, not just one specific scenario.
  • Avoid Conflicts: Choose unique names to prevent clashes with future jQuery selectors or other plugins you might use.

Custom Selector Challenge

You want to create a custom selector :is-empty that selects elements which have no text content and no child elements. This is similar to jQuery's built-in :empty selector.

Which of the following code snippets correctly define this custom pseudo-selector?

Recap: Custom Selectors

In this lesson, you learned how to extend jQuery's powerful selection capabilities by creating your own custom pseudo-selectors using jQuery.expr[':'].

You explored how to define simple selectors, pass arguments to them via the match array, and apply them to simplify complex filtering logic, ultimately making your jQuery code more readable, maintainable, and efficient.

Frequently asked questions

Is the “Building Custom Pseudo-Selectors” lesson free?

Yes — the full text of “Building Custom Pseudo-Selectors” is free to read here on the web, and the jQuery Academy course includes 3 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the jQuery Academy course, upgrade to CoddyKit PRO.

What will I learn in “Building Custom Pseudo-Selectors”?

Learn to register your own custom pseudo-selectors with jQuery.expr[':'] to simplify complex element selection logic and improve code readability. You practise jQuery Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start jQuery Academy?

No prior experience is required. jQuery Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 3, so you can start here or from the beginning and move at your own pace.

How long does the “Building Custom Pseudo-Selectors” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this jQuery Academy lesson?

Yes. Every jQuery Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Building Custom Pseudo-Selectors
  2. Advanced Filtering with .filter()
  3. Excluding Elements with .not()
← Back to jQuery Academy