Re: [selectors-api] Scoped Selectors

Hi Lachy,

Here's a proposal.

querySelector*(selector, context) // allows selectors with :scope 
queryScopedSelector*(selector, context) // allows selectors with implied 
matchesSelector(selector, context) // allows selectors with :scope 

To check if the :scope pseudo-class is available, use:

try { document.body.matchesSelector(":scope", document.body); }
catch (error) { /* not supported */ }


try { document.querySelector(":scope", document.body); }
catch (error) { /* not supported */ }

Now, querySelector*() can't accept selectors with implied :scope because 
while "> em" is unambiguously ":scope > em", "p em" would become 
ambiguous. (is it "p em" or ":scope p em")
So we need a new method, such as queryScopedSelector*().
element.querySelector*() limits selection to descendants of elements, 
and element.queryScopedSelector*() should be consistent.
If element is the scope then element.queryScopedSelector*("~p") will 
return no elements.
If we want to support sibling queries then we need to provide a scope 
explicitly, so:

    element.parentNode.queryScopedSelector*("~p", element);

1. I don't think browsers should provide queryScopedSelector*()
2. I think :context is a better name than :scope
3. If the context argument of these methods could be an element or a 
NodeList it might satisfy some of the other feature requests.

Lachlan Hunt wrote:
> Hi,
>    I'm trying to find a suitable solution for the scoped selector
> issues, but figuring out what the most suitable API is proving 
> challenging.
> *Use Cases*
> 1. JS libraries like JQuery and others, accept special selector 
> strings beginning with combinators. e.g. ">em,+strong". These 
> libraries behave as if there was a selector that matched the context 
> node.
> e.g. In JQuery:
> $("+p", elm);
> This would select the p element that is a sibling of elm.
> 2. It would be useful to be able to check if an a given element 
> matches a selector in relation to a specified reference element 
> (:scope).  For example, check if an event target is a sibling of a 
> specific element, and if the parent element has a specifc class name set.
> e.g. Matches the selector: ".foo>:scope~input[type=text]"
> This may be particularly useful for event delgation.
> 3. Obtain a collection of elements based on their relation to more 
> than one specified reference elements.
> e.g.
> Query to the document to obtain elements matching ":scope+span", where 
> :scope is intended to match any of the elements in a specific 
> collection.  This would be simpler than iterating all of the nodes in 
> the collection, running the query on each of them and then merging the 
> results.
> *Problems*
> 1. Need a way to allow the browser to parse implicitly scoped 
> selectors beginning with combinators and imply the presence of :scope 
> before each in the group.
> 2. Need to allow :scope to be used within the selector strings, and 
> specify one or more scope elements that will be matched by :scope.  
> This needs to be useable with all of the querySelector(), 
> querySelectorAll() and matchesSelector() methods, or others with 
> equivalent functionality.
> 3. Ideally, there would be an easy, reliable way for scripts to test 
> if the implementation supports scoped selectors (at least, implicitly 
> scoped selectors. Those using :scope could only be discovered by 
> capturing the SYNTAX_ERR exception)  For legacy browsers that don't, 
> they can fall back to their own selector engines.
> *Possible Solutions*
> 1. Define a Selector object that can be used to parse and store a
>     selector, and which can handle pre-parsing the selector and
>     specifying the scope elements upon creation.  This selector object
>     can then be passed anywhere that accepts a selector string. (This is
>     basically part of the createSelector() and Selector interface
>     proposal from earlier).
> 2. Add parameters to the querySelector(), querySelectorAll() and
>     matchesSelector() methods for:
>     a. Indicating whether the selectors parameter should be processed
>        with an implied scope.
>     b. Specifying one or more reference elements that would match :scope.
> 3. Create new scoped versions of the existing methods that accept one
>     or more reference elements that would match the implied scope.
>     Add an optional parameter to the existing querySelector*() methods
>     that would Allow one or more reference elements to be specified to
>     match the explicit use of :scope in the selector.
> Option 2 doesn't provide an easy way to detect browser support.  
> Option 3 creates an additional queryScopedSelector*() and 
> matchesScopedSelector() methods, but this could get quite verbose if 
> we also add equivalent NS methods to handle the namespace issue, to 
> both the scoped and non-scoped versions.  This would create an 
> unreasonable number of different methods that would make understanding 
> the API quite complex.  Option 1 is syntactically messy, and requires 
> the creation of a new object just to handle a scoped selector, even if 
> that selector is only used once.
> I'm not sure which alternative would be best, and I'm kind of hoping 
> there's a 4th alternative I haven't thought of yet that can address 
> the use cases easliy enough.

Received on Friday, 25 September 2009 10:09:28 UTC