jQuery Positional Selectors Overview
Relevant source files
The following files were used as context for generating this wiki page:
jQuery positional selectors are a specialized set of pseudo-classes that allow for element selection based on their relative index within a result set rather than their position in the DOM tree. The cheerio-select library acts as a thin wrapper around css-select, extending it to support these non-standard CSS selectors which are prevalent in jQuery-based workflows.
Sources: README.md:1-10, src/index.ts:1-15
Positional Selector Logic and Implementation
The core engine distinguishes between "plain" CSS selectors and "filtered" (positional) selectors. When a selector string is parsed, the library groups them to apply different execution strategies. Plain selectors are passed directly to the standard CSS engine, while positional selectors trigger a custom filtering pipeline that respects the index of the elements found so far.
Supported Positional Pseudo-classes
The following table summarizes the positional selectors supported by the engine:
| Selector | Description | Logic Implementation |
|---|---|---|
:first | Selects the first element in the set. | Returns element at index 0. |
:last | Selects the last element in the set. | Returns element at length - 1. |
:eq(index) | Selects the element at the specified index. | Supports negative indices (e.g., -1 for last). |
:nth(index) | Equivalent to :eq. | Alias for index-based selection. |
:gt(index) | Selects elements with an index higher than the value. | Uses elements.slice(index + 1). |
:lt(index) | Selects elements with an index lower than the value. | Returns elements from 0 to index - 1. |
:even | Selects even-indexed elements (0, 2, 4...). | index % 2 === 0 |
:odd | Selects odd-indexed elements (1, 3, 5...). | index % 2 === 1 |
:not(:pos) | Excludes elements matching a positional selector. | Set-based subtraction of results. |
Sources: README.md:10-22, src/index.ts:80-125, src/positionals.ts:40-65
Selection Flow Architecture
The selection process involves an initial query to retrieve a base set of candidate elements, followed by a sequential application of positional filters.
This diagram illustrates how the engine separates standard CSS logic from the positional filtering pipeline to maintain performance while supporting jQuery extensions.
Sources: src/index.ts:167-210, src/index.ts:260-285
Technical Components
The findFilterElements Function
This function is the primary recursive driver for positional selection. It identifies the first occurrence of a positional filter in a selector array, resolves the elements leading up to it, applies the positional logic, and then recursively processes the remainder of the selector string.
Key logic includes:
- Limit Calculation: Using
getLimit, the engine optimizes by not fetching more elements than the positional selector could possibly return (e.g.,:firstsets a limit of 1). - Traversal Handling: If a selector contains traversals (like
>or+) after a positional, the engine resets the context or uses arootFuncto ensure the traversal stays within the scope of the previously filtered elements.
Sources: src/index.ts:260-315, src/positionals.ts:70-85
Filter By Position Execution
The filterByPosition function implements the specific math for each jQuery pseudo-class.
Sources: src/index.ts:80-120, src/index.ts:310-330
Handling Traversal-First Queries
The engine supports selectors starting with combinators (e.g., + .class). In these cases, it uses the provided element as the context and ensures the relative selector is handled correctly by prepending a universal selector if necessary.
Sources: src/index.ts:213-230, src/index.spec.ts:38-42
Usage and Integration
Positional selectors are integrated into the main API functions: select, filter, is, and some.
select: Returns an array of elements matching the selector, supporting alimitargument to stop searching once a certain count is reached.filter: Takes a list of existing nodes and filters them against the selector string, preserving the original DOM order.is: Checks if a single element matches the criteria.some: Efficiently checks if at least one element in a set matches, short-circuiting where possible.
Sources: src/index.ts:40-78, src/index.ts:233-258, README.md:28-60
Advanced Context and Root Options
The Options interface allows developers to specify a root (the top-level document) and a context (a specific set of elements to search within). This is critical for positional selectors like :scope, which allows queries to be relative to the provided elements.
Sources: src/index.ts:28-35, test/advanced-selectors.spec.ts:60-75
Conclusion
jQuery Positional Selectors in cheerio-select provide a bridge for legacy jQuery selector support within a modern, performant CSS engine. By separating selection into plain and filtered stages, the library maintains high performance for standard CSS while providing the specific indexing logic required for :first, :last, :eq(), and related positional pseudo-classes.