- From: Alex Russell <slightlyoff@google.com>
- Date: Wed, 19 Oct 2011 01:00:01 +0100
- To: Matt Shulman <mattsh@google.com>
- Cc: Webapps WG <public-webapps@w3.org>, Yehuda Katz <wycats@gmail.com>, John Resig <jeresig@gmail.com>, Paul Irish <paulirish@google.com>, Lachlan Hunt <lachlan.hunt@lachy.id.au>
Hi Matt, On Tue, Oct 18, 2011 at 6:25 PM, Matt Shulman <mattsh@google.com> wrote: > I think the query selector functionality is important enough that one > could easily justify adding additional APIs to make this work > better/faster, even if they overlap with existing APIs. But, it would > be unfortunate if more APIs were added to the DOM and libraries still > weren't able to use them because the semantics didn't end up being > quite right. > It seems like the right approach would be to take jquery and rewrite > it to use this new API and then see empirically whether it gives the > same selection behavior as before and see how much of a performance or > simplicity gain there is after doing this. No need to wait. We had something nearly identical for this in Dojo using an ID prefix hack. It looked something like this: (function(){ var ctr = 0; query = function(query, root){ root = root||document; var rootIsDoc = (root.nodeType == 9); var doc = rootIsDoc ? root : (root.ownerDocment||document); if(!rootIsDoc || (">~+".indexOf(query.charAt(0)) >= 0)){ // Generate an ID prefix for the selector root.id = root.id||("qUnique"+(ctr++)); query = "#"+root.id+" "+query; } return Array.prototype.slice.call( doc.querySelectorAll(query) ); }; })(); This is exactly the same dance that ":scope" does. > (I think it's a good thing to allow selectors to start with > combinators. That seems very useful.) > > On Tue, Oct 18, 2011 at 9:47 AM, Alex Russell <slightlyoff@google.com> wrote: >> On Tue, Oct 18, 2011 at 5:42 PM, Alex Russell <slightlyoff@google.com> wrote: >>> Lachlan and I have been having an...um...*spirited* twitter discussion >>> regarding querySelectorAll, the (deceased?) queryScopedSelectorAll, >>> and ":scope". He asked me to continue here, so I'll try to keep it >>> short: >>> >>> The rooted forms of "querySelector" and "querySelectorAll" are mis-designed. >>> >>> Discussions about a Scoped variant or ":scope" pseudo tacitly >>> acknowledge this, and the JS libraries are proof in their own right: >>> no major JS library exposes the QSA semantic, instead choosing to >>> implement a rooted search. >>> >>> Related and equally important, that querySelector and querySelectorAll >>> are often referred to by the abbreviation "QSA" suggests that its name >>> is bloated and improved versions should have shorter names. APIs gain >>> use both through naming and through use. >> >> Sorry, this should say "meaning". APIs gain *meaning* through both use >> and naming. >> >>> On today's internet -- the >>> one where 50% of all websites include jQuery -- you could even go with >>> element.$("selector") and everyone would know what you mean: it's >>> clearly a search rooted at the element on the left-hand side of the >>> dot. >>> >>> Ceteris peribus, shorter is better. When there's a tie that needs to >>> be broken, the more frequently used the API, the shorter the name it >>> deserves -- i.e., the larger the component of its meaning it will gain >>> through use and repetition and not naming and documentation. >>> >>> I know some on this list might disagree, but all of the above is >>> incredibly non-controversial today. Even if there may have been >>> debates about scoping or naming when QSA was originally designed, >>> history has settled them. And QSA lost on both counts. >>> >>> I therefore believe that this group's current design for scoped >>> selection could be improved significantly. If I understand the latest >>> draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class) >>> correctly, a scoped search for multiple elements would be written as: >>> >>> element.querySelectorAll(":scope > div > .thinger"); >>> >>> Both then name and the need to specify ":scope" are punitive to >>> readers and writers of this code. The selector is *obviously* >>> happening in relationship to "element" somehow. The only sane >>> relationship (from a modern JS hacker's perspective) is that it's >>> where our selector starts from. I'd like to instead propose that we >>> shorten all of this up and kill both stones by introducing a new API >>> pair, "find" and "findAll", that are rooted as JS devs expect. The >>> above becomes: >>> >>> element.findAll("> div > .thinger"); >>> >>> Out come the knives! You can't start a selector with a combinator! >>> >>> Ah, but we don't need to care what CSS thinks of our DOM-only API. We >>> can live and let live by building on ":scope" and specifying find* as >>> syntactic sugar, defined as: >>> >>> HTMLDocument.prototype.find = >>> HTMLElement.prototype.find = function(rootedSelector) { >>> return this.querySelector(":scope " + rootedSelector); >>> } >>> >>> HTMLDocument.prototype.findAll = >>> HTMLElement.prototype.findAll = function(rootedSelector) { >>> return this.querySelectorAll(":scope " + rootedSelector); >>> } >>> >>> Of course, ":scope" in this case is just a special case of the ID >>> rooting hack, but if we're going to have it, we can kill both birds >>> with it. >>> >>> Obvious follow up questions: >>> >>> Q.) Why do we need this at all? Don't the toolkits already just do >>> this internally? >>> A.) Are you saying everyone, everywhere, all the time should need to >>> use a toolkit to get sane behavior from the DOM? If so, what are we >>> doing here, exactly? >>> >>> Q.) Shorter names? Those are for weaklings! >>> A.) And humans. Who still constitute most of our developers. Won't >>> someone please think of the humans? >>> >>> Q.) You're just duplicating things! >>> A.) If you ignore all of the things that are different, then that's >>> true. If not, well, then no. This is a change. And a good one for the >>> reasons listed above. >>> >>> Thoughts? >>> >> >> >
Received on Wednesday, 19 October 2011 00:01:38 UTC