Re: Proposed Specification for find/findAll/matches

2011-12-19 Thread Lachlan Hunt

On 2011-12-12 17:57, Boris Zbarsky wrote:

On 12/12/11 6:07 AM, Lachlan Hunt wrote:

2. These new methods for Element may be split out to a separate
interface that omits the refElements and and refNodes parameters.


Yes, please. There's no point having the same interface if the behavior
is totally different based on the |this| object as described. In my
opinion.


I did this by defining partial interfaces for each of Document, 
DocumentFragment and Element, rather than having a single NodeSelector 
interface implemented by all three.



Open Issue: Should this change affect Element.querySelector() too, or
leave it as currently specified?


One option is to simply not do any special scope stuff in querySelector,
if we suddenly have no use cases for it.


I removed the refNodes stuff from querySelector, since all use cases for 
it are covered by find/findAll.



Given a selector list as input to the method, trim whitespace and then
for each complex selector, run the first step that applies:

(Note: if the selector list is , then there are 0 complex selectors in
the list and the following doesn't run)

| 1. Otherwise, if the complex selector begins with any combinator


This needs to be defined better. complex selector can't begin with a
combinator, per its definition.


I defined the concept of a relative selector a custom grammar to 
handle this better.


I also started updating the draft to use Selectors 4 and DOM4 references 
and terminology.  Some DOM3 references still remain, but they'll be 
changed eventually.  This meant the removal of terms like context node 
in favour of context object defined in DOM4, among others.


The editor's draft is here.

http://dev.w3.org/2006/webapi/selectors-api2/#the-apis

--
Lachlan Hunt - Opera Software
http://lachy.id.au/
http://www.opera.com/



Re: Proposed Specification for find/findAll/matches

2011-12-13 Thread Lachlan Hunt

On 2011-12-12 17:57, Boris Zbarsky wrote:

On 12/12/11 6:07 AM, Lachlan Hunt wrote:

Given a selector list as input to the method, trim whitespace and then
for each complex selector, run the first step that applies:

(Note: if the selector list is , then there are 0 complex selectors in
the list and the following doesn't run)

| 1. Otherwise, if the complex selector begins with any combinator


This needs to be defined better. complex selector can't begin with a
combinator, per its definition.


For the purposes of this API, I think the spec needs to define a 
modified syntax for a DOM Selector, which is similar to, but slightly 
different from a regular selector. The grammar production would be:


dom_selectors_group
  : dom_selector [ COMMA S* dom_selector ]*
  ;

dom_selector
  : [ combinator ]? selector
  ;

Where the productions for combinator and selector are defined in 
Selectors.  The spec would then define that the parameter accepts a 
group of DOM selectors that matches that grammar.


--
Lachlan Hunt - Opera Software
http://lachy.id.au/
http://www.opera.com/



Re: Proposed Specification for find/findAll/matches

2011-12-13 Thread Yehuda Katz
This proposal looks really good and matches my expectations.

Yehuda Katz
(ph) 718.877.1325


On Tue, Dec 13, 2011 at 3:53 AM, Lachlan Hunt lachlan.h...@lachy.id.auwrote:

 On 2011-12-12 17:57, Boris Zbarsky wrote:

 On 12/12/11 6:07 AM, Lachlan Hunt wrote:

 Given a selector list as input to the method, trim whitespace and then
 for each complex selector, run the first step that applies:

 (Note: if the selector list is , then there are 0 complex selectors in
 the list and the following doesn't run)

 | 1. Otherwise, if the complex selector begins with any combinator


 This needs to be defined better. complex selector can't begin with a
 combinator, per its definition.


 For the purposes of this API, I think the spec needs to define a modified
 syntax for a DOM Selector, which is similar to, but slightly different from
 a regular selector. The grammar production would be:

 dom_selectors_group
  : dom_selector [ COMMA S* dom_selector ]*
  ;

 dom_selector
  : [ combinator ]? selector
  ;

 Where the productions for combinator and selector are defined in
 Selectors.  The spec would then define that the parameter accepts a group
 of DOM selectors that matches that grammar.


 --
 Lachlan Hunt - Opera Software
 http://lachy.id.au/
 http://www.opera.com/




Proposed Specification for find/findAll/matches

2011-12-12 Thread Lachlan Hunt

Hi,
  I have reviewed all of the recent discussion and spent some time 
analysing JQuery, and I have compiled this rough specification detailing 
how I think find, findAll and matches can work.  The following details 
the rationale for each of the design decisions made.


The new methods should be available on documents, document fragments and 
elements, just like querySelector.  The easiest approach is to put these 
on the same NodeSelector interface as the existing methods.


This email is long and detailed. For those of you who just want the 
conclusion, skip to the the proposed IDL and summary.


---

*Table of Contents*:

1. Methods and Return Types
2. Document Methods
3. Document Fragment Methods
4. Element Methods
5. Match Testing
6. Proposed IDL
7. Summary of Proposed Spec Changes
8. Proposed Rules for Prepending :scope

---

1. *Methods and Return Types*

Throughout the discussion, there seems to be the assumption that we 
should have both find() and findAll() methods, which return a single 
matching element and a collection of all matches, respectively.  One 
issue to decide is, based on experience with and usage of 
querySelector() and querySelectorAll(), whether it worth introducing the 
same distinction for new methods, or would it be better to just go with 
a single method that returns a collection?  That is, is it really useful 
or better in practice to have the method that only returns the first match?


For the purposes of the rest of this email, however, I'll stick with the 
assumption that we'll introduce both find() and findAll().


There is also the open issue of what type of collection should be 
returned by findAll(), whether it be an Array or special kind of 
NodeList with an Array-like interface.  I have not addressed this issue 
in this proposal.


---

2. *Document Methods*

The document.findAll() method is supposed to be designed to more closely 
align with the behaviour of JQuery's global $() method, which is defined 
as an alias for the jQuery() method:


  jQuery( selector [, context] )

(Note: The other overloaded JQuery methods are not relevant.)
http://api.jquery.com/jQuery/

All script examples relate to the following sample document:

!DOCTYPE html
body
  p id=1/p
  div
p id=2/p
  /div
/body

JQuery results:
(Note: All results are returned as instances of jQuery objects, which 
are indexable like an array)


  $(html) // returns [html]
  $(body) // returns []
  $(+div) // returns []
  $(body, document.documentElement) // returns [body]
  $(p, $(body)) // returns [p#1]
  $(p, $(div)) // returns [p#2]
  $(+div, $(#1)) // returns [div]
  $(p, div, $(body)) // returns [p#1, div]

  $(body, []) // returns []
  $(body, null) // returns [body]
  $(body, undefined) // returns [body]
  $() // returns []

document.findAll() should support the same parameters as $() and return 
an equivalent result collection in the majority of cases.  Likewise, 
document.find() should work the same way, but return only the first 
match.  Where findAll() returns an empty collection, find() would return 
null.


From the above, it's clear that in the new API, there are cases where 
:scope should be implied and cases where it should not.  In cases where 
:scope is implied and there's no explicit combinator, a descendant 
combinator needs to be implied too.


  $(html) // returns [html]
  document.findAll(html)

:scope cannot be implied here because html is the root element, so it 
wouldn't match if the selector was interpreted as :scope html.


  $(body) // returns []
  document.findAll(body)

  $(+div) // returns []
  document.findAll(+div)

:scope needs to be implied to make a syntactically valid selectors, 
making them equivalent to :scopebody and :scope+div, respectively. 
But :scope cannot match the root element here because otherwise the 
first would return the body element as a match.


  $(body, document.documentElement) // returns [body]
  document.findAll(body, document.documentElement)

Like the previous case, :scope needs to be implied. This time, however, 
it needs to match the specified element node.  It also means that the 
second parameter must be able to accept an Element node.



  $(p, $(body)) // returns [p#1]
  document.findAll(p, $(body))
  document.findAll(p, document.findAll(body))

This is the same as the previous case, except a collection of elements 
is passed instead of a single Element node.  This is equivalent to 
:scopep, where :scope matches the elements in the collection.


It should work regardless of the type of collection.  In the first case, 
$() returns a numerically indexed JQuery object, the latter returns a 
yet to be defined Array-like structure.


  $(p, $(div)) // returns [p#2]
  document.findAll(p, document.findAll(div))

In this case, despite not beginning with a combinator, the presence of a 
reference node indicates that :scope with a descendant combinator should 
be implied, equivalent to :scope p.


  $(+div, $(#1)) // returns [div]
  

Re: Proposed Specification for find/findAll/matches

2011-12-12 Thread Tab Atkins Jr.
Thanks for doing the work here, Lachlan!  This appears to be an
excellent summary of the discussion and a consistent proposal.

On Mon, Dec 12, 2011 at 3:07 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 6. *Proposed IDL*

 interface NodeSelector {
  Element   find(DOMString selectors, optional Element refElement);
  Element   find(DOMString selectors, sequenceNode? refNodes);

  ???       findAll(DOMString selectors, optional Element refElement);
  ???       findAll(DOMString selectors, sequenceNode? refNodes);
 };
 Document implements NodeSelector;
 DocumentFragment implements NodeSelector;
 Element implements NodeSelector;

 This extends the same interface as that the existing querySelector methods
 use, which will make the methods available on elements, documents and
 fragments.

 Open Issues:

 1. The return type for findAll is yet to be decided. It may be the
   proposed NodeArray, a regular Array or something else.

It really needs to be NodeArray or whatever, so we can hang
.find/All() and many other useful methods off of it.


 2. These new methods for Element may be split out to a separate
   interface that omits the refElements and and refNodes parameters.

I'd agree with this.  Given that the refs are ignored on Element,
there's no reason to keep them in the IDL; it'll just be confusing.

 3. Do we need both find() and findAll(), or should we only have a
   single new method that returns a collection?

I'm still slightly for only having the single method that returns a
collection, but the original arguments for having a single-node
version still hold (efficiency, etc.), and many people still want it,
so I'm fine with it.

 Additionally, matchesSelector() will simply be renamed to matches().

With the detail (specified below) that it'll imply scope the same way
that .find() does, this is excellent.

 Open Issue: Should findAll() and find() throw SYNTAX_ERR or return empty
 collection and null, respectively?

No opinion on this.  I've never used  in jQuery.  I assume it can be
used when you've built a selector in a switch or if-chain, and one of
the cases is just use the same elements again.  However, in our
method you can just use :scope for that, so it doesn't seem
necessary to support it with the empty-string case as well.


Your :scope prepending rules look good as well.

~TJ