Re: [selectors-api] Scoped Selectors
Lachlan Hunt wrote: John Resig wrote: With that in mind, option #3 looks the best to me. It's lame that the API will be longer but we'll be able to use basic object detection to see if it exists. Unfortunately the proper scoping wasn't done the first time the Selectors API was implemented so we kind of have to play the hand we've been dealt. Thus there would be two new methods: queryScopedSelectorAll queryScopedSelector I really didn't want to introduce new methods for this if it could be avoided. I realise one problem with the first draft of the API I posted yesterday was that is was too cumbersome for scripts to create and use scoped selectors, rather than normal selectors. That draft required scripts to do the following: var selector = document.createSelector("+p", true); document.querySelector(selector, elm); This isn't cumbersome: - JS libraries are still going to provide their own query functions which can wrap this trivially - people who want to use the standard API will also want to use standard selectors - the tiny group of people who don't want to use a JS library but do want to use selector strings with implied :scope will just create a wrapper function (or method). Element.prototype.queryScopedSelector = function(selector, scope) { return this.querySelector(document.createSelector(selector, true), scope); } This is just as simple as the new proposal. Element.prototype.queryScopedSelector = function(selector, scope) { return this.querySelector("!" + selector, scope); } I have come up with a significantly simpler, alternative solution that not only abolishes the createSelector() method and the SelectorExpression interfaces, but also avoids introducing additional methods like queryScopedSelector(), or extra parameters. The draft now defines the concept of a *selector string* and a *scoped selector string*. The selector string is just an ordinary selector, as supported by current implementations. A scoped selector string is a string that begins with an exclamation point followed by a the remainder of the selector. The purpose of the exclamation point is to clearly identify the string as a scoped selector that requries an extra pre-processing step to turn it into a valid group of selectors. There are also slightly different requirements for the processing Element.querySelectorAll() when the selector argument is a scoped selector string. This allows for the sibling combinator cases to work. That is quite inconsistent behavior. - querySelector*() and matchesSelector() can now take standard and non-standard selector strings - matchesSelector() can have explicit declaration of the ::reference element, while querySelector*() can have explicit and implied - element.querySelector*() now has quite complex behavior. With one selector string it selects from descendants of element, with another is selects from descendants of element.parentNode. If you want "element" to be the :reference node then it doesn't need a second argument. But if you want "element" and another node to be :reference then you have to pass both in an array as the second argument. It is also less flexible - it makes using non-standard selector strings slightly easier but using standard selector strings is now more difficult. - if I want to provide an API that doesn't accept these non-standard selector strings then I can no longer just wrap querySelector*(). - if I want to provide an API that doesn't return siblings of the context-node then I can no longer just wrap querySelector*(). To illustrate that last point using the previous and current drafts: To support "+p" in previous draft is trivial. Element.prototype.queryScopedSelectorAll = function(selector, ref) { return this.parentNode.querySelectorAll(document.createSelector(selector, true), ref); } To NOT support ":reference + p" in current draft we have to filter siblings from the result. Element.prototype._querySelectorAll = Element.prototype.querySelectorAll; Element.prototype.querySelectorAll = function(selector, ref) { var parent = this.parentNode; var nodes = this.querySelectorAll(selector, ref); return Array.filter(nodes, function(node) { return (node.parentNode == parent) ? false : true; }); } To NOT support "+ p" in current draft have to reject scoped selector syntax and filter siblings. Element.prototype._querySelectorAll = Element.prototype.querySelectorAll; Element.prototype.querySelectorAll = function(selector, ref) { var parent = this.parentNode; if (/^(>|+|~|!)/.test(selector)) throw ""; var nodes = this._querySelectorAll(selector, ref); return Array.filter(nodes, function(node) { return (node.parentNode == parent) ? false : true; }); } e.g. The selector ">em, >strong" supported by JS libraries can simply be prefixed with a "!", like "!>em, >strong" and the implementation will be able to process it to become ":scope>em, :sco
Re: [selectors-api] Scoped Selectors
Boris Zbarsky wrote: On 9/26/09 4:36 PM, Lachlan Hunt wrote: A scoped selector string is a string that begins with an exclamation point followed by a the remainder of the selector. This assumes that '!' will never be allowed at the beginning of a CSS selector, right? It does, but the workaround would be to insert an extra space at the beginning. I'd be willing to pick an alternative character to avoid any possible clash. Perhaps a comma instead, like ",div div", which can never be used at the beginning of a conforming group of selectors. I'm also considering adjusting the idea it so that it will work when the string simply begins with any combinator ('+', '~', or '>'), but we still need something to use in place of the descendant combinator as the space won't have the desired effect. Have you run this by the CSS working group? Not yet, but will do so after I find out from this group if the technique is viable. e.g. The selector ">em, >strong" supported by JS libraries can simply be prefixed with a "!", like "!>em, >strong" and the implementation will be able to process it to become ":scope>em, :scope>strong". Of course, it will also work with the other combinators. That processing still needs to be defined, right? Yes. It would be useful to get feedback from implementers about how I should define this. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: [selectors-api] Scoped Selectors
On 9/26/09 4:36 PM, Lachlan Hunt wrote: A scoped selector string is a string that begins with an exclamation point followed by a the remainder of the selector. This assumes that '!' will never be allowed at the beginning of a CSS selector, right? Have you run this by the CSS working group? e.g. The selector ">em, >strong" supported by JS libraries can simply be prefixed with a "!", like "!>em, >strong" and the implementation will be able to process it to become ":scope>em, :scope>strong". Of course, it will also work with the other combinators. That processing still needs to be defined, right? -Boris
Re: [selectors-api] Scoped Selectors
John Resig wrote: 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. I don't see the purpose of making a distinction between the root node used for the query and the node being used for the scope - they should be one and the same. // Doesn't make sense: document.querySelectorAll("div div", document.body) // Does make sense document.body.querySelectorAll("div div") It does make sense. It just means something slightly different from what you appear to be thinking. In the above, the document.body element wouldn't have any effect because it's not a scoped selector and there is no :scope pseudo-class used. Also, I don't think it's been made clear in the discussion thus far but while cases like handling "> div" are nice - we're mostly concerned about cases like "div div" (that escape outside the original root of the query). The problems with handling ">div", "+div" and "div div" are exactly the same issue. The only difference is that the first 2 begin with a child combinator and sibling combinator, respectively, and the latter has an implied descendant combinator. They can all be addressed with the same solution. Given this DOM: // All of these should return nothing document.getElementById("one").querySelelctor("div div") document.getElementById("one").querySelelctor("body div") document.getElementById("one").querySelelctor("div #two") The real benefit of the API as I first designed it, is that it elegantly provides ways to address nearly every use case raised and more, using the simple, yet extremely powerful concept of contextual reference elements, which is in fact not so different from the pattern used in JQuery: $("selector", context);. There doesn't need to be scoping for matchesSelector. matchesSelector implies that it it's starting from the specified node and doing a match. Additionally the use case of .matchesSelector("> div") doesn't really exist. The use case doesn't really exist when the context node is considered to be the contextual reference element. But allowing reference nodes to be specified, it allows the query to check where it is in relation to another element. So, for example you could more easily check if the parent of element elm is one of the nodes in the collection elms. var elms = [div1, div2, div3]; e.g. elm.matchesSelector(":scope>*", elms); Returns true if the elm.parent == div1, elm.parent == div2 or elm.parent == div3. With that in mind, option #3 looks the best to me. It's lame that the API will be longer but we'll be able to use basic object detection to see if it exists. Unfortunately the proper scoping wasn't done the first time the Selectors API was implemented so we kind of have to play the hand we've been dealt. Thus there would be two new methods: queryScopedSelectorAll queryScopedSelector I really didn't want to introduce new methods for this if it could be avoided. I realise one problem with the first draft of the API I posted yesterday was that is was too cumbersome for scripts to create and use scoped selectors, rather than normal selectors. That draft required scripts to do the following: var selector = document.createSelector("+p", true); document.querySelector(selector, elm); I have come up with a significantly simpler, alternative solution that not only abolishes the createSelector() method and the SelectorExpression interfaces, but also avoids introducing additional methods like queryScopedSelector(), or extra parameters. The draft now defines the concept of a *selector string* and a *scoped selector string*. The selector string is just an ordinary selector, as supported by current implementations. A scoped selector string is a string that begins with an exclamation point followed by a the remainder of the selector. The purpose of the exclamation point is to clearly identify the string as a scoped selector that requries an extra pre-processing step to turn it into a valid group of selectors. There are also slightly different requirements for the processing Element.querySelectorAll() when the selector argument is a scoped selector string. This allows for the sibling combinator cases to work. e.g. The selector ">em, >strong" supported by JS libraries can simply be prefixed with a "!", like "!>em, >strong" and the implementation will be able to process it to become ":scope>em, :scope>strong". Of course, it will also work with the other combinators. This allows JS libraries to trivially prepend "!" to the selector before passing it to the API, rather than requiring any complicated pre-processing. In current browser im
Re: [selectors-api] Scoped Selectors
Lachlan Hunt wrote: Sean Hogan wrote: Here's a proposal. querySelector*(selector, context) // allows selectors with :scope pseudo-class queryScopedSelector*(selector, context) // allows selectors with implied :scope matchesSelector(selector, context) // allows selectors with :scope pseudo-class Yes, this is effectively the same as option #2 that I described, except you haven't provided a way to support implied scope there. That's because implied scope is incompatible with ":scope ~ p" or "~ p" should we want to support those. I think it will be confusing to have implied and explicit forms for :scope. 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); Notes: 1. I don't think browsers should provide queryScopedSelector*() This seems contradictory. You seemed to be proposing that we use queryScopedSelector, and now you're saying we shouldn't. Personally, I agree that we shouldn't. It's my least favourite solution of them all. I don't think implied ":scope" selector text should be supported at all. It's a whim of the JS libraries. I'm just concerned that if we do have it then at least it doesn't screw up the core functionality. 2. I think :context is a better name than :scope Yeah, the name of :scope is a complicated issue. :context isn't ideal either. It would be slightly confusing because selectors API defines the term "context node" as being the node upon which the method is being invoked. Maybe something like :ref or :reference might work. Yeah. 3. If the context argument of these methods could be an element or a NodeList it might satisfy some of the other feature requests. Yes, the reference elements parameter will accept either a single element, Array or NodeList. I have checked in a new draft containing my first attempt at supporting scoped selectors, with support for both :scope (or whatever it gets called) and implied scope selectors. I've opted for a combination of options 1 and 2 that I previously described, using the createSelector() and SelectorExpression object for being able to represent implied scoped selectors easily, and optional refNodes parameters on querySelector*() and matchesSelector() methods for supplying contextual reference elements (that match :scope). Basically, for the simple case, it works as illustrated in these examples: elm.querySelector(":scope>p"); document.querySelectorAll(":scope>p", elm); document.querySelectorAll(":scope>p", [elm1, elm2]); To provide the functionality of JS libraries supporting implied scope selectors, you first create a SelectorExpression object like this: document.createSelector(">em,>strong", true); That object can then be passed to either the querySelector*() or matchesSelector() methods. The effect of this is basically that JavaScript libraries can mostly use document.createSelector(str, true) as a direct replacement their own custom selector parsing libraries (except for the cases where they're using custom pseudo-classes not supported by the browser) One possible modification I'm considering is introducing a separate factory method for creating implied scope selectors: createScopedSelector(selector); rather than using a boolean parameter. Looks okay, except I don't think there should be implied contextual reference elements. What are the chances that we will have to extend createSelector in the future? e.g. namespaces
Re: [selectors-api] Scoped Selectors
> 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. > I don't see the purpose of making a distinction between the root node used for the query and the node being used for the scope - they should be one and the same. // Doesn't make sense: document.querySelectorAll("div div", document.body) // Does make sense document.body.querySelectorAll("div div") Also, I don't think it's been made clear in the discussion thus far but while cases like handling "> div" are nice - we're mostly concerned about cases like "div div" (that escape outside the original root of the query). Given this DOM: // All of these should return nothing document.getElementById("one").querySelelctor("div div") document.getElementById("one").querySelelctor("body div") document.getElementById("one").querySelelctor("div #two") > *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. > There doesn't need to be scoping for matchesSelector. matchesSelector implies that it it's starting from the specified node and doing a match. Additionally the use case of .matchesSelector("> div") doesn't really exist. With that in mind, option #3 looks the best to me. It's lame that the API will be longer but we'll be able to use basic object detection to see if it exists. Unfortunately the proper scoping wasn't done the first time the Selectors API was implemented so we kind of have to play the hand we've been dealt. Thus there would be two new methods: queryScopedSelectorAll queryScopedSelector Same length as getElementsByClassName - long but not untenable. --John
Re: [selectors-api] Scoped Selectors
On 9/25/09 9:59 AM, Lachlan Hunt wrote: Yes, the reference elements parameter will accept either a single element, Array or NodeList. What about HTMLCollection? Or have we finally made that interface inherit from NodeList? Another question I just had reading this, and this is probably a webidl question, not a selectors API question, is what makes something an element, array, or nodelist. First off, what if some spec introduces objects that implement both the Element and NodeList interfaces? Second, what if I do: function foo() { } foo.prototype = Array.prototype var myObj = new foo(); Is that an array? How should the callee be able to determine this? What about: var elm = document.createElement("div"); function foo() { } foo.prototype = elm; var myObj = new foo(); For what it's worth, it looks like in this case myObj.appendChild(document.createTextNode("test")) appends to |elm| in Gecko and Google Chrome, throws WRONG_THIS_ERR in Opera, and throws "Type error" in Safari. Doing document.body.appendChild(myObj) throws WRONG_ARGUMENTS_ERR in Opera, throws NOT_FOUND_ERR in Safari and Chrome, and throws HIERARCHY_REQUEST_ERR in Gecko How is this case different from the array case, if at all? -Boris
Re: [selectors-api] Scoped Selectors
Sean Hogan wrote: Here's a proposal. querySelector*(selector, context) // allows selectors with :scope pseudo-class queryScopedSelector*(selector, context) // allows selectors with implied :scope matchesSelector(selector, context) // allows selectors with :scope pseudo-class Yes, this is effectively the same as option #2 that I described, except you haven't provided a way to support implied scope there. To check if the :scope pseudo-class is available, use: try { document.body.matchesSelector(":scope", document.body); } catch (error) { /* not supported */ } I'm not sure that relying on exceptions for feature testing is an ideal way to provide that functionality. 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*(). Well, we at least need some way to tell the implementation to pre-process the selector to imply the presence of :scope. queryScopedSelector*() would do this, as would providing an explicit pre-processing step, the result of which can be passed to the querySelector*() methods. 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); Notes: 1. I don't think browsers should provide queryScopedSelector*() This seems contradictory. You seemed to be proposing that we use queryScopedSelector, and now you're saying we shouldn't. Personally, I agree that we shouldn't. It's my least favourite solution of them all. 2. I think :context is a better name than :scope Yeah, the name of :scope is a complicated issue. :context isn't ideal either. It would be slightly confusing because selectors API defines the term "context node" as being the node upon which the method is being invoked. Maybe something like :ref or :reference might work. 3. If the context argument of these methods could be an element or a NodeList it might satisfy some of the other feature requests. Yes, the reference elements parameter will accept either a single element, Array or NodeList. I have checked in a new draft containing my first attempt at supporting scoped selectors, with support for both :scope (or whatever it gets called) and implied scope selectors. I've opted for a combination of options 1 and 2 that I previously described, using the createSelector() and SelectorExpression object for being able to represent implied scoped selectors easily, and optional refNodes parameters on querySelector*() and matchesSelector() methods for supplying contextual reference elements (that match :scope). Basically, for the simple case, it works as illustrated in these examples: elm.querySelector(":scope>p"); document.querySelectorAll(":scope>p", elm); document.querySelectorAll(":scope>p", [elm1, elm2]); To provide the functionality of JS libraries supporting implied scope selectors, you first create a SelectorExpression object like this: document.createSelector(">em,>strong", true); That object can then be passed to either the querySelector*() or matchesSelector() methods. The effect of this is basically that JavaScript libraries can mostly use document.createSelector(str, true) as a direct replacement their own custom selector parsing libraries (except for the cases where they're using custom pseudo-classes not supported by the browser) One possible modification I'm considering is introducing a separate factory method for creating implied scope selectors: createScopedSelector(selector); rather than using a boolean parameter. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: [selectors-api] Scoped Selectors
Sean Hogan wrote: Hi Lachy, Here's a proposal. querySelector*(selector, context) // allows selectors with :scope pseudo-class queryScopedSelector*(selector, context) // allows selectors with implied :scope matchesSelector(selector, context) // allows selectors with :scope pseudo-class To check if the :scope pseudo-class is available, use: try { document.body.matchesSelector(":scope", document.body); } catch (error) { /* not supported */ } OR try { document.querySelector(":scope", document.body); } catch (error) { /* not supported */ } Sorry. Replace document.body with document.documentElement. That should be more efficient for the querySelector test.
Re: [selectors-api] Scoped Selectors
Hi Lachy, Here's a proposal. querySelector*(selector, context) // allows selectors with :scope pseudo-class queryScopedSelector*(selector, context) // allows selectors with implied :scope matchesSelector(selector, context) // allows selectors with :scope pseudo-class To check if the :scope pseudo-class is available, use: try { document.body.matchesSelector(":scope", document.body); } catch (error) { /* not supported */ } OR 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); Notes: 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 select
[selectors-api] Scoped Selectors
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. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/