- From: John Resig <jresig@mozilla.com>
- Date: Thu, 24 Sep 2009 14:43:33 -0400
- To: Lachlan Hunt <lachlan.hunt@lachy.id.au>
- Cc: public-webapps <public-webapps@w3.org>
- Message-ID: <730bab940909241143v56271ad4tffff47fe4a71621c@mail.gmail.com>
> Not quite. It depends what's being done and which steps need to be > performed and how. AIUI, there are 3 major steps involved here. > > 1. Obtain a collection of Elements. This could be in one or more > Arrays and/or NodeLists, depending on th. > 2. Iteratively execute a selector query on all elements in the > collection, saving the results from each. > 3. Merge and sort all elements into a single NodeList, removing > duplicates. > > In order to understand which of those steps need to be optimised by the > browser with new APIs, it would help if you could explain some typical > tasks, or use cases, that would need to perform any or all of those steps. > > In particular, what type of task would lead to there being more than one > Array and/or NodeList to be used as input to step 2? > var foo = document.querySelectorAll("div.foo"); // do stuff with the divs... var bar = document.querySelectorAll("div.bar"); // do stuff with the divs... var items = document.createNodeList(foo, bar).querySelectorAll("ul.items"); // do stuff with the items... Alternatively, in jQuery we would be doing something like this: var foo = $("div.foo"); // do stuff with the divs... var bar = $("div.bar"); // do stuff with the divs... var items = foo.add( bar ).find("ul.items"); // do stuff with the items... The important thing here is that: 1) There is only one sub-query being done. 2) That all the ul.items are being aggregated into a single collection, in document order. > What type of task would require executing the same selector query over a > whole collection of elements? > The most important case is where there's additional filtering being done. For example, in jQuery you can do: $("div.foo") .bind("click", function(){}) .find("span") .addClass("foo"); This reduces the total number of query operations down to two if it was possible to run it against a complete collection. > And what task would require the results of those to be merged into a single > list? The case where $("div").parents() is done, for example. This is a custom query where we return a set of ancestor elements for each of the divs. This is not something that I would expect the Selectors API to support but the case of merging those results, sorting them, and uniqueing them is taking place and is very costly. To explain what I mean, let's look at a simple DOM: <html> <body> <div id="one"> <div id="two"></div> </div> </body> </html> $("div").parents() should return: [ html, body, div#one, div#two ] naturally if this query is being done on two elements the result set will need to be merged/sorted/uniqued before it can be returned. > It would be great to have a separate, standalone, function that handles >>> >>>> these merge/sort/unique operations for collections of DOM elements >>>> (especially if they're disconnected from the document!). >>>> >>>> The proposal from my previous mail falls into Option A. Would it >>> address >>> this issue adequately? Specifically, defining document.createSelector() >>> and >>> a Selector interface that allows running a query like this: >>> >>> var elements = [...] // Some Array (or NodeList) of Elements >>> var selector = document.createSelector("em, strong"); >>> var list = selector.querySelectorAll(elements); >>> >>> This is equivalent to iterating over the elements array, running >>> elements[i].querySelectorAll("em, strong") on each, and then >>> merging/sorting >>> all of the results into a single collection. >>> >> >> Not a huge fan of that - it seems really backwards. >> > > Could you elaborate? > Right now we have (Document|Element|DocumentFragment).querySelectorAll(selector) - this makes sense - you're going from your base root and finding sub-elements using the selector. You're proposing sticking the selector some place else and using the selector as the root, sort of, then passing the collection of elements as some sort of filter? It's completely backwards. > Another alternative would be to implement the merge/sort/unique >> method and have it return a NodeList (which would, then, have qSA). >> > > The collection of elements (step 1, above) input into the qSA step (step 2) > wouldn't need to be a sorted list. Technically, it doesn't even necessarily > have to be a merged list if the API allows multiple arrays and/or nodelists > to be provided. It will have no effect on the result. The important point > seems to be that a collection of elements can be provided somehow and that > the implementation can execute the query on each distinct element in that > collection. How exactly that is done is just an API design issue. Sure - but we can kill two birds with one API stone. Having a document.createNodeList gives us merge/sort/unique (yay!) and it makes NodeList.querySelectorAll and NodeList.matchesSelector doubly-useful (yay! - since they can now be used for normal NodeLists and for array-like collections, thanks to createNodeList). --John
Received on Thursday, 24 September 2009 18:44:37 UTC