- From: Yehuda Katz <wycats@gmail.com>
- Date: Tue, 25 Oct 2011 10:43:12 -0700
- To: Jonas Sicking <jonas@sicking.cc>
- Cc: Lachlan Hunt <lachlan.hunt@lachy.id.au>, "Tab Atkins Jr." <jackalmage@gmail.com>, 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>
- Message-ID: <CAMFeDTXABJ9EA7D49uUvxrwNcPQUAQARaOpoVZGBWC2EZeV7uA@mail.gmail.com>
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 Yehuda Katz (ph) 718.877.1325 On Fri, Oct 21, 2011 at 12:41 AM, Jonas Sicking <jonas@sicking.cc> wrote: > On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt <lachlan.hunt@lachy.id.au> > wrote: > > Not necessarily. It depends what exactly it means for a selector to > contain > > :scope for determining whether or not to enable the implied :scope > > behaviour. Consider: > > > > foo.find(":not(:scope)"); > > Ooh, this is an interesting case too. So here's the full list of cases > which we need defined behavior for (again looking at Alex and Yehuda here). > > In the following DOM > > <body id="3"> > <div id=0></div> > <div id="context" foo=bar> > <div id=1></div> > <div class="class" id=2></div> > <div class="withChildren" id=3><div class=child id=4></div></div> > </div> > <div id=5></div> > <div id=6></div> > </body> > > What would each of the following .findAll calls return. I've included my > guessed based on the discussions so far: > > var e = document.getElementById('context'); > > e.findAll("div") // returns ids 1,2,3,4 > e.findAll("") // returns an empty list > e.findAll("#3") // returns id 3, but not the body node > e.findAll("> div") // returns ids 1,2,3 > e.findAll("[foo=bar]") // returns nothing > e.findAll("[id=1]") // returns id 1 > e.findAll(":first-child") // returns id 1 > e.findAll("+ div") // returns id 5 > e.findAll("~ div") // returns id 5, 6 > e.findAll(":scope") > e.findAll("div:scope") > e.findAll("[foo=bar]:scope") > e.findAll(":scope div") > e.findAll("div:scope div") > e.findAll("div:scope #3") > e.findAll("body > :scope > div") > e.findAll("div, :scope") > e.findAll("body > :scope > div, :scope") > e.findAll(":not(:scope)") > > / Jonas
Received on Tuesday, 25 October 2011 17:43:59 UTC