- From: Lachlan Hunt <lachlan.hunt@lachy.id.au>
- Date: Fri, 21 Oct 2011 15:45:42 +0200
- To: public-webapps <public-webapps@w3.org>
- CC: Alex Russell <slightlyoff@google.com>
Hi, Based on the ongoing discussion, I've put together the following list of requirements and sumarised use cases that should be met by the design of new features in selectors API. *Use Cases* 1. Select elements that are descendants of specific Element node, where all elements matched by the chain of selectors are all descendants of that element. <section> <h1>A</h1> <div id="foo"> <h1>B</h1> <section> <h1>C</h1> </section> </div> <section> <h1>D</h1> </section> </section> e.g. JQuery $("#foo").find("section h1") This should find heading C only. 2. Select elements that is a child of a specific Element node. e.g. $("#foo").find(">h1") 3. Select elements that are siblings (adjacent + or general ~) of a specific Element node. e.g. $("#foo").find("+section h1") $("#foo").find("~section h1") 4. Select elements relative to a specific Element node, conditionally based on it's own state. e.g. (Pseudo code) if Element foo has class name "X", Select descendant elements matching "input[type=radio]" Otherwise, if Element foo has class name "Y" Select descendant elements matching "input[type=checkbox]" Alternatively, foo = document.getElementById("foo"); inputs = foo.querySelectorAll(".X:scope input[type=radio], .Y:scope input[type=checkbox]"); 5. Select elements relative to a specific Element node, conditionally based on the state of an ancestor or previous sibling element. e.g. (Pseudo code) if ancestor Element section has class name "X", Select descendant elements matching "input[type=radio]" Otherwise, if ancestor Element section has class name "Y" Select descendant elements matching "input[type=checkbox]" foo = document.getElementById("foo"); inputs = foo.querySelectorAll("section.X :scope input[type=radio], section.Y :scope input[type=checkbox]"); *General* * Method names should be short, memorable and easy to type. - querySelectorAll is considered too long by authors. * Methods should prioritise optimisations for the common cases over full flexibility. Less common and more complex cases can be handled by existing methods. - Use cases 4 and 5 may be left to existing methods, depending on complexity they introduce and the impact upon potential optimisations. i.e. The cost vs. benefit of supporting them in new methods. * Optimisations should consider both authors and implementations *Implicit Scoping* * In the common case, when called on an element, selectors should be scoped relative to the context element * In the common case when called on the document, it either: - Search the whole document, or - Be scoped relative to a collection of reference elements * Support matching descendants, next siblings and their descendants * Should avoid matching ancestors or previous siblings - (See reference combinator issue below) *Syntax* * Should not require authors to explicitly use :scope, at least when it occurs at the beginning. * Selectors should be able to begin with combinators, :scope should be implied at the beginning. *Return Value* * Methods should return either a single Element node and/or an collection of elements * A collection of Elements should be - Mutable - Static, not live - Support all, or at least some, methods from Array. Need to determine which functionality is most important. - JS Libraries use Array.slice hack to convert a NodeList to an Array. This is a sub-optimal solution. *Implementation Optimisations* * It should be possible to, at least in the common cases, to limit the set of potential matches to a subset of the document. - This reduces the number of comparisons that need to be done and thus time to compute the result. * Ideally, it should be possible to determine heuristically from the Selector whether the impelemntation needs to check: - Only context element's descendants (descendant or child combinators) - Only context element's siblings (sibling combinators) - Both Issue: What should happen with the new reference combinator? label.find("/for/ input"); div.find("label /for/ input") div.find(">label /for/ input + span") * What would authors expect the result to be? * Should these search: - The whole document (or whole tree, if disconnected from document)? - Only descendants? - Only descendants and siblings? - Other subset of the document? * How does each option affect performance? * Are there any possible optimisations for these cases? e.g. <label for="foo">Label</label> <input type="text" name="a" id="foo"> <input type="text" name="b" id="foo"> "label /for/ input" matches both inputs, just like "#foo" Note: If you have anything to add, please do so. I'll be on holiday and mostly offline for the next 3 weeks. I'll review any additional discussion and attempt to draft up a possible solution in the spec after I get back from holidays. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Received on Friday, 21 October 2011 13:46:21 UTC