- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Tue, 25 Oct 2011 13:41:14 -0700
- To: Yehuda Katz <wycats@gmail.com>
- Cc: Jonas Sicking <jonas@sicking.cc>, Lachlan Hunt <lachlan.hunt@lachy.id.au>, Boris Zbarsky <bzbarsky@mit.edu>, Ojan Vafai <ojan@chromium.org>, Alex Russell <slightlyoff@google.com>, Webapps WG <public-webapps@w3.org>, John Resig <jeresig@gmail.com>, Paul Irish <paulirish@google.com>
On Tue, Oct 25, 2011 at 10:43 AM, Yehuda Katz <wycats@gmail.com> wrote: > Your guesses are all right in terms of existing jQuery but one: > 'div': [1, 2, 3, 4] > '': [] > '#3': [3] > '> div': [1, 2, 3] > '[foo=bar]': [] > '[id=1]': [1] > ':first-child': [1, 4] > '+ div': [5] > '~ div': [5, 6] > You can see the results live at http://jsfiddle.net/Dj3Ab/. > The basic rule is that if there is no combinator, a descendent combinator is > implied. > jQuery returns an empty list with an empty String, but querySelectorAll > throws an exception (the spec says that the selector SHOULD match a slightly > loosened version of the selector production in > http://www.w3.org/TR/2009/PR-css3-selectors-20091215/#w3cselgrammar, which > disallows the empty string). It probably makes sense for find or findAll to > raise an exception too, but an empty list is fine too. > I'm not as sure about the :scope cases. I can make some guesses: > e.findAll(":scope") // context > e.findAll("div:scope") // context > e.findAll("[foo=bar]:scope") // context > e.findAll(":scope div") // 1,2,3,4 > e.findAll("div:scope div") // 1,2,3,4 > e.findAll("div:scope #3") // 3 > e.findAll("body > :scope > div") // 1,2,3 > e.findAll("div, :scope") // 0,context,1,2,3,4,5,6 > e.findAll("body > :scope > div, :scope") // context,1,2,3 > e.findAll(":not(:scope)") // all elements except context > > In cases where :scope is used, I would say that the selector behaves > identically to the "id hack" used by most JavaScript libraries. In > particular, the selector is relative to the root element, and the :scope > element simply represents the context element. > So you could change the :scope rules to be: > e.findAll("#context") // context > e.findAll("div#context") // context > e.findAll("[foo=bar]#context") // context > e.findAll("#context div") // 1,2,3,4 > e.findAll("div#context div") // 1,2,3,4 > e.findAll("div#context #3") // 3 > e.findAll("body > #context > div") // 1,2,3 > e.findAll("div, #context") // 0,context,1,2,3,4,5,6 > e.findAll("body > #context > div, #context") // context,1,2,3 > e.findAll(":not(#context)") // all elements except context > This also means that the above (non-:scope) rule could (I think) be restated > as: > > Each selector in a selector group passed to find or findAll has an implied > leading :scope > If no initial combinator is supplied, a descendent combinator is implied I'm no longer strongly convinced that we need to support :scope not at the front of the selector. el.find("foo :scope bar") is equivalent to first doing el.matches("foo :scope"), then running el.find("bar") if it does. This is slightly inconvenient with individual elements, but in the ideal future when .find returns a nice NodeList class that's a subtype of Array, the NodeList can have its own .filter and .find functions on it that automatically runs the operations over all the children and unions the results into a new NodeList. Then you can do elems.filter("foo :scope").find("bar"), and you're done. ~TJ
Received on Tuesday, 25 October 2011 20:42:02 UTC