Positional Selectors: :even and :odd
Relevant source files
The following files were used as context for generating this wiki page:
Positional selectors, specifically :even and :odd, are specialized jQuery-style pseudo-selectors supported by cheerio-select. These selectors allow developers to filter a set of matched elements based on their 0-indexed position within that set. While standard CSS selectors primarily focus on tree relationships (like :nth-child), these positional selectors operate on the flat list of elements returned by preceding selector parts.
Sources: README.md:14-17, src/index.ts:79-85
Architectural Overview
The implementation of positional selectors in cheerio-select involves a two-stage process: gathering a set of candidate elements using standard CSS selection and then applying a positional filter. The engine identifies these selectors as "filtered selectors" to distinguish them from "plain" CSS selectors that can be executed natively by the underlying css-select library.
Selection Logic Flow
When a selector containing :even or :odd is encountered, the engine splits the query. It first retrieves the relevant elements and then applies a modulo-based filtering logic.
Technical Implementation
The filterByPosition Function
The core logic for :even and :odd resides within the internal filterByPosition function in src/index.ts. This function takes an array of Element objects and returns a new array containing only those that satisfy the positional requirement.
:even: Filters the array to include elements where the index is divisible by 2 (0, 2, 4, etc.).:odd: Filters the array to include elements where the index has a remainder of 1 when divided by 2 (1, 3, 5, etc.).
Sources: src/index.ts:101-107
Implementation Detail
case "even": {
return elements.filter((_, index) => index % 2 === 0);
}
case "odd": {
return elements.filter((_, index) => index % 2 === 1);
}
Sources: src/index.ts:101-106
Usage and Examples
Positional selectors are zero-indexed. In a list of paragraph elements, :even will select the first, third, and fifth elements, while :odd will select the second, fourth, and sixth.
| Selector | Description | Example Result (0-indexed) |
|---|---|---|
:even | Selects even elements | 0, 2, 4, 6... |
:odd | Selects odd elements | 1, 3, 5, 7... |
Sources: README.md:14-17, test/sizzle.spec.ts:896-899
Chaining and Limits
Positional selectors can be combined with other filters or limited by the select function's limit parameter. When a limit is provided, the engine optimizes the search to stop once the required number of positional matches is found.
Integration with Query Engine
The positional selectors are identified during the grouping phase of query execution. The groupSelectors helper separates standard CSS selectors from these positional pseudo-classes. This ensures that css-select handles the standard parts while cheerio-select manages the jQuery-specific positional logic.
| Component | Responsibility | Source Reference |
|---|---|---|
groupSelectors | Splits query into plain and filtered (positional) selectors | src/helpers.spec.ts:10 |
isFilter | Identifies if a pseudo-selector is a positional positional filter | src/index.ts:252 |
filterBySelector | Handles traversal and context for positional queries | src/index.ts:192-212 |
Summary
The :even and :odd selectors provide a convenient way to perform index-based filtering on element sets within cheerio-select. By extending the base css-select functionality with filterByPosition, the library maintains compatibility with legacy jQuery selectors while providing a performant, zero-indexed filtering mechanism.
Sources: src/index.ts:101-107, README.md:1-10