[selectors-api] Scoped Selectors

    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.

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 


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.

Lachlan Hunt - Opera Software

Received on Friday, 25 September 2009 03:01:46 UTC