Re: nth descendent selector

On Fri, Nov 9, 2012 at 2:33 AM, Dave Smith <da__smith@hotmail.com> wrote:
> For example
> li:nth(7)
> would be equivalent to document.getElementsByTagName('li')[6]

The XQuery language (cousin to Selectors) has this functionality.
Unfortunately, it's difficult to do in Selectors, because all browsers
(and most JS-based selector engines, too) optimize selectors by
evaluating them right-to-left, rather than the left-to-right that you
probably expect.

That is, given a selector like "div span", browsers first find all the
<span>s in the document, then, for each one, test whether they have a
<div> ancestor.  It turns out that this is faster almost all of the
time, particularly when you're trying to match styles to elements as
the page loads (which constitutes *most* selector matching in a
browser).

If you had something like "div:nth(5) span", though, browsers that do
r-to-l would have to do the same testing, but also test whether the
<div> is the fifth in the document.  This isn't impossible, and it
doesn't invoke any hard-to-get information (if the document is in the
middle of loading, this only requires information that you already
have), but it will be *slow* (much slower than the ~ combinator, which
is already ridiculously slow compared to most other things in
Selectors).

It gets a bit more complicated if stuff precedes the :nth() compound
selector, like in "article div:nth(5)".  This is somewhat ambiguous,
first of all - does it get the fifth <div> in the document (assuming
it has an <article> ancestor), all of the fifth <div> descendants of
<article>s, or the fifth "<div> in an <article>" element?  Regardless,
the handling is more complicated, which means slower.

None of these are necessarily killer for this feature.  However,
browser vendors don't generally like adding extremely slow features
into Selectors, because authors aren't good at predicting Selector
performance (even "experts" routinely give nonsensical or outdated
advice in "Selector performance" presentations).  These kinds of
things give perverse incentives to the browser vendor, encouraging
them to implement the feature in a way that is fast but only somewhat
functional (but works in lots of cases).  This isn't a theoretical
concern - WebKit still gets some basic Selectors features wrong (many
things related to the + combinator don't work right) because they
consider the speed hit from doing it right to be not worth making it
correct.

On the JS side of things, you don't really need much here - when we
add the Selectors API functions to normal NodeLists, which we intend
to do, you can query, filter, then query again, and achieve the same
functionality with more power.

~TJ

Received on Tuesday, 13 November 2012 19:28:28 UTC