John Resig wrote:
Filtering NodeLists/StaticNodeLists, Queries on NodeLists/StaticNodeLists:
Neither of these are useful, as is, to libraries.
I believe this would be handled using the Array.filter() method, with a
callback that checks if the selector matches the element, as Jonas pointed
out:
filteredArray = myArrayOfNodes.filter(function(node) { return
node.matchesSelector("some>selector"); });
(That could also work with the above Selector.matches() proposal)
Array.filter() will meet the need of filtering
NodeLists/StaticNodeLists/Arrays of Elements - sure - but it won't meet the
need of NodeList.querySelectorAll (especially if that works with an
array-like collection of DOM elements).
Right, but I'm dealing with that as an entirely separate issue, which I
disucssed later on in that email.
Basic filtering of nodelists is bug 5864, which I've resolved WONTFIX
for now because the functionality doesn't seem too desirable or beneficial.
http://www.w3.org/Bugs/Public/show_bug.cgi?id=5864
The issue you're discussing is bug 7707, which is still open.
http://www.w3.org/Bugs/Public/show_bug.cgi?id=7707
The problem is that when you have multiple collections of DOM elements and
you wish to reduce them to a single collection it ends up being a very
expensive task. The steps are as follows:
- The collections must be merged together into a single array of DOM
elements.
- The elements must be sorted to be in document order.
- Duplicate elements must be removed from the collection.
So the question is, at which point in the chain do you want to address
this issue? The options are:
A) Have specific selectors API feauture that allowed executing a
selector query on a whole collection of elements that returns a
single, sorted collection of unique elements.
B) A more generic API for being able to easily merge and sort
NodeLists/Arrays of elements.
Option A saves the step of having to run the queries on each individual
element manually and just returns a merged and sorted collection of
unique elements. But it's limited to running selector queries, rather
than any other getElementsBy*() method to obtain the results.
Option B is more generic in that it could potentially merge and sort any
set of NodeLists, and those NodeLists could be obtained by any method,
but would still require running the queries on each element individually
to obtain the the lists that then need to be merged.
Both options present an issue with sorting, since they could result in
lists that contain both connected and disconnected elements, and the
sort order for connected elements in relation to disconnected elements
would need to be defined.
Option B seems potentially harder to define and possibly implement,
especially if you want to be able to sort merge NodeList objects with
Array objects. Since Arrays aren't limited to just containing DOM
Nodes, the issue of what to do with other types objects and how to sort
them along with the Nodes is complicated.
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.
If there was a merge/sort/unique method it would drop the need for having a
NodeList/Array.querySelectorAll.
Whether we should go for the extra complexity required for this really
depends on the use case you're trying to address. Do you just need to
merge NodeLists that are all obtained via querySelector methods, or do
you need to merge any random NodeLists or Arrays that could be obtained
via querySelector*() or getElementsBy*(), or wherever else.
--
Lachlan Hunt - Opera Software
http://lachy.id.au/
http://www.opera.com/