Re: Supporting Scoped Selectors in Selectors API 2

2009/9/29 Tab Atkins Jr. <jackalmage@gmail.com>:
> On Tue, Sep 29, 2009 at 1:04 PM, fantasai <fantasai.lists@inkedblade.net> wrote:
>> Lachlan Hunt wrote:
>>> As I said, the boolean flag parameter provided absolutely no way for
>>> scripts to detect whether or not implementations support scoped selectors.
>>>  Using the syntactic flag instead at least caused a syntax error to be
>>> thrown by existing implementations, allowing scripts to catch it and resort
>>> to fallback behaviour.
>>
>> Maybe you can't do this, but if you put the flag first then that will
>> trigger an exception in existing implementations.
>> (Not that I'm particularly in favor of this solution in any case.)
>
> Actually, you can feature-test for this pretty easily, especially if
> it works on document fragments.  Just create a document fragment like
> "<div><div></div></div>", grab the inner div and check what
> querySelector("div div",{"scoped":true}) on it returns.  If you get an
> element, the implementation doesn't support the flag.  Authors are
> already used to feature-testing, and this is the sort of thing that
> can easily be dropped into Modernizr or similar.
>
> ~TJ
>

And given that you can feature test, and that selectors are currently
scoped to the context node (the element where you call querySelector),
what if:

- you take the set of context elements using the provided algorithm
(note: allowing bare Elements, Arrays, sequences, NodeLists is quite a
mess, maybe using a variant function is better)
- for each context element in the set:
- you parse the selector:
   - if you get a good selector, you match it in the subtree of the
context element (same as now, except that now you need to get a
reference to a different element)
   - if it starts with a descendant combinator, you put the context
element (but you don't need to represent it in any syntax, it just
implementation) at the beginning of the selector, and match in the
subtree of the context element
   - if is starts with a (general or adjacent) sibling combinator, you
put the context element (again, syntax not needed) at the beginning of
the selector, and match in the subtree of the parent element
   - anything else, SYNTAX_ERR (even if for example "-" is an accepted
combinator in other places, to avoid messing with parent nodes and
keeping forward compatibility)
- you union the results

This allows to add a context element to good selectors, like
document.querySelector("div div", el2, el3, el4);
el2.querySelector("inside",outside1,outside2,outside3);
while allowing
document.querySelector("> div div", el2, el3, el4);
and el3.querySelector("> div"); and el4.querySelector("~ sibling");

No additional flags, arguments, methods: it just works.

Giovanni

Received on Tuesday, 29 September 2009 20:06:28 UTC