Re: Remaining Problems with Explicit :scope Switching in find/findAll (was: Re: [Selectors API 2] Is matchesSelector stable enough to unprefix in implementations?)
On Thursday, November 24, 2011, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-11-24 00:52, Yehuda Katz wrote: On Wed, Nov 23, 2011 at 2:38 PM, Sean Hoganshogu...@westnet.com.au wrote: The alternative option (find / findAll / matches can accept explicit :scope, but will otherwise imply :scope) seems to be where all the ambiguity lies. What exact cases are ambiguous with find/findAll/matches can accept explicit :scope, but will otherwise imply :scope? The problems to be solved with automatically switching between implied and explicit :scope are basically in determining what exactly counts as an explicit :scope. The answers to each of these has is trade off between complexity and functionality, with the simplest option being always implying :scope. * Is explicit :scope allowed at the beginning of each selector? find(:scopediv); find(body.foo :scopediv); * Does :scope inside functional pseudo-classes count? find(:not(:scope)); find(:matches(:scope)); If yes, does the first match the whole document, only descendants, or descendants plus siblings? * If using an explicit :scope, can it match itself? find(:scope) // Return null or the element itself? * Is :scope always implied if it begins with an explicit combinator other than descendant, even if :scope is used elsewhere? find(div :scope); find(+div :scope); find(~div :scope); Here is what I sent to the list on Nov 10th. Though it didn't get archived so maybe it didn't go through properly: 1. Start with an empty list 2. Skip any whitespace at the beginning of the string. 3. If the next character is a , a + or a ~, insert a simple selector[1] containing just the :scope pseudo selector at the beginning of the selector. 4. Parse as a selector[1]. If there's a parse error throw an SyntaxError exception. 5. If during parsing a :scope pseudo class was parsed, and if a :scope pseudo selector was added in step 2, throw a SyntaxError exception. 6. If during parsing no :scope pseudo class was parsed, and if no :scope pseudo selector was added in step 2, add a simple selector containing just the :scope pseudo class to the beginning of the list, and use a descendant selector as combinator to the rest of the selector. 7. Add selector to the end of list created in step 1. 8. If, after skipping any whitespace, the next character is a comma, skip the comma and go to step 2. The resulting selector list is evaluated against the document node, but with :scope matching the node that .find/.findAll was called on. .findAll returns all nodes which match the selector in document order. .find returns the first node in the list of nodes that .findAll returns, or null if the list is empty. The reason I suggested to throw in step 5 was that such a selector would never match anything and so must be a bug. But maybe that isn't the case for /for/. More below. * There's also the general issue, not related to :scope, about how the reference combinator affects the range of potential matches. label.find(/for/ input) Based on the above issues, what happens in this case? foo.find(label /for/ input+:scope~span) Can this expression ever match anything if we prepend :scope? Would simply removing step 5 above make the steps work for this case too? / Jonas
Remaining Problems with Explicit :scope Switching in find/findAll (was: Re: [Selectors API 2] Is matchesSelector stable enough to unprefix in implementations?)
On 2011-11-24 00:52, Yehuda Katz wrote: On Wed, Nov 23, 2011 at 2:38 PM, Sean Hoganshogu...@westnet.com.au wrote: The alternative option (find / findAll / matches can accept explicit :scope, but will otherwise imply :scope) seems to be where all the ambiguity lies. What exact cases are ambiguous with find/findAll/matches can accept explicit :scope, but will otherwise imply :scope? The problems to be solved with automatically switching between implied and explicit :scope are basically in determining what exactly counts as an explicit :scope. The answers to each of these has is trade off between complexity and functionality, with the simplest option being always implying :scope. * Is explicit :scope allowed at the beginning of each selector? find(:scopediv); find(body.foo :scopediv); * Does :scope inside functional pseudo-classes count? find(:not(:scope)); find(:matches(:scope)); If yes, does the first match the whole document, only descendants, or descendants plus siblings? * If using an explicit :scope, can it match itself? find(:scope) // Return null or the element itself? * Is :scope always implied if it begins with an explicit combinator other than descendant, even if :scope is used elsewhere? find(div :scope); find(+div :scope); find(~div :scope); * There's also the general issue, not related to :scope, about how the reference combinator affects the range of potential matches. label.find(/for/ input) Based on the above issues, what happens in this case? foo.find(label /for/ input+:scope~span) -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: Remaining Problems with Explicit :scope Switching in find/findAll (was: Re: [Selectors API 2] Is matchesSelector stable enough to unprefix in implementations?)
On Thu, Nov 24, 2011 at 12:50 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-11-24 00:52, Yehuda Katz wrote: On Wed, Nov 23, 2011 at 2:38 PM, Sean Hoganshogu...@westnet.com.au wrote: The alternative option (find / findAll / matches can accept explicit :scope, but will otherwise imply :scope) seems to be where all the ambiguity lies. What exact cases are ambiguous with find/findAll/matches can accept explicit :scope, but will otherwise imply :scope? The problems to be solved with automatically switching between implied and explicit :scope are basically in determining what exactly counts as an explicit :scope. The answers to each of these has is trade off between complexity and functionality, with the simplest option being always implying :scope. * Is explicit :scope allowed at the beginning of each selector? find(:scopediv); find(body.foo :scopediv); Anywhere within the selector. * Does :scope inside functional pseudo-classes count? find(:not(:scope)); find(:matches(:scope)); If yes, does the first match the whole document, only descendants, or descendants plus siblings? Yes, I believe so. The first matches the whole document except for the scoping element. The second matches only the scoping element. * If using an explicit :scope, can it match itself? find(:scope) // Return null or the element itself? Yes, because selectors with an explicit scope are evaluated against the whole document. (Selectors with an implicit scope are too, theoretically, though implementations can optimize.) That example returns the element itself. * Is :scope always implied if it begins with an explicit combinator other than descendant, even if :scope is used elsewhere? find(div :scope); find(+div :scope); find(~div :scope); Yes. * There's also the general issue, not related to :scope, about how the reference combinator affects the range of potential matches. label.find(/for/ input) Based on the above issues, what happens in this case? foo.find(label /for/ input+:scope~span) This is equivalent to prepending :scope to the selector, and evaluating it against the whole document. In other words, it finds a span that is preceded by the scope which is immediately preceded by an input which is referenced by a label which is a child of the scope. So, the rules end up being very simple. find always evaluates against the whole document. If one of the selectors starts with a combinator or doesn't contain a :scope pseudoclass somewhere in it, :scope is prepended to it. That's it. With this, we make the most common cases (searching descendants/siblings) easy, while making the global case *also* easy. There's a bit of intent-guessing when :scope is used in an indirect way, but I believe it's better to err on the side of simplicity and consistency there. ~TJ