Re: QSA, the problem with :scope, and naming

2011-12-07 Thread Lachlan Hunt

On 2011-10-20 10:14, Sean Hogan wrote:

The primary use-case for matchesSelector() has been event-delegation,
and this is the same for matches(). More specifically, consider the
following scenario:

jQuery adds a new event registration method that uses event delegation
to mimic the behavior of:
$(elem).find( div  .thinger).bind(eventType, fn);
The new method is called proxybind(), and the equivalent of the above is:
$(elem).proxybind( div  .thinger, eventType, fn);


I cannot find any documentation for proxybind() and it doesn't seem to 
be in JQuery 1.7.1.  I found a proxy() method, but it doesn't seem to 
match what you're talking about.


http://api.jquery.com/jQuery.proxy/

Also, the JQuery.is() method, which is the method similar to 
.matchesSelector(), does not support any context node, and so it does 
not work with .is(.foo, context).


Could you provide some documentation for, or at least a version of 
JQuery that implements proxybind?


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



Re: QSA, the problem with :scope, and naming

2011-11-15 Thread Brian Kardell
 Right now, the spec does however handle that use case by doing this:

  document.querySelectorAll(:scope .foo, x);

 Where x is either an individual element, or an Array, NodeList or
numerically indexed object containing 0 or more Elements.

 (It does however limit the result only to elements that are in the
document, and any disconnected elements in the collection x would not be
found.)


What spec are you referring to? I've never seen that and I am having
trouble finding it now.


Re: QSA, the problem with :scope, and naming

2011-11-15 Thread Lachlan Hunt

On 2011-11-15 15:13, Brian Kardell wrote:

Right now, the spec does however handle that use case by doing this:

  document.querySelectorAll(:scope .foo, x);

Where x is either an individual element, or an Array, NodeList or
numerically indexed object containing 0 or more Elements.

(It does however limit the result only to elements that are in the
document, and any disconnected elements in the collection x would not be
found.)


What spec are you referring to? I've never seen that and I am having
trouble finding it now.


It's in the draft of Selectors API Level 2.

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

See the refElement/refNodes parameters which specify elements matched by 
:scope.


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



Re: QSA, the problem with :scope, and naming

2011-11-10 Thread Travis Leithead
This has been an interesting debate, but I'm still a little confused with the 
outcome (if any).

Will someone summarize the current position on these issues:

1. Should find() and findAll() follow style scoped rules or not and how?
2. How does the presence of :scope affect find() and findAll()
3. Should invalid selectors be allowed (those that start with a combinator)? 
(I'm not quite sure where that landed)

And finally...
When can we expect to see a draft proposal of find() and findAll() in 
Selectors API L2?

-Travis





Re: QSA, the problem with :scope, and naming

2011-11-10 Thread Tab Atkins Jr.
On Thu, Nov 10, 2011 at 2:57 PM, Travis Leithead
travis.leith...@microsoft.com wrote:
 This has been an interesting debate, but I'm still a little confused with the 
 outcome (if any).

 Will someone summarize the current position on these issues:

 1. Should find() and findAll() follow style scoped rules or not and how?
 2. How does the presence of :scope affect find() and findAll()
 3. Should invalid selectors be allowed (those that start with a 
 combinator)? (I'm not quite sure where that landed)

 And finally...
 When can we expect to see a draft proposal of find() and findAll() in 
 Selectors API L2?

This is based on my understanding of the thread's conclusion.

1. Almost, though with a few small differences due to slightly
different affordances.  Specifically:
  a. Normal selectors (without :scope in them) will *not* match the
context element - you have to use :scope specifically to refer to the
context.  This was chosen so that the common case of el.find('div')
won't just return the context element when it's a div.  style scoped
goes the opposite way largely for forwards compat, so people can use
the #id of the context during the interim period
  b. You can select elements outside of the context element.  The
search starts at the context, but you can use a sibling or reference
combinator to select outside the subtree.  This is because it's
useful, and also because it allows one to interrupt a selector at
any point, do some work on the set, and then continue with the rest of
the selector, regardless of what the selector's structure was.

2. The presence of :scope lets you select the context element, or
specialize on it.  It hasn't been fully decided whether :scope is
required to be at the start of the selector when it's present or if it
can occur anywhere (in which case it switches the selector to matching
over the whole document).

3. Yes, they should be.  Everyone's used to them from jQuery, so why not?

~TJ



Re: QSA, the problem with :scope, and naming

2011-11-10 Thread Jonas Sicking
On Thu, Nov 10, 2011 at 2:57 PM, Travis Leithead
travis.leith...@microsoft.com wrote:
 This has been an interesting debate, but I'm still a little confused with the 
 outcome (if any).

 Will someone summarize the current position on these issues:

 1. Should find() and findAll() follow style scoped rules or not and how?

While related, I think the question of how style scoped rules are
parsed is somewhat independent.

 2. How does the presence of :scope affect find() and findAll()
 3. Should invalid selectors be allowed (those that start with a 
 combinator)? (I'm not quite sure where that landed)

Here is my detailed proposal based on the previous thread for how
selector parsing should work in the context of .find/.findAll:

1. Start with an empty list
2. Skip any whitespace at the beginning of the string.
3. If the next character is a , a + or a ~, insert a simple
selector[1] containing just the :scope pseudo selector at the
beginning of the selector.
4. Parse as a selector[1]. If there's a parse error throw an
SyntaxError exception.
5. If during parsing a :scope pseudo class was parsed, and if a
:scope pseudo selector was added in step 2, throw a SyntaxError
exception.
6. If during parsing no :scope pseudo class was parsed, and if no
:scope pseudo selector was added in step 2, add a simple selector
containing just the :scope pseudo class to the beginning of the
list, and use a descendant selector as combinator to the rest of the
selector.
7. Add selector to the end of list created in step 1.
8. If, after skipping any whitespace, the next character is a comma,
skip the comma and go to step 2.

The resulting selector list is evaluated against the document node,
but with :scope matching the node that .find/.findAll was called on.
.findAll returns all nodes which match the selector in document order.
.find returns the first node in the list of nodes that .findAll
returns, or null if the list is empty.

Now, as for what type .findAll should return is a so far unresolved
question. I'll start a separate thread on that.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-11-10 Thread Jonas Sicking
On Thu, Nov 10, 2011 at 11:33 PM, Jonas Sicking jo...@sicking.cc wrote:
 On Thu, Nov 10, 2011 at 2:57 PM, Travis Leithead
 travis.leith...@microsoft.com wrote:
 This has been an interesting debate, but I'm still a little confused with 
 the outcome (if any).

 Will someone summarize the current position on these issues:

 1. Should find() and findAll() follow style scoped rules or not and 
 how?

 While related, I think the question of how style scoped rules are
 parsed is somewhat independent.

 2. How does the presence of :scope affect find() and findAll()
 3. Should invalid selectors be allowed (those that start with a 
 combinator)? (I'm not quite sure where that landed)

 Here is my detailed proposal based on the previous thread for how
 selector parsing should work in the context of .find/.findAll:

 1. Start with an empty list
 2. Skip any whitespace at the beginning of the string.
 3. If the next character is a , a + or a ~, insert a simple
 selector[1] containing just the :scope pseudo selector at the
 beginning of the selector.
 4. Parse as a selector[1]. If there's a parse error throw an
 SyntaxError exception.
 5. If during parsing a :scope pseudo class was parsed, and if a
 :scope pseudo selector was added in step 2, throw a SyntaxError
 exception.
 6. If during parsing no :scope pseudo class was parsed, and if no
 :scope pseudo selector was added in step 2, add a simple selector
 containing just the :scope pseudo class to the beginning of the
 list, and use a descendant selector as combinator to the rest of the
 selector.
 7. Add selector to the end of list created in step 1.
 8. If, after skipping any whitespace, the next character is a comma,
 skip the comma and go to step 2.

 The resulting selector list is evaluated against the document node,
 but with :scope matching the node that .find/.findAll was called on.
 .findAll returns all nodes which match the selector in document order.
 .find returns the first node in the list of nodes that .findAll
 returns, or null if the list is empty.

 Now, as for what type .findAll should return is a so far unresolved
 question. I'll start a separate thread on that.

And I forgot to include:

[1] as defined by the Selector spec.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Alex Russell
On Fri, Oct 21, 2011 at 12:41 AM, Jonas Sicking jo...@sicking.cc wrote:
 On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt lachlan.h...@lachy.id.au
 wrote:
 Not necessarily.  It depends what exactly it means for a selector to
 contain
 :scope for determining whether or not to enable the implied :scope
 behaviour.  Consider:

  foo.find(:not(:scope));

 Ooh, this is an interesting case too. So here's the full list of cases which
 we need defined behavior for (again looking at Alex and Yehuda here).

 In the following DOM

 body id=3
  div id=0/div
  div id=context foo=bar
   div id=1/div
   div class=class id=2/div
   div class=withChildren id=3div class=child id=4/div/div
  /div
  div id=5/div
  div id=6/div
 /body

 What would each of the following .findAll calls return. I've included my
 guessed based on the discussions so far:

 var e = document.getElementById('context');

 e.findAll(div)  // returns ids 1,2,3,4
 e.findAll()      // returns an empty list
 e.findAll(#3)  // returns id 3, but not the body node
 e.findAll( div) // returns ids 1,2,3
 e.findAll([foo=bar]) // returns nothing
 e.findAll([id=1]) // returns id 1
 e.findAll(:first-child) // returns id 1
 e.findAll(+ div) // returns id 5
 e.findAll(~ div) // returns id 5, 6
 e.findAll(:scope)

Returns the context.

 e.findAll(div:scope)

Returns the context.

 e.findAll([foo=bar]:scope)

Returns the context.

 e.findAll(:scope div)

1, 2, 3, 4

 e.findAll(div:scope div)

1, 2, 3, 4

 e.findAll(div:scope #3)

3

 e.findAll(body  :scope  div)

1, 2, 3, 4

 e.findAll(div, :scope)

context, 1, 2, 3, 4

 e.findAll(body  :scope  div, :scope)

context, 1, 2, 3, 4

 e.findAll(:not(:scope))

empty set



Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Alex Russell
What Tab said  = )

On Sun, Oct 30, 2011 at 9:23 AM, Tab Atkins Jr. jackalm...@gmail.com wrote:
 On Sat, Oct 29, 2011 at 8:28 PM, Cameron McCormack c...@mcc.id.au wrote:
 On 20/10/11 3:50 AM, Alex Russell wrote:

 I strongly agree that it should be an Array *type*, but I think just
 returning a plain Array is the wrong resolution to our NodeList
 problem. WebIDL should specify that DOM List types *are* Array types.
 It's insane that we even have a NodeList type which isn't a real array
 at all. Adding a parallel system when we could just fix the one we
 have (and preserve the value of a separate prototype for extension) is
 wonky to me.

 That said, I'd *also* support the ability to have some sort of
 decorator mechanism before return on .find() or a way to re-route the
 prototype of the returned Array.

 +heycam to debate this point.

 Late replying here again, apologies, but I agree with others who say that an
 actual Array object should be returned from this new API given that it is
 not meant to be live.  What benefit is there from returning a NodeList?

 If it's a NodeList (or something else that *subclasses* Array) we can
 do fun things like add .find to it, which returns the sorted union of
 calling .find on all the elements within it.  Returning a plain Array
 doesn't let us do that.

 ~TJ




Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Alex Russell
On Sun, Oct 30, 2011 at 1:23 PM, Rick Waldron waldron.r...@gmail.com wrote:


 On Sat, Oct 29, 2011 at 11:28 PM, Cameron McCormack c...@mcc.id.au wrote:

 On 20/10/11 3:50 AM, Alex Russell wrote:

 I strongly agree that it should be an Array *type*, but I think just
 returning a plain Array is the wrong resolution to our NodeList
 problem. WebIDL should specify that DOM List types *are* Array types.
 It's insane that we even have a NodeList type which isn't a real array
 at all. Adding a parallel system when we could just fix the one we
 have (and preserve the value of a separate prototype for extension) is
 wonky to me.

 That said, I'd *also* support the ability to have some sort of
 decorator mechanism before return on .find() or a way to re-route the
 prototype of the returned Array.

 +heycam to debate this point.

 Late replying here again, apologies, but I agree with others who say that
 an actual Array object should be returned from this new API given that it is
 not meant to be live.  What benefit is there from returning a NodeList?

 As much as I hate saying this: introducing a third return type would be
 counter-productive, as you'd now have live NodeList, static NodeList and
 subclassed Array. Congratulations, the cluster-f*ck continues in true form.

Live NodeList instances don't need to be considered here. They're the
result of an API which generates them, and that API can be described
in terms of Proxies. No need to complicate NodeList or imply that we
need a different type.

Making NodeList instances real array unifies them all. We can get that done too.



Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Cameron McCormack

On 31/10/11 1:56 PM, Alex Russell wrote:

Live NodeList instances don't need to be considered here. They're the
result of an API which generates them, and that API can be described
in terms of Proxies. No need to complicate NodeList or imply that we
need a different type.

Making NodeList instances real array unifies them all. We can get that done too.


Don't live and static NodeLists use the same prototype?  If they are 
separate, I don't see any problem with making them real arrays, but I 
am not sure what the implications of that are.  Array.isArray == true, I 
guess?  Do we have that ability within the bounds of ECMAScript yet? 
Note that we can already make NodeList.prototype === Array.prototype if 
we want, using appropriate Web IDL annotations.




Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Charles Pritchard

On 10/31/11 2:03 PM, Cameron McCormack wrote:

On 31/10/11 1:56 PM, Alex Russell wrote:

Live NodeList instances don't need to be considered here. They're the
result of an API which generates them, and that API can be described
in terms of Proxies. No need to complicate NodeList or imply that we
need a different type.

Making NodeList instances real array unifies them all. We can get 
that done too.


Don't live and static NodeLists use the same prototype?  If they are 
separate, I don't see any problem with making them real arrays, but 
I am not sure what the implications of that are.  Array.isArray == 
true, I guess?  Do we have that ability within the bounds of 
ECMAScript yet? Note that we can already make NodeList.prototype === 
Array.prototype if we want, using appropriate Web IDL annotations.

Array seems to work fine in WebKit:
document.getElementsByTagName('div').__proto__.__proto__ = Array.prototype;

dojo just reimplements NodeList as an array:
http://dojotoolkit.org/reference-guide/dojo/NodeList.html

I don't understand what real array means, other than the prototype 
equivalence.


If NodeList were an array, what's the behavior of running push on NodeList?
The list may end up with non-node objects if push is not supplemented.

-Charles




Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Jonas Sicking
Ok, so we're down to not having full agreement on the following selectors:

On Mon, Oct 31, 2011 at 1:55 PM, Alex Russell slightly...@google.com wrote:
 On Fri, Oct 21, 2011 at 12:41 AM, Jonas Sicking jo...@sicking.cc wrote:
 e.findAll(body  :scope  div)

 1, 2, 3, 4

 e.findAll(body  :scope  div, :scope)

 context, 1, 2, 3, 4

I'm hoping that you just made a mistake here? 4 isn't a child of the
context node. So in both of these I would think that 4 should be
removed based on your answers to the other questions.

 e.findAll(div, :scope)

 context, 1, 2, 3, 4

Yehuda had a very different suggestion here but so far hasn't motivated why.

Personally I think Alex answer is the more useful one.

We just need to decide on something

 e.findAll(:not(:scope))

 empty set

Again, Yehuda had a different answer here. Though in this case I think
Yehuda's answer is more useful and consistent.

But I'm all ears for what the logic used to get to your answer and why
you think this is a better (more consistent? more useful?) answer.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Cameron McCormack

On 31/10/11 2:18 PM, Charles Pritchard wrote:

I don't understand what real array means, other than the prototype
equivalence.


There's also the [[DefineOwnProperty]] behaviour which is different from 
normal objects.  That kind of behaviour doesn't *need* to be handled by 
making NodeLists real arrays, it can be done by making them proxies. 
Some people might prefer not to do require that though, if it is indeed 
possible to make them real arrays.




Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Alex Russell
On Mon, Oct 31, 2011 at 2:03 PM, Cameron McCormack c...@mcc.id.au wrote:
 On 31/10/11 1:56 PM, Alex Russell wrote:

 Live NodeList instances don't need to be considered here. They're the
 result of an API which generates them, and that API can be described
 in terms of Proxies. No need to complicate NodeList or imply that we
 need a different type.

 Making NodeList instances real array unifies them all. We can get that
 done too.

 Don't live and static NodeLists use the same prototype?

Yes, I envision they would. The restrictions on live lists are
probably going to be created by a proxy that wraps them and manages
their semantics.

 If they are
 separate, I don't see any problem with making them real arrays, but I am
 not sure what the implications of that are.  Array.isArray == true, I guess?

For JS, it just means having a working .length property (in all the
ways that Arrays allow it to be used). Arrays are identical to other
objects in all other respects.

  Do we have that ability within the bounds of ECMAScript yet? Note that we
 can already make NodeList.prototype === Array.prototype if we want, using
 appropriate Web IDL annotations.

We'll need ES 6 proxies to get the working .length thing today. Not ideal.



Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Alex Russell
On Mon, Oct 31, 2011 at 2:18 PM, Charles Pritchard ch...@jumis.com wrote:
 On 10/31/11 2:03 PM, Cameron McCormack wrote:

 On 31/10/11 1:56 PM, Alex Russell wrote:

 Live NodeList instances don't need to be considered here. They're the
 result of an API which generates them, and that API can be described
 in terms of Proxies. No need to complicate NodeList or imply that we
 need a different type.

 Making NodeList instances real array unifies them all. We can get that
 done too.

 Don't live and static NodeLists use the same prototype?  If they are
 separate, I don't see any problem with making them real arrays, but I am
 not sure what the implications of that are.  Array.isArray == true, I guess?
  Do we have that ability within the bounds of ECMAScript yet? Note that we
 can already make NodeList.prototype === Array.prototype if we want, using
 appropriate Web IDL annotations.

 Array seems to work fine in WebKit:
 document.getElementsByTagName('div').__proto__.__proto__ = Array.prototype;

 dojo just reimplements NodeList as an array:
 http://dojotoolkit.org/reference-guide/dojo/NodeList.html

The reason we did it that way is because there's no other way to
create an intermediate type with the magic .length property.

 I don't understand what real array means, other than the prototype
 equivalence.

 If NodeList were an array, what's the behavior of running push on NodeList?
 The list may end up with non-node objects if push is not supplemented.

 -Charles






Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Boris Zbarsky

On 10/31/11 7:25 PM, Alex Russell wrote:

For JS, it just means having a working .length property (in all the
ways that Arrays allow it to be used). Arrays are identical to other
objects in all other respects.


No, they're not.  For example, off the top of my head, they get 
serialized differently by JSON.stringify.  Note that this is based off 
of the [[Class]] (ES5 section 15.12.3 definition of Str() item 10a).  So 
if you want your object to behave like an array for JSON serialization, 
it needs to have the right [[Class]].


I'd bet money there are other such things in ES5, for what it's worth.


We'll need ES 6 proxies to get the working .length thing today. Not ideal.


I think we should just start assuming ES 6 proxies or equivalent 
mechanism.  It's needed for all sorts of stuff and UAs are implementing 
it anyway.  If we want to avoid assuming it, we could just specify 
things in terms of ES5 internal classes and hooks.


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Charles Pritchard

On 10/31/11 7:25 PM, Alex Russell wrote:

For JS, it just means having a working .length property (in all the
ways that Arrays allow it to be used). Arrays are identical to other
objects in all other respects.


No, they're not.  For example, off the top of my head, they get 
serialized differently by JSON.stringify.  Note that this is based off 
of the [[Class]] (ES5 section 15.12.3 definition of Str() item 10a).  
So if you want your object to behave like an array for JSON 
serialization, it needs to have the right [[Class]].


I'd bet money there are other such things in ES5, for what it's worth.


Structured cloning fails for NodeList, same as postMessage, because of 
circular structure.  With .join, you get the .toString of the DOM Nodes. 
There is no JSON serialization for DOM elements.





Re: QSA, the problem with :scope, and naming

2011-10-31 Thread Boris Zbarsky

On 10/31/11 9:32 PM, Charles Pritchard wrote:

Structured cloning fails for NodeList, same as postMessage, because of
circular structure.


What circular structure?  Structured clone can handle that.

It fails because it's a host object (based on its [[Class]]) that's not 
whitelisted in the structured clone algorithm.



With .join, you get the .toString of the DOM Nodes.


Yes, as you would for an array of DOM nodes.

A quick skim through the ES spec shows that Array.prototype.concat also 
considers the [[Class]] of its arguments, by the way.  And indeed, this 
testcase:


  script
var l = document.getElementsByTagName(html);
var a = Array.prototype.slice.call(l);
l.__proto__.__proto__ = Array.prototype;
var test1 = [].concat(l);
var test2 = [].concat(a);
alert(test1[0] instanceof HTMLHtmlElement);
alert(test2[0] instanceof HTMLHtmlElement);
  /script

alerts false followed by true in UAs.

So we really do need to decide what it means for a return value to be 
an Array.  For example, how does it behave with concat()?


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-30 Thread Tab Atkins Jr.
On Sat, Oct 29, 2011 at 8:28 PM, Cameron McCormack c...@mcc.id.au wrote:
 On 20/10/11 3:50 AM, Alex Russell wrote:

 I strongly agree that it should be an Array *type*, but I think just
 returning a plain Array is the wrong resolution to our NodeList
 problem. WebIDL should specify that DOM List types *are* Array types.
 It's insane that we even have a NodeList type which isn't a real array
 at all. Adding a parallel system when we could just fix the one we
 have (and preserve the value of a separate prototype for extension) is
 wonky to me.

 That said, I'd *also* support the ability to have some sort of
 decorator mechanism before return on .find() or a way to re-route the
 prototype of the returned Array.

 +heycam to debate this point.

 Late replying here again, apologies, but I agree with others who say that an
 actual Array object should be returned from this new API given that it is
 not meant to be live.  What benefit is there from returning a NodeList?

If it's a NodeList (or something else that *subclasses* Array) we can
do fun things like add .find to it, which returns the sorted union of
calling .find on all the elements within it.  Returning a plain Array
doesn't let us do that.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-30 Thread Sean Hogan

On 30/10/11 2:28 PM, Cameron McCormack wrote:

On 20/10/11 3:50 AM, Alex Russell wrote:

I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.
It's insane that we even have a NodeList type which isn't a real array
at all. Adding a parallel system when we could just fix the one we
have (and preserve the value of a separate prototype for extension) is
wonky to me.

That said, I'd *also* support the ability to have some sort of
decorator mechanism before return on .find() or a way to re-route the
prototype of the returned Array.

+heycam to debate this point.


Late replying here again, apologies, but I agree with others who say 
that an actual Array object should be returned from this new API given 
that it is not meant to be live.  What benefit is there from returning 
a NodeList?





I think it's already been said, but if StaticNodeList (or whatever) 
inherits from Array then it receives array methods plus it can still 
have .item() for people who are assuming it is like NodeList.


Sean




Re: QSA, the problem with :scope, and naming

2011-10-30 Thread Rick Waldron
On Sat, Oct 29, 2011 at 11:28 PM, Cameron McCormack c...@mcc.id.au wrote:

 On 20/10/11 3:50 AM, Alex Russell wrote:

 I strongly agree that it should be an Array *type*, but I think just
 returning a plain Array is the wrong resolution to our NodeList
 problem. WebIDL should specify that DOM List types *are* Array types.
 It's insane that we even have a NodeList type which isn't a real array
 at all. Adding a parallel system when we could just fix the one we
 have (and preserve the value of a separate prototype for extension) is
 wonky to me.

 That said, I'd *also* support the ability to have some sort of
 decorator mechanism before return on .find() or a way to re-route the
 prototype of the returned Array.

 +heycam to debate this point.


 Late replying here again, apologies, but I agree with others who say that
 an actual Array object should be returned from this new API given that it
 is not meant to be live.  What benefit is there from returning a NodeList?


As much as I hate saying this: introducing a third return type would be
counter-productive, as you'd now have live NodeList, static NodeList and
subclassed Array. Congratulations, the cluster-f*ck continues in true form.


Re: QSA, the problem with :scope, and naming

2011-10-29 Thread Cameron McCormack

On 20/10/11 3:50 AM, Alex Russell wrote:

I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.
It's insane that we even have a NodeList type which isn't a real array
at all. Adding a parallel system when we could just fix the one we
have (and preserve the value of a separate prototype for extension) is
wonky to me.

That said, I'd *also* support the ability to have some sort of
decorator mechanism before return on .find() or a way to re-route the
prototype of the returned Array.

+heycam to debate this point.


Late replying here again, apologies, but I agree with others who say 
that an actual Array object should be returned from this new API given 
that it is not meant to be live.  What benefit is there from returning a 
NodeList?




Re: QSA, the problem with :scope, and naming

2011-10-26 Thread Brian Kardell
Yeah, I have to agree with the list here.  If you allow one its unintuitive
to not allow it the same way in a group.  The more exceptions and complexity
you add, the harder it is for someone to learn.

 On Oct 25, 2011 10:16 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote:

 * Tab Atkins Jr. wrote:
 On Tue, Oct 25, 2011 at 4:56 PM, Ojan Vafai o...@chromium.org wrote:
  On Tue, Oct 25, 2011 at 4:44 PM, Bjoern Hoehrmann derhoe...@gmx.net
 wrote:
  * Tab Atkins Jr. wrote:
  Did you not understand my example?  el.find(+ foo, + bar) feels
  really weird and I don't like it.  I'm okay with a single selector
  starting with a combinator, like el.find(+ foo), but not a selector
  list.
 
  Allowing + foo but not + foo, + bar would be really weird.
 
  Tab, what specifically is weird about el.find(+ foo, + bar)?
 
 Seeing a combinator immediately after a comma just seems weird to me.

 A list of abbreviated selectors is a more intuitive concept than a
 list of selectors where the first and only the first selector may be
 abbreviated. List of type versus special case and arbitrary limit.
 If one abbreviated selector isn't weird, then two shouldn't be either
 if two selectors aren't weird on their own.
 --
 Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
 Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/




Re: QSA, the problem with :scope, and naming

2011-10-26 Thread Tab Atkins Jr.
On Wed, Oct 26, 2011 at 1:47 PM, Jonas Sicking jo...@sicking.cc wrote:
 On Tue, Oct 25, 2011 at 10:43 AM, Yehuda Katz wyc...@gmail.com wrote:
 e.findAll(div, :scope) // 0,context,1,2,3,4,5,6

 Huh, why 0 and 6? What's the logic there? I would have expected it to
 be a sorted union of the results returned from the individual parts.
 I.e. something like:

 sortedUnion(e.findAll(div), e.findAll(:scope))

 Which would yield [context, 1, 2, 3, 4]

Agreed.  Any behavior switch based on the contents of a complex
selector should be limited to that complex selector, rather than
polluting the entire selector list.


 e.findAll(:not(:scope)) // all elements except context

 What do you mean by all elements? All elements in the whole document
 (except the context node). Including the body and any siblings it
 might have (and their descendants)?

Yes to both.  It would be identical to giving the context element a
unique id, and then just doing a normal full-document query for
:not(#unique).

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Yehuda Katz
Your guesses are all right in terms of existing jQuery but one:

'div': [1, 2, 3, 4]
'': []
'#3': [3]
' div': [1, 2, 3]
'[foo=bar]': []
'[id=1]': [1]
':first-child': [1, 4]
'+ div': [5]
'~ div': [5, 6]

You can see the results live at http://jsfiddle.net/Dj3Ab/.

The basic rule is that if there is no combinator, a descendent combinator is
implied.

jQuery returns an empty list with an empty String, but querySelectorAll
throws an exception (the spec says that the selector SHOULD match a slightly
loosened version of the selector production in
http://www.w3.org/TR/2009/PR-css3-selectors-20091215/#w3cselgrammar, which
disallows the empty string). It probably makes sense for find or findAll to
raise an exception too, but an empty list is fine too.

I'm not as sure about the :scope cases. I can make some guesses:

e.findAll(:scope) // context
e.findAll(div:scope) // context
e.findAll([foo=bar]:scope) // context
e.findAll(:scope div) // 1,2,3,4
e.findAll(div:scope div) // 1,2,3,4
e.findAll(div:scope #3) // 3
e.findAll(body  :scope  div) // 1,2,3
e.findAll(div, :scope) // 0,context,1,2,3,4,5,6
e.findAll(body  :scope  div, :scope) // context,1,2,3
e.findAll(:not(:scope)) // all elements except context

In cases where :scope is used, I would say that the selector behaves
identically to the id hack used by most JavaScript libraries. In
particular, the selector is relative to the root element, and the :scope
element simply represents the context element.

So you could change the :scope rules to be:

e.findAll(#context) // context
e.findAll(div#context) // context
e.findAll([foo=bar]#context) // context
e.findAll(#context div) // 1,2,3,4
e.findAll(div#context div) // 1,2,3,4
e.findAll(div#context #3) // 3
e.findAll(body  #context  div) // 1,2,3
e.findAll(div, #context) // 0,context,1,2,3,4,5,6
e.findAll(body  #context  div, #context) // context,1,2,3
e.findAll(:not(#context)) // all elements except context

This also means that the above (non-:scope) rule could (I think) be restated
as:

   - Each selector in a selector group passed to find or findAll has an
   implied leading :scope
   - If no initial combinator is supplied, a descendent combinator is
   implied

Yehuda Katz
(ph) 718.877.1325


On Fri, Oct 21, 2011 at 12:41 AM, Jonas Sicking jo...@sicking.cc wrote:

 On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt lachlan.h...@lachy.id.au
 wrote:
  Not necessarily.  It depends what exactly it means for a selector to
 contain
  :scope for determining whether or not to enable the implied :scope
  behaviour.  Consider:
 
   foo.find(:not(:scope));

 Ooh, this is an interesting case too. So here's the full list of cases
 which we need defined behavior for (again looking at Alex and Yehuda here).

 In the following DOM

 body id=3
  div id=0/div
  div id=context foo=bar
   div id=1/div
   div class=class id=2/div
   div class=withChildren id=3div class=child id=4/div/div
  /div
  div id=5/div
  div id=6/div
 /body

 What would each of the following .findAll calls return. I've included my
 guessed based on the discussions so far:

 var e = document.getElementById('context');

 e.findAll(div)  // returns ids 1,2,3,4
 e.findAll()  // returns an empty list
 e.findAll(#3)  // returns id 3, but not the body node
 e.findAll( div) // returns ids 1,2,3
 e.findAll([foo=bar]) // returns nothing
 e.findAll([id=1]) // returns id 1
 e.findAll(:first-child) // returns id 1
 e.findAll(+ div) // returns id 5
 e.findAll(~ div) // returns id 5, 6
 e.findAll(:scope)
 e.findAll(div:scope)
 e.findAll([foo=bar]:scope)
 e.findAll(:scope div)
 e.findAll(div:scope div)
 e.findAll(div:scope #3)
 e.findAll(body  :scope  div)
 e.findAll(div, :scope)
 e.findAll(body  :scope  div, :scope)
 e.findAll(:not(:scope))

 / Jonas


Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Tab Atkins Jr.
On Tue, Oct 25, 2011 at 10:43 AM, Yehuda Katz wyc...@gmail.com wrote:
 Your guesses are all right in terms of existing jQuery but one:
 'div': [1, 2, 3, 4]
 '': []
 '#3': [3]
 ' div': [1, 2, 3]
 '[foo=bar]': []
 '[id=1]': [1]
 ':first-child': [1, 4]
 '+ div': [5]
 '~ div': [5, 6]
 You can see the results live at http://jsfiddle.net/Dj3Ab/.
 The basic rule is that if there is no combinator, a descendent combinator is
 implied.
 jQuery returns an empty list with an empty String, but querySelectorAll
 throws an exception (the spec says that the selector SHOULD match a slightly
 loosened version of the selector production in
 http://www.w3.org/TR/2009/PR-css3-selectors-20091215/#w3cselgrammar, which
 disallows the empty string). It probably makes sense for find or findAll to
 raise an exception too, but an empty list is fine too.
 I'm not as sure about the :scope cases. I can make some guesses:
 e.findAll(:scope) // context
 e.findAll(div:scope) // context
 e.findAll([foo=bar]:scope) // context
 e.findAll(:scope div) // 1,2,3,4
 e.findAll(div:scope div) // 1,2,3,4
 e.findAll(div:scope #3) // 3
 e.findAll(body  :scope  div) // 1,2,3
 e.findAll(div, :scope) // 0,context,1,2,3,4,5,6
 e.findAll(body  :scope  div, :scope) // context,1,2,3
 e.findAll(:not(:scope)) // all elements except context

 In cases where :scope is used, I would say that the selector behaves
 identically to the id hack used by most JavaScript libraries. In
 particular, the selector is relative to the root element, and the :scope
 element simply represents the context element.
 So you could change the :scope rules to be:
 e.findAll(#context) // context
 e.findAll(div#context) // context
 e.findAll([foo=bar]#context) // context
 e.findAll(#context div) // 1,2,3,4
 e.findAll(div#context div) // 1,2,3,4
 e.findAll(div#context #3) // 3
 e.findAll(body  #context  div) // 1,2,3
 e.findAll(div, #context) // 0,context,1,2,3,4,5,6
 e.findAll(body  #context  div, #context) // context,1,2,3
 e.findAll(:not(#context)) // all elements except context
 This also means that the above (non-:scope) rule could (I think) be restated
 as:

 Each selector in a selector group passed to find or findAll has an implied
 leading :scope
 If no initial combinator is supplied, a descendent combinator is implied

I'm no longer strongly convinced that we need to support :scope not at
the front of the selector.  el.find(foo :scope bar) is equivalent to
first doing el.matches(foo :scope), then running el.find(bar) if
it does.

This is slightly inconvenient with individual elements, but in the
ideal future when .find returns a nice NodeList class that's a subtype
of Array, the NodeList can have its own .filter and .find functions on
it that automatically runs the operations over all the children and
unions the results into a new NodeList.

Then you can do elems.filter(foo :scope).find(bar), and you're done.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Sean Hogan

On 26/10/11 4:43 AM, Yehuda Katz wrote:

Your guesses are all right in terms of existing jQuery but one:

'div': [1, 2, 3, 4]
'': []
'#3': [3]
' div': [1, 2, 3]
'[foo=bar]': []
'[id=1]': [1]
':first-child': [1, 4]
'+ div': [5]
'~ div': [5, 6]

You can see the results live at http://jsfiddle.net/Dj3Ab/.

The basic rule is that if there is no combinator, a descendent 
combinator is implied.


jQuery returns an empty list with an empty String, but 
querySelectorAll throws an exception (the spec says that the selector 
SHOULD match a slightly loosened version of the selector production in 
http://www.w3.org/TR/2009/PR-css3-selectors-20091215/#w3cselgrammar, 
which disallows the empty string). It probably makes sense for find or 
findAll to raise an exception too, but an empty list is fine too.


I'm not as sure about the :scope cases. I can make some guesses:

e.findAll(:scope) // context
e.findAll(div:scope) // context
e.findAll([foo=bar]:scope) // context
e.findAll(:scope div) // 1,2,3,4
e.findAll(div:scope div) // 1,2,3,4
e.findAll(div:scope #3) // 3
e.findAll(body  :scope  div) // 1,2,3
e.findAll(div, :scope) // 0,context,1,2,3,4,5,6
e.findAll(body  :scope  div, :scope) // context,1,2,3
e.findAll(:not(:scope)) // all elements except context

In cases where :scope is used, I would say that the selector behaves 
identically to the id hack used by most JavaScript libraries. In 
particular, the selector is relative to the root element, and the 
:scope element simply represents the context element.




I think allowing explicit :scope in findAll() will be perpetually 
confusing. I can imagine someone looking at old code like:


e.findAll(div.foo span, div.bar :scope span)

and asking themselves what's the rule again? If there's :scope in the 
selector then there's no :scope implied? Or was that just on each single 
selector? Or is :scope always implied at the start of the whole selector 
list and that's why it's explicit in the second part? Dammit, why didn't 
we just use querySelectorAll() if we wanted explicit :scope?



So you could change the :scope rules to be:

e.findAll(#context) // context
e.findAll(div#context) // context
e.findAll([foo=bar]#context) // context
e.findAll(#context div) // 1,2,3,4
e.findAll(div#context div) // 1,2,3,4
e.findAll(div#context #3) // 3
e.findAll(body  #context  div) // 1,2,3
e.findAll(div, #context) // 0,context,1,2,3,4,5,6
e.findAll(body  #context  div, #context) // context,1,2,3
e.findAll(:not(#context)) // all elements except context

This also means that the above (non-:scope) rule could (I think) be 
restated as:


  * Each selector in a selector group passed to find or findAll has an
implied leading :scope
  * If no initial combinator is supplied, a descendent combinator is
implied

Yehuda Katz
(ph) 718.877.1325


On Fri, Oct 21, 2011 at 12:41 AM, Jonas Sicking jo...@sicking.cc wrote:

On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt
lachlan.h...@lachy.id.au mailto:lachlan.h...@lachy.id.au wrote:
 Not necessarily.  It depends what exactly it means for a
selector to contain
 :scope for determining whether or not to enable the implied :scope
 behaviour.  Consider:

  foo.find(:not(:scope));

Ooh, this is an interesting case too. So here's the full list of
cases which we need defined behavior for (again looking at Alex
and Yehuda here).

In the following DOM

body id=3
div id=0/div
div id=context foo=bar
div id=1/div
div class=class id=2/div
div class=withChildren id=3div class=child id=4/div/div
/div
div id=5/div
div id=6/div
/body

What would each of the following .findAll calls return. I've
included my guessed based on the discussions so far:

var e = document.getElementById('context');

e.findAll(div)  // returns ids 1,2,3,4
e.findAll()  // returns an empty list
e.findAll(#3)  // returns id 3, but not the body node
e.findAll( div) // returns ids 1,2,3
e.findAll([foo=bar]) // returns nothing
e.findAll([id=1]) // returns id 1
e.findAll(:first-child) // returns id 1
e.findAll(+ div) // returns id 5
e.findAll(~ div) // returns id 5, 6
e.findAll(:scope)
e.findAll(div:scope)
e.findAll([foo=bar]:scope)
e.findAll(:scope div)
e.findAll(div:scope div)
e.findAll(div:scope #3)
e.findAll(body  :scope  div)
e.findAll(div, :scope)
e.findAll(body  :scope  div, :scope)
e.findAll(:not(:scope))

/ Jonas 







Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Tab Atkins Jr.
On Tue, Oct 25, 2011 at 1:47 PM, Sean Hogan shogu...@westnet.com.au wrote:
 I think allowing explicit :scope in findAll() will be perpetually confusing.
 I can imagine someone looking at old code like:

     e.findAll(div.foo span, div.bar :scope span)

 and asking themselves what's the rule again? If there's :scope in the
 selector then there's no :scope implied? Or was that just on each single
 selector? Or is :scope always implied at the start of the whole selector
 list and that's why it's explicit in the second part? Dammit, why didn't we
 just use querySelectorAll() if we wanted explicit :scope?

Using :scope explicitly at the beginning of selectors is necessary if
we want a sane way to have selector lists chain off of the scoping
element.  I'm okay with the string starting with a combinator when
it's a single selector like + foo, but not when it's a selector list
like + foo, + bar.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Sean Hogan

On 26/10/11 7:51 AM, Tab Atkins Jr. wrote:

On Tue, Oct 25, 2011 at 1:47 PM, Sean Hoganshogu...@westnet.com.au  wrote:

I think allowing explicit :scope in findAll() will be perpetually confusing.
I can imagine someone looking at old code like:

 e.findAll(div.foo span, div.bar :scope span)

and asking themselves what's the rule again? If there's :scope in the
selector then there's no :scope implied? Or was that just on each single
selector? Or is :scope always implied at the start of the whole selector
list and that's why it's explicit in the second part? Dammit, why didn't we
just use querySelectorAll() if we wanted explicit :scope?

Using :scope explicitly at the beginning of selectors is necessary if
we want a sane way to have selector lists chain off of the scoping
element.  I'm okay with the string starting with a combinator when
it's a single selector like + foo, but not when it's a selector list
like + foo, + bar.

~TJ



I didn't follow that. Why does findAll() need to support explicit :scope?

It is simpler if querySelectorAll() supports explicit :scope and 
findAll() doesn't.

Plus it means findAll() matches how js libs currently work.

Sean




Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Yehuda Katz
The only case I can think of where explicit scope might be useful would be
to filter out certain cases entirely:

elem.findAll(:scope:visible div);
elem.findAll(#contents :scope [data-foo])

It's probably fine to just say that you should do a match first in that
case, given the additional complexity of remembering all the rules. Alex,
what do you think?

Yehuda Katz
(ph) 718.877.1325


On Tue, Oct 25, 2011 at 2:33 PM, Sean Hogan shogu...@westnet.com.au wrote:

 On 26/10/11 7:51 AM, Tab Atkins Jr. wrote:

 On Tue, Oct 25, 2011 at 1:47 PM, Sean Hoganshogu...@westnet.com.au
  wrote:

 I think allowing explicit :scope in findAll() will be perpetually
 confusing.
 I can imagine someone looking at old code like:

 e.findAll(div.foo span, div.bar :scope span)

 and asking themselves what's the rule again? If there's :scope in the
 selector then there's no :scope implied? Or was that just on each single
 selector? Or is :scope always implied at the start of the whole selector
 list and that's why it's explicit in the second part? Dammit, why didn't
 we
 just use querySelectorAll() if we wanted explicit :scope?

 Using :scope explicitly at the beginning of selectors is necessary if
 we want a sane way to have selector lists chain off of the scoping
 element.  I'm okay with the string starting with a combinator when
 it's a single selector like + foo, but not when it's a selector list
 like + foo, + bar.

 ~TJ


 I didn't follow that. Why does findAll() need to support explicit :scope?

 It is simpler if querySelectorAll() supports explicit :scope and findAll()
 doesn't.
 Plus it means findAll() matches how js libs currently work.

 Sean




Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Tab Atkins Jr.
On Tue, Oct 25, 2011 at 2:33 PM, Sean Hogan shogu...@westnet.com.au wrote:
 On 26/10/11 7:51 AM, Tab Atkins Jr. wrote:
 On Tue, Oct 25, 2011 at 1:47 PM, Sean Hoganshogu...@westnet.com.au
  wrote:

 I think allowing explicit :scope in findAll() will be perpetually
 confusing.
 I can imagine someone looking at old code like:

     e.findAll(div.foo span, div.bar :scope span)

 and asking themselves what's the rule again? If there's :scope in the
 selector then there's no :scope implied? Or was that just on each single
 selector? Or is :scope always implied at the start of the whole selector
 list and that's why it's explicit in the second part? Dammit, why didn't
 we
 just use querySelectorAll() if we wanted explicit :scope?

 Using :scope explicitly at the beginning of selectors is necessary if
 we want a sane way to have selector lists chain off of the scoping
 element.  I'm okay with the string starting with a combinator when
 it's a single selector like + foo, but not when it's a selector list
 like + foo, + bar.

 I didn't follow that. Why does findAll() need to support explicit :scope?

Did you not understand my example?  el.find(+ foo, + bar) feels
really weird and I don't like it.  I'm okay with a single selector
starting with a combinator, like el.find(+ foo), but not a selector
list.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Sean Hogan

On 26/10/11 9:28 AM, Tab Atkins Jr. wrote:

On Tue, Oct 25, 2011 at 2:33 PM, Sean Hoganshogu...@westnet.com.au  wrote:

On 26/10/11 7:51 AM, Tab Atkins Jr. wrote:

On Tue, Oct 25, 2011 at 1:47 PM, Sean Hoganshogu...@westnet.com.au
  wrote:

I think allowing explicit :scope in findAll() will be perpetually
confusing.
I can imagine someone looking at old code like:

 e.findAll(div.foo span, div.bar :scope span)

and asking themselves what's the rule again? If there's :scope in the
selector then there's no :scope implied? Or was that just on each single
selector? Or is :scope always implied at the start of the whole selector
list and that's why it's explicit in the second part? Dammit, why didn't
we
just use querySelectorAll() if we wanted explicit :scope?

Using :scope explicitly at the beginning of selectors is necessary if
we want a sane way to have selector lists chain off of the scoping
element.  I'm okay with the string starting with a combinator when
it's a single selector like + foo, but not when it's a selector list
like + foo, + bar.

I didn't follow that. Why does findAll() need to support explicit :scope?

Did you not understand my example?  el.find(+ foo, + bar) feels
really weird and I don't like it.  I'm okay with a single selector
starting with a combinator, like el.find(+ foo), but not a selector
list.


So +foo becomes :scope +foo
But +foo, +bar throws an error?
What about:
+foo, bar
:scope+foo, bar
body :scope+foo, :scope+bar

What do JS lib selectors do? Do any support :scope? Do any not support 
+foo, +bar, foo, bar?


Sean




Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Yehuda Katz
The CSS grammar (http://www.w3.org/TR/selectors/#w3cselgrammar) has a
production for selector_group and selector. I would think that :scope would
be prepended to each selector, not the entire selector group.

-- Yehuda Katz

On Tuesday, October 25, 2011, Tab Atkins Jr. wrote:

 On Tue, Oct 25, 2011 at 2:33 PM, Sean Hogan 
 shogu...@westnet.com.aujavascript:;
 wrote:
  On 26/10/11 7:51 AM, Tab Atkins Jr. wrote:
  On Tue, Oct 25, 2011 at 1:47 PM, Sean 
  Hoganshogu...@westnet.com.aujavascript:;
 
   wrote:
 
  I think allowing explicit :scope in findAll() will be perpetually
  confusing.
  I can imagine someone looking at old code like:
 
  e.findAll(div.foo span, div.bar :scope span)
 
  and asking themselves what's the rule again? If there's :scope in the
  selector then there's no :scope implied? Or was that just on each
 single
  selector? Or is :scope always implied at the start of the whole
 selector
  list and that's why it's explicit in the second part? Dammit, why
 didn't
  we
  just use querySelectorAll() if we wanted explicit :scope?
 
  Using :scope explicitly at the beginning of selectors is necessary if
  we want a sane way to have selector lists chain off of the scoping
  element.  I'm okay with the string starting with a combinator when
  it's a single selector like + foo, but not when it's a selector list
  like + foo, + bar.
 
  I didn't follow that. Why does findAll() need to support explicit :scope?

 Did you not understand my example?  el.find(+ foo, + bar) feels
 really weird and I don't like it.  I'm okay with a single selector
 starting with a combinator, like el.find(+ foo), but not a selector
 list.

 ~TJ



-- 
Yehuda Katz
(ph) 718.877.1325


Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Bjoern Hoehrmann
* Tab Atkins Jr. wrote:
Did you not understand my example?  el.find(+ foo, + bar) feels
really weird and I don't like it.  I'm okay with a single selector
starting with a combinator, like el.find(+ foo), but not a selector
list.

Allowing + foo but not + foo, + bar would be really weird.
-- 
Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/ 



Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Tab Atkins Jr.
On Tue, Oct 25, 2011 at 4:56 PM, Ojan Vafai o...@chromium.org wrote:
 On Tue, Oct 25, 2011 at 4:44 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote:

 * Tab Atkins Jr. wrote:
 Did you not understand my example?  el.find(+ foo, + bar) feels
 really weird and I don't like it.  I'm okay with a single selector
 starting with a combinator, like el.find(+ foo), but not a selector
 list.

 Allowing + foo but not + foo, + bar would be really weird.

 Tab, what specifically is weird about el.find(+ foo, + bar)?

Seeing a combinator immediately after a comma just seems weird to me.
This may just be a personal prejudice.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Yehuda Katz
fwiw, jQuery doesn't properly handle the comma-separated case, but this is
most definitely a bug, caused by the naïve implementation that Alex showed
early on in this thread.

-- Yehuda

On Tuesday, October 25, 2011, Tab Atkins Jr. wrote:

 On Tue, Oct 25, 2011 at 4:56 PM, Ojan Vafai o...@chromium.orgjavascript:;
 wrote:
  On Tue, Oct 25, 2011 at 4:44 PM, Bjoern Hoehrmann 
  derhoe...@gmx.netjavascript:;
 wrote:
 
  * Tab Atkins Jr. wrote:
  Did you not understand my example?  el.find(+ foo, + bar) feels
  really weird and I don't like it.  I'm okay with a single selector
  starting with a combinator, like el.find(+ foo), but not a selector
  list.
 
  Allowing + foo but not + foo, + bar would be really weird.
 
  Tab, what specifically is weird about el.find(+ foo, + bar)?

 Seeing a combinator immediately after a comma just seems weird to me.
 This may just be a personal prejudice.

 ~TJ



-- 
Yehuda Katz
(ph) 718.877.1325


Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Sean Hogan

On 26/10/11 11:03 AM, Yehuda Katz wrote:
fwiw, jQuery doesn't properly handle the comma-separated case, but 
this is most definitely a bug, caused by the naïve implementation that 
Alex showed early on in this thread.




So no-one is actually using +foo, +bar? How common is +foo usage?

Sean




Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Ojan Vafai
On Tue, Oct 25, 2011 at 4:58 PM, Tab Atkins Jr. jackalm...@gmail.comwrote:

 On Tue, Oct 25, 2011 at 4:56 PM, Ojan Vafai o...@chromium.org wrote:
  On Tue, Oct 25, 2011 at 4:44 PM, Bjoern Hoehrmann derhoe...@gmx.net
 wrote:
 
  * Tab Atkins Jr. wrote:
  Did you not understand my example?  el.find(+ foo, + bar) feels
  really weird and I don't like it.  I'm okay with a single selector
  starting with a combinator, like el.find(+ foo), but not a selector
  list.
 
  Allowing + foo but not + foo, + bar would be really weird.
 
  Tab, what specifically is weird about el.find(+ foo, + bar)?

 Seeing a combinator immediately after a comma just seems weird to me.
 This may just be a personal prejudice.


With my web developer hat on, I would expect the selector list version to
just be a comma-separated list of any valid single selectors. We should
either allow it in both cases or neither IMO. My preference is to allow it.

Ojan


Re: QSA, the problem with :scope, and naming

2011-10-25 Thread Bjoern Hoehrmann
* Tab Atkins Jr. wrote:
On Tue, Oct 25, 2011 at 4:56 PM, Ojan Vafai o...@chromium.org wrote:
 On Tue, Oct 25, 2011 at 4:44 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote:
 * Tab Atkins Jr. wrote:
 Did you not understand my example?  el.find(+ foo, + bar) feels
 really weird and I don't like it.  I'm okay with a single selector
 starting with a combinator, like el.find(+ foo), but not a selector
 list.

 Allowing + foo but not + foo, + bar would be really weird.

 Tab, what specifically is weird about el.find(+ foo, + bar)?

Seeing a combinator immediately after a comma just seems weird to me.

A list of abbreviated selectors is a more intuitive concept than a
list of selectors where the first and only the first selector may be
abbreviated. List of type versus special case and arbitrary limit.
If one abbreviated selector isn't weird, then two shouldn't be either
if two selectors aren't weird on their own.
-- 
Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/ 



Re: QSA, the problem with :scope, and naming

2011-10-23 Thread Sean Hogan

On 23/10/11 5:44 AM, Timmy wrote:

On Oct 21, 2011, at 7:57 PM, Sean Hogan wrote:

It was definitely not a design flaw in QSA. As Alex's sample code shows it is 
possible to get findAll() behavior using QSA.

I think that further supports my argument.  JS libraries have commonly 
considered this to be an oversight in the design of QSA, hence the need for ID 
hack.  That is still true whether it was actually a design flaw or not.


To do the reverse would involve calling document.findAll() then filtering for 
nodes that are descendants of the invoking node.

I don't think anyone is interested in implementing the reverse in selector 
engines.  The most useful thing would be elem.findAll().  No manual filtering 
required.


rant
This sounds like:

Although X is more composable than Y, this is irrelevant because no-one 
would use X if Y is available.


This was the rationale used for removing matchesSelector() from the 
original Selectors API spec.


In my experience, when someone (me, for instance) or a committee or 
work-group can't think of a benefit of a more composable function it 
merely indicates a limited experience or imagination.


Once it has been decided that an API will be provided for a particular 
feature, the more primitive methods should be available by default. To 
*not* include them should require good reasons.


More specific methods should require use-cases and a rationale for why 
they shouldn't be composed from other methods.


Anyway, the use-case for element.querySelectorAll() - apart from being 
called from selector engines in js libs - is quite straight-forward.


Say I want to augment all elements in a page that match a given 
selector. After the page has loaded I can find all the elements by 
calling document.querySelectorAll(). When new content is added into the 
page I don't want to call document.querySelectorAll() and filter out 
already augmented elements. But if I only had element.findAll() then I 
might miss elements that match the selector because for findAll() the 
*whole* selector must match within the scope of element.


This is similar to the way jQuery.fn.delegate() works. One of the 
strengths of .delegate() is that it can handle events for elements that 
match the given selector even if the element wasn't in the document when 
delegate() was called. But .delegate() scopes selectors to the whole 
document, not the invoking nodes.

/rant


But if findAll() is implemented they can advertise that avoiding non-standard 
pseudo selectors gives virtually native performance (on supporting platforms). 
I imagine this would be almost equivalent to deprecating them, which would be a 
win.

This is extraneous.  The implementation of custom pseudo selectors would be 
identical.


Well, no-one can prevent JS libs implementing custom pseudo selectors, 
just as they can't be prevented from implementing custom DOM methods, 
e.g. HTMLElement.prototype.awesome().
But they both have the same negatives, most especially that if the 
method name / pseudo-selector name is one day implemented in browsers 
but with a different definition then code that was relying on the 
library will start receiving the different native behavior.


Of course, there are counter-arguments to the negatives. Never-the-less 
it is considered good practice (good web-citizenship if you like) to use 
vendor prefixes for custom methods and custom selectors.


Sean




Re: QSA, the problem with :scope, and naming

2011-10-22 Thread Timmy
On Oct 21, 2011, at 7:57 PM, Sean Hogan wrote:
 It was definitely not a design flaw in QSA. As Alex's sample code shows it is 
 possible to get findAll() behavior using QSA.
I think that further supports my argument.  JS libraries have commonly 
considered this to be an oversight in the design of QSA, hence the need for ID 
hack.  That is still true whether it was actually a design flaw or not.

 To do the reverse would involve calling document.findAll() then filtering for 
 nodes that are descendants of the invoking node. 
I don't think anyone is interested in implementing the reverse in selector 
engines.  The most useful thing would be elem.findAll().  No manual filtering 
required.

 
 But if findAll() is implemented they can advertise that avoiding non-standard 
 pseudo selectors gives virtually native performance (on supporting 
 platforms). I imagine this would be almost equivalent to deprecating them, 
 which would be a win. 

This is extraneous.  The implementation of custom pseudo selectors would be 
identical.

- Timmy


Re: QSA, the problem with :scope, and naming

2011-10-21 Thread Jonas Sicking
On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt lachlan.h...@lachy.id.au
wrote:
 Not necessarily.  It depends what exactly it means for a selector to
contain
 :scope for determining whether or not to enable the implied :scope
 behaviour.  Consider:

  foo.find(:not(:scope));

Ooh, this is an interesting case too. So here's the full list of cases which
we need defined behavior for (again looking at Alex and Yehuda here).

In the following DOM

body id=3
 div id=0/div
 div id=context foo=bar
  div id=1/div
  div class=class id=2/div
  div class=withChildren id=3div class=child id=4/div/div
 /div
 div id=5/div
 div id=6/div
/body

What would each of the following .findAll calls return. I've included my
guessed based on the discussions so far:

var e = document.getElementById('context');

e.findAll(div)  // returns ids 1,2,3,4
e.findAll()  // returns an empty list
e.findAll(#3)  // returns id 3, but not the body node
e.findAll( div) // returns ids 1,2,3
e.findAll([foo=bar]) // returns nothing
e.findAll([id=1]) // returns id 1
e.findAll(:first-child) // returns id 1
e.findAll(+ div) // returns id 5
e.findAll(~ div) // returns id 5, 6
e.findAll(:scope)
e.findAll(div:scope)
e.findAll([foo=bar]:scope)
e.findAll(:scope div)
e.findAll(div:scope div)
e.findAll(div:scope #3)
e.findAll(body  :scope  div)
e.findAll(div, :scope)
e.findAll(body  :scope  div, :scope)
e.findAll(:not(:scope))

/ Jonas


Re: QSA, the problem with :scope, and naming

2011-10-21 Thread Willison, Timothy
On Oct 20, 2011, at 4:34 PM, Tab Atkins Jr. wrote:

 On Thu, Oct 20, 2011 at 12:09 PM, Jonas Sicking jo...@sicking.cc wrote:
 Let's do the general discussion about how live and non-live NodeLists
 should behave in a separate thread.
 
 Yes, let's.  ^_^
 
 
 The immediate question here is how should the returned object from
 .findAll behave? Should it be mutable? Should you be able to insert
 non-Nodes into it? Should it have all of the functions of
 Array.prototype or just some subset? Should it have any additional
 functions?
 
 Since .findAll is a new function we have absolutely no constraints as
 far as how NodeLists behave, we can simply return something that isn't
 a NodeList.
 
 It should absolutely have all the Array functions.  I know that I want
 to be able to slice, append, forEach, map, and reduce the list
 returned by .find.
 

IMHO, the most useful thing would be to just return an Array of nodes so no 
further adjustment of the return value is required in selector engines.

 ~TJ
 





Re: QSA, the problem with :scope, and naming

2011-10-21 Thread Sean Hogan

On 20/10/11 12:39 AM, Timmy Willison wrote:
From the perspective of building a selector engine, I think all 
selector engines need something like .findAll, and not something like 
:scope.


On Tue, Oct 18, 2011 at 8:00 PM, Alex Russell slightly...@google.com 
mailto:slightly...@google.com wrote:


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 http://root.id = root.id
http://root.id||(qUnique+(ctr++));
   query = #+root.id
http://root.id+ +query;
   }

   return Array.prototype.slice.call(
   doc.querySelectorAll(query)
   );
   };
   })();

This is exactly the same dance that :scope does.


Sizzle and Slick do the same thing. As far as I can tell, nwmatcher 
doesn't deal with it.  We can't just add :scope to all selections (for 
many reasons) and adding just before QSA would require the same logic 
that Alex has demonstrated above.


All of the selector engines do predictions at loadtime on whether QSA 
will work.  They continue differently beyond that, but one thing every 
library has in common is a try/catch around the call to QSA that falls 
back to manual parsing if it throws an exception (intentionally 
avoiding the need for complete parsing before calling QSA).  The point 
is it is a misconception that selector engines parse selectors before 
delegating to QSA. The number of things libraries want to do before 
getting to the QSA call is very minimal.  The one that hurts us all 
the most is this need for scoping and ':scope' would simply never be 
used in a selector engine, since the id trick already works 
everywhere.  The case Alex wrote above is pretty much the only case 
where the selector is parsed beyond checking for tag only, id only, or 
class only and it is due to what all of the js libraries has 
considered a design flaw in QSA.  A method like findAll would fix 
that, leaving as much parsing as possible in the hands of the browser.




It was definitely not a design flaw in QSA. As Alex's sample code shows 
it is possible to get findAll() behavior using QSA. To do the reverse 
would involve calling document.findAll() then filtering for nodes that 
are descendants of the invoking node.


Clearly JS libs aren't going to switch from implied :scope to explicit 
:scope.


But if findAll() is implemented they can advertise that avoiding 
non-standard pseudo selectors gives virtually native performance (on 
supporting platforms). I imagine this would be almost equivalent to 
deprecating them, which would be a win.


PS - I should say I don't necessarily think the name 'findAll' would 
work. I agree it should be short.  The equivalent of querySelector 
would be find and in library land 'find' selects more than one thing, 
but I'm not as concerned about the name.




Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 1:07 PM, Jonas Sicking wrote:

On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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.



I like the general idea here. And since we're changing behavior, I
think it's a good opportunity to come up with shorter names. Naming is
really hard. The shorter names we use, the more likely it is that
we're going to break webpages which are messing around with the
prototype chain and it increases the risk that we'll regret it later
when we come up with even better functions which should use those
names. Say that we come up with an even better query language than
selectors, at that point .find will simply not be available to us.

However, it does seem like selectors are here to stay. And as much as
they have shortcomings, people seem to really like them for querying.

So with that out of the way, I agree that the CSS working group
shouldn't be what is holding us back.


I don't agree with Selectors API supporting invalid selectors, but I 
guess the discussion is more appropriate here than there.



However we do need a precise
definition of what the new function does. Is prepending :scope  and
then parsing as a normal selector always going to give the behavior we
want? This is actually what I think we got stuck on when the original
querySelector was designed.

So let's get into specifics about how things should work. According to
your proposal of simply prepending a conceptual :scope to each
selector group, for the following DOM:

body id=3
   div id=context foo=bar
 div id=1/div
 div class=class id=2/div
 div class=withChildren id=3div class=child id=4/div/div
   /div
/body

you'd get the following behavior:

.findAll(div)  // returns ids 1,2,3,4
.findAll()  // returns the context node itself. This was
indicated undesirable
.findAll(body  :scope  div)  // returns nothing
.findAll(#3)  // returns id 3, but not the body node
.findAll(  div) // returns ids 1,2,3
.findAll([foo=bar]) // returns nothing
.findAll([id=1]) // returns id 1
.findAll(:first-child) // returns id 1

Is this desired behavior in all cases except the empty string? If so
this seems very doable to me. We can easily make an exception for the
case when the passed in string contains no selectors and make that an
error or some such.


I know everyone knows this, but...

These specific examples (where the selector is not a comma separated 
list) plus most instances of selector lists (e.g. th, td,  ul  li, 
 ol  li) can be trivially supported by a tiny wrapper around 
querySelectorAll() as defined in Selectors API v2. In fact, I've never 
seen a selector list that couldn't be successfully split on , and I 
wouldn't be surprised if they are never used outside of stylesheets.



I do however like the idea that if :scope appears in the selector,
then this removes the prepending of :scope  to that selector group.
Is there a reason not to do that?


1. Already supported (in the draft spec) by querySelectorAll().
2. Not supported by JS libs.
3. No use cases requiring it.


Additionally it seems to me that we could allow the same syntax for
style scoped. But maybe others disagree?


Surely it is both or neither. You don't want to set a precedent for DOM 
selectors not matching CSS selectors.



I think appropriate optimizations as well as extensible functions
should be out-of-scope for this thread. They are both big subjects on
their own and we're approaching 50 emails in this thread.






Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Jonas Sicking
On Wed, Oct 19, 2011 at 11:14 PM, Sean Hogan shogu...@westnet.com.au wrote:
 I do however like the idea that if :scope appears in the selector,
 then this removes the prepending of :scope  to that selector group.
 Is there a reason not to do that?

 1. Already supported (in the draft spec) by querySelectorAll().
 2. Not supported by JS libs.
 3. No use cases requiring it.

It's annoying if querying engines have to work with two different
query methods (.findAll and .querySelectorAll) and know when to call
which. So I don't think 1 is a particularly good point.

However 3 is a very good point. If there aren't use cases, then we
shouldn't support it. And 2 is a good indicator that there aren't use
cases.

But if someone knows of use cases then I'm all ears.

It's also something that can be added at a later point if use cases arise.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 5:41 PM, Jonas Sicking wrote:

On Wed, Oct 19, 2011 at 11:14 PM, Sean Hoganshogu...@westnet.com.au  wrote:

I do however like the idea that if :scope appears in the selector,
then this removes the prepending of :scope  to that selector group.
Is there a reason not to do that?

1. Already supported (in the draft spec) by querySelectorAll().
2. Not supported by JS libs.
3. No use cases requiring it.

It's annoying if querying engines have to work with two different
query methods (.findAll and .querySelectorAll) and know when to call
which. So I don't think 1 is a particularly good point.


I don't follow that.
If you want style scoped behavior you call findAll().
If not you call querySelectorAll().

Sean




Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Roland Steiner
On Thu, Oct 20, 2011 at 14:08, Tab Atkins Jr. jackalm...@gmail.com wrote:

 style scoped should (I think) have three cases:

 1. Selector without :scope - same as .find
 2. Selector with :scope - Same as #1, but also including the context node.
 3. Selector in @global - run the selector across the entire document,
 filter the results to only be the context node and its descendants.

 (Some people disagree with me on this, and think that #1 and #2 should
 be merged to always include the context node.  That's acceptable, but
 I don't like it as much.)


The - very valid IMHO - main argument for style scoped to always include
the scoping element was to allow for easy migration. I.e., where currently
you'd use

style
#menu .foo { color: green }
/style

div id=menu
div class=foo
Will be green
/div
/div
div class=foo
Will NOT be green
/div

You could just stick the stylesheet under the div and add 'scoped':

div id=menu
style scoped
#menu .foo { color: green }
/style
div class=foo
Will be green
/div
/div
div class=foo
Will NOT be green
/div

In browsers that don't support 'scoped', this would still work. Where
'scoped' is supported, this doesn't change much per se, except that those
style rules don't need to be checked outside the scope. Once a majority of
browsers support style scoped one can then proceed to simplify the rules
and remove '#menu' (admitted caveat: where this then doesn't create an
ambiguity with the scoping div).


- Roland


Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Roland Steiner
On Thu, Oct 20, 2011 at 14:52, Jonas Sicking jo...@sicking.cc wrote:

  style scoped should (I think) have three cases:
 
  1. Selector without :scope - same as .find
  2. Selector with :scope - Same as #1, but also including the context
 node.
  3. Selector in @global - run the selector across the entire document,
  filter the results to only be the context node and its descendants.
 
  (Some people disagree with me on this, and think that #1 and #2 should
  be merged to always include the context node.  That's acceptable, but
  I don't like it as much.)
 
  I think it's perfectly okay that these two APIs have different cases.

 I'm not sure I understand what you are proposing here. Are you saying that

 div
 style scoped
 :scope {
  background: green;
 }
 /style
 /div

 should set the background of the div green? This does seem intuitive
 I agree, but it might also lead to strange behavior since the
 rendering of the div will change once the stylesheet is parsed. In
 other words, it's very easy to get flash-of-unstyled-content behavior.


Hixie's - again valid IMHO - counterargument for this was that, with the
above proposal:

div { background-color-green }

would not color the scoping element, while the more specific (!)

div:scope { background-color: green }

would. I.e., a more specific selector suddenly selecting MORE elements than
a not so specific one.


- Roland


Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 1:07 PM, Jonas Sicking wrote:

On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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.



  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);


I like the general idea here.

I think appropriate optimizations as well as extensible functions
should be out-of-scope for this thread. They are both big subjects on
their own and we're approaching 50 emails in this thread.


If find / findAll are added to the spec there should also be an 
equivalent of matchesSelector that handles implicitly scoped selector, 
e.g.  div  .thinger. To aid discussion I will call this matches(), 
but I don't think it is a good final choice.


The primary use-case for matchesSelector() has been event-delegation, 
and this is the same for matches(). More specifically, consider the 
following scenario:


jQuery adds a new event registration method that uses event delegation 
to mimic the behavior of:

$(elem).find( div  .thinger).bind(eventType, fn);
The new method is called proxybind(), and the equivalent of the above is:
$(elem).proxybind( div  .thinger, eventType, fn);

The event handling for proxybind() would invoke matches( div  
.thinger, [elem]) on elements between the event target and elem to find 
matching elements.


Sean




Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Jonas Sicking
On Thu, Oct 20, 2011 at 1:14 AM, Sean Hogan shogu...@westnet.com.au wrote:
 On 20/10/11 1:07 PM, Jonas Sicking wrote:

 On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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.

  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);

 I like the general idea here.

 I think appropriate optimizations as well as extensible functions
 should be out-of-scope for this thread. They are both big subjects on
 their own and we're approaching 50 emails in this thread.

 If find / findAll are added to the spec there should also be an equivalent
 of matchesSelector that handles implicitly scoped selector, e.g.  div 
 .thinger. To aid discussion I will call this matches(), but I don't think
 it is a good final choice.

How would .matches() work? For .findAll we basically prepend a :scope
 selector step where the :scope pseudo-class matches the element on
which .findAll was called.

If we did the same for .matches() then

elem.matches(foo)

would try to match elem against the selector :scope foo where
:scope only matches elem and thus the selector only matches elements
which are descendants of the element on which .matches() was called.

In other words, .matches() would never match anything.

Clearly you must have some other behavior in mind as a function which
always returns false isn't particularly interesting.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 7:32 PM, Jonas Sicking wrote:

On Thu, Oct 20, 2011 at 1:14 AM, Sean Hoganshogu...@westnet.com.au  wrote:

On 20/10/11 1:07 PM, Jonas Sicking wrote:

On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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.
  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);


I like the general idea here.

I think appropriate optimizations as well as extensible functions
should be out-of-scope for this thread. They are both big subjects on
their own and we're approaching 50 emails in this thread.

If find / findAll are added to the spec there should also be an equivalent
of matchesSelector that handles implicitly scoped selector, e.g.   div
.thinger. To aid discussion I will call this matches(), but I don't think
it is a good final choice.

How would .matches() work? For .findAll we basically prepend a :scope
 selector step where the :scope pseudo-class matches the element on
which .findAll was called.

If we did the same for .matches() then

elem.matches(foo)

would try to match elem against the selector :scope foo where
:scope only matches elem and thus the selector only matches elements
which are descendants of the element on which .matches() was called.

In other words, .matches() would never match anything.

Clearly you must have some other behavior in mind as a function which
always returns false isn't particularly interesting.

/ Jonas


See the definition of matchesSelector(selector, [ refNodes ]) in the spec:
http://www.w3.org/TR/selectors-api2/#matchtesting




Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Jonas Sicking
On Thu, Oct 20, 2011 at 2:13 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-20 07:52, Jonas Sicking wrote:

 I'm not sure I understand what you are proposing here. Are you saying that

 div
 style scoped
 :scope {
   background: green;
 }
 /style
 /div

 should set the background of thediv  green? This does seem intuitive
 I agree, but it might also lead to strange behavior since the
 rendering of thediv  will change once the stylesheet is parsed. In
 other words, it's very easy to get flash-of-unstyled-content behavior.

 In the majority of cases, that's a very easy problem for authors to avoid by
 always putting style scoped as the first child of the element.  Since a
 div is invisible in most cases without any content or other styles, any
 change in rendering from invisible to visible wouldn't be any different from
 normal incremental rendering.

You'd also get the same effect since earlier siblings of the style
scoped would be affected, right?

I.e. in the following markup, both spans would be blue and the div
would be green.
div
spantext here/span
style scoped
:scope span { background: green }
:scope { background: red }
/style
spanmore text here/span
/div

Another problem though is one of performance. Allowing style
elements which are later in the DOM affect earlier nodes means that
you have to walk significantly more nodes to look for which sheet
could apply. You'll have to both look at the elements children, as
well as all following siblings.

If style scoped elements only affect nodes which are later in DOM
order, it's much easier to keep a list of all currently applying
style scoped elements as you walk through the DOM tree.

However it's possible that this can be optimized satisfactory. But
it's something that we need implementation feedback on.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 8:42 PM, Lachlan Hunt wrote:

On 2011-10-20 10:14, Sean Hogan wrote:

The primary use-case for matchesSelector() has been event-delegation,
and this is the same for matches(). More specifically, consider the
following scenario:

jQuery adds a new event registration method that uses event delegation
to mimic the behavior of:
$(elem).find( div  .thinger).bind(eventType, fn);
The new method is called proxybind(), and the equivalent of the above 
is:

$(elem).proxybind( div  .thinger, eventType, fn);

The event handling for proxybind() would invoke matches( div 
.thinger, [elem]) on elements between the event target and elem to find
matching elements.


It may not be too late to introduce that behaviour into 
matchesSelector, with a switch based on the presence or absence of the 
refNodes/refElement parameter.


As currently specified, calling the following doesn't and shouldn't 
prepend :scope.


  el.matchesSelector(div .foo);

This one also matches the prefixed implementations in browsers, since 
most haven't started supporting :scope yet, and I don't believe 
Mozilla's experimental implementation [1] has landed yet.


As currently specified, calling this:

  el.matchesSelector(div .foo, ref);

Also doesn't prepend :scope automatically, but in that case, the ref 
nodes do nothing useful. 


But this selector can still match elements. Admittedly I can't think of 
a use-case for this, but it is conceivable for someone to expect this to 
work without an implied :scope.


Authors have to use :scope explicitly for them to be useful as in 
something like:


  el.matchesSelector(:scope div .foo, ref);

Or

  el.matchesSelector(div:scope .foo, ref);

One thing we could possibly do is define that if ref nodes are passed, 
and the selector doesn't explicitly use :scope, then effectively 
prepend :scope .  This would be exactly the same behaviour as that 
discussed for .findAll();


That wouldn't break compatibility with anything, optimises for a 
common case and avoids introducing two separate match methods.




I don't see the need for findAll(), but if it is added I think it should 
always imply :scope  at the start of a selector, and I think a 
separate match method that does the same should be added. To do 
otherwise seems too ambiguous for a DOM API.



e.g.
el.matchesSelector(div .foo); // No ref, no magic :scope

el.matchesSelector(div .foo, ref);// Implied, magic :scope
el.matchesSelector(+.foo, ref);   // Implied, magic :scope

el.matchesSelector(:scope div .foo, ref); // Explicit, no magic :scope
el.matchesSelector(div:scope .foo, ref);  // Explicit, no magic :scope

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=648722






Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Alex Russell
On Wed, Oct 19, 2011 at 7:01 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-19 16:08, Alex Russell wrote:

 On Wed, Oct 19, 2011 at 1:54 PM, Lachlan Huntlachlan.h...@lachy.id.au
  wrote:

 I have attempted to address this problem before and the algorithm for
 parsing a *scoped selector string* (basically what you're calling a
 rootedSelector) existed in an old draft [1].

 That draft also allowed the flexibility of including an explicit :scope
 pseudo-class in the selector, which allows for conditional expressions to
 be
 built into the selector itself that can be used to check the state of the
 scope element or any of its ancestors.

 We could accomodate that by looking at the passed selector and trying
 to determine if it includes a :scope term. If so, avoid prefixing.

 Yes, that's exactly what the draft specified.

Great! So if we specify this behavior for .find() too, I think we're
in good shape.

 That'd allow this sort of flexibility for folks who want to write
 things out long-hand or target the scope root in the selector,
 possibly returning itself.

 I don't see a use case for wanting the proposed method to be able to return
 the element itself.  The case where it's useful for elements matching :scope
 to be the subject of a selector is where you're trying to filter a list of
 elements.

 e.g.
  document.querySelectorAll(.foo:scope, list);
  // Returns all elements from list that match.

 But this wouldn't make sense

  el.find(.foo:scope) // Return itself if it matches.

Ok, I'm fine with not allowing that.

 That result seems effectively like a less efficient boolean check that is
 already handled by el.matchesSelector(.foo).

matchesSelector...really? We've gotta get a better name for that = )

 I''d also support a resolution for this sort of power-tool that
 forces people to use document.qsa(...,scopeEl) to get at that sort
 of thing.

 If there was no special handling to check for an explicit :scope, that would
 mean that any selector that does include :scope explicitly would not match
 anything at all.

 e.g. el.findAll(:scopep);

yeah, that occurred to me after sending the last mail.

 That would be equivalent to:

  document.querySelectorAll(:scope :scopep, el);

 Which won't match anything.

 That might keep things simpler from an implementation perspective and
 doesn't sacrifice any functionality being requested.

Eh, I'm not sure it's sane though. Putting in checking for :scope in
the selector and not prefixing if it occurs seems the only reasonable
thing. There's a corner case I haven't formed an opinion on though:

   el.find(div span :scope .whatevs);

...does what? I think it's an error. :scope will need to occur in
the first term or not at all for .find().

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




Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Alex Russell
On Thu, Oct 20, 2011 at 3:07 AM, Jonas Sicking jo...@sicking.cc wrote:
 On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell slightly...@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. 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?

 I like the general idea here. And since we're changing behavior, I
 think it's a good opportunity to come up with shorter names. Naming is
 really hard. The shorter names we use, the more likely it is that
 we're going to break webpages which are messing around with the
 prototype chain and it increases the risk that we'll regret it later
 when we come up with even better functions which should use those
 names.

So long as the slots are still writable, no loss. Their patches into
the prototype chain still exist. Being afraid of this when we're on
top seems really, *REALLY* strange to me.

 Say that we come up with an even better query language than
 selectors, at that point .find will simply not be available to us.

Premature optimization. And $ is still available ;-)

 However, it does seem like selectors are here to stay. And as much as
 they have shortcomings, people seem to really like them for querying.

 So with that out of the way, I agree that the CSS working group
 shouldn't be what is holding us back. However we do need a precise
 definition of what the new function does. Is prepending 

Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Alex Russell
On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sicking jo...@sicking.cc wrote:
 On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell slightly...@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. 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?

 Oh, and as a separate issue. I think .findAll should return a plain
 old JS Array. Not a NodeList or any other type of host object.

I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.
It's insane that we even have a NodeList type which isn't a real array
at all. Adding a parallel system when we could just fix the one we
have (and preserve the value of a separate prototype for extension) is
wonky to me.

That said, I'd *also* support the ability to have some sort of
decorator mechanism before return on .find() or a way to re-route the
prototype of the returned Array.

+heycam to debate this point.

 One of
 the use cases is being able to mutate the returned value. This is
 useful if you're for example doing multiple .findAll calls (possibly
 with different context nodes) and want to merge the resulting lists
 into a single list.

Agreed. An end to the Array.slice() hacks would be great.



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Lachlan Hunt

On 2011-10-20 12:50, Alex Russell wrote:

On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sickingjo...@sicking.cc  wrote:

Oh, and as a separate issue. I think .findAll should return a plain
old JS Array. Not a NodeList or any other type of host object.


I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.


We need NodeList separate from Array where they are live lists.  I 
forget the reason we originally opted for a static NodeList rather than 
Array when this issue was originally discussed a few years ago.


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



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Alex Russell
On Thu, Oct 20, 2011 at 12:05 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-20 12:50, Alex Russell wrote:

 On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sickingjo...@sicking.cc  wrote:

 Oh, and as a separate issue. I think .findAll should return a plain
 old JS Array. Not a NodeList or any other type of host object.

 I strongly agree that it should be an Array *type*, but I think just
 returning a plain Array is the wrong resolution to our NodeList
 problem. WebIDL should specify that DOM List types *are* Array types.

 We need NodeList separate from Array where they are live lists.

No we don't. The fact that there's someone else who has a handle to
the list and can mutate it underneath you is a documentation issue,
not a question of type...unless the argument is that the slots should
be non-configurable, non-writable except by the browser that's also
holding a ref to it.

  I forget
 the reason we originally opted for a static NodeList rather than Array when
 this issue was originally discussed a few years ago.



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 10:05 PM, Lachlan Hunt wrote:

On 2011-10-20 12:50, Alex Russell wrote:

On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sickingjo...@sicking.cc  wrote:

Oh, and as a separate issue. I think .findAll should return a plain
old JS Array. Not a NodeList or any other type of host object.


I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.


We need NodeList separate from Array where they are live lists.  I 
forget the reason we originally opted for a static NodeList rather 
than Array when this issue was originally discussed a few years ago.




I wonder if anyone is relying on querySelectorAll() returning a 
StaticNodeList?





Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Lachlan Hunt

On 2011-10-20 13:18, Alex Russell wrote:

On Thu, Oct 20, 2011 at 12:05 PM, Lachlan Huntlachlan.h...@lachy.id.au  wrote:

We need NodeList separate from Array where they are live lists.


No we don't. The fact that there's someone else who has a handle to
the list and can mutate it underneath you is a documentation issue,
not a question of type...unless the argument is that the slots should
be non-configurable, non-writable except by the browser that's also
holding a ref to it.


The author cannot be allowed to directly modify a live list, as such it 
must be an immutable object from the script's perspective.  Otherwise, 
things would get really complicated if this happened:


var p = document.getElementsByTagName(p);
p.reverse();
p.push(x);
p.shift();
document.body.insertBefore(document.createElement(p), p[2]);

Where in the array would that new P element get added?

NodeLists are supposed to be live and in document order.  Ordinarily, 
that new P element would be inserted into the document and the change 
reflected in the NodeList.  By allowing an author to modify the list in 
some way, that completely breaks the way NodeLists are defined to work. 
 Now while it's arguable that live node lists were a mistake and that 
it would have been better if static Arrays were returned, we are stuck 
with them and cannot change that.


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



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Tab Atkins Jr.
On Thu, Oct 20, 2011 at 3:39 AM, Alex Russell slightly...@google.com wrote:
 There's a corner case I haven't formed an opinion on though:

   el.find(div span :scope .whatevs);

 ...does what? I think it's an error. :scope will need to occur in
 the first term or not at all for .find().

Disagree.  If :scope appears in the selector, just match across the
whole document.  It's simple and useful.  (It's equivalent to
document.querySelector(div span :scope .whatevs, el), except shorter
and amenable to chaining.)

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Lachlan Hunt

On 2011-10-20 13:35, Sean Hogan wrote:

I wonder if anyone is relying on querySelectorAll() returning a
StaticNodeList?


Only if there are people out there using list.item(n) instead of 
list[n], or people extending the NodeList interface and expecting such 
methods to be available on the result.  Though I suspect the former is 
very rare, and the latter doesn't work in all browsers.


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



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Sean Hogan

On 20/10/11 10:49 PM, Lachlan Hunt wrote:

On 2011-10-20 13:35, Sean Hogan wrote:

I wonder if anyone is relying on querySelectorAll() returning a
StaticNodeList?


Only if there are people out there using list.item(n) instead of 
list[n], or people extending the NodeList interface and expecting such 
methods to be available on the result.  Though I suspect the former is 
very rare, and the latter doesn't work in all browsers.




And I wonder if one of the browser vendors would be willing to silently 
change the behavior and see if they get any bug reports.





Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Boris Zbarsky

On 10/20/11 6:50 AM, Alex Russell wrote:

Oh, and as a separate issue. I think .findAll should return a plain
old JS Array. Not a NodeList or any other type of host object.


I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.


You missed the point of Jonas's suggestion.

DOM NodeLists are not mutable via direct manipulation of indexed 
properties.  Jonas is saying that we want the return value here to be 
thus mutable.


Making all DOM NodeLists mutable won't really work because a bunch of 
them are live; there's no sane way to combine liveness and mutability.


The non-live lists (e.g. the one involved here) could be made mutable, 
but then why make then nodelists at all?  What's the point?



It's insane that we even have a NodeList type which isn't a real array
at all.


It's not at all insane for the live lists.  See previous discussion 
about this.


I think any solution here that tries to treat live and non-live lists 
identically is doomed to failure.


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Boris Zbarsky

On 10/20/11 7:18 AM, Alex Russell wrote:

No we don't. The fact that there's someone else who has a handle to
the list and can mutate it underneath you


There is no sane way to mutate the list on the part of the browser if 
someone else is also messing with it, because the someone else can 
violate basic invariants the browser's behavior needs to maintain.



unless the argument is that the slots should
be non-configurable, non-writable except by the browser that's also
holding a ref to it.


Yes.

Though I don't know what slots you're talking about; the only sane JS 
implementation of live nodelists is as a proxy.  There's no way to get 
the behaviors that browsers have for them otherwise.


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Alex Russell
On Thu, Oct 20, 2011 at 3:14 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 10/20/11 7:18 AM, Alex Russell wrote:

 No we don't. The fact that there's someone else who has a handle to
 the list and can mutate it underneath you

 There is no sane way to mutate the list on the part of the browser if
 someone else is also messing with it, because the someone else can violate
 basic invariants the browser's behavior needs to maintain.

Right. So you need to vend an apparently-immutable Array, one which
can only be changed by the browser. I think that could be accomplished
in terms of Proxies. But it's still an Array type.

 unless the argument is that the slots should
 be non-configurable, non-writable except by the browser that's also
 holding a ref to it.

 Yes.

 Though I don't know what slots you're talking about; the only sane JS
 implementation of live nodelists is as a proxy.  There's no way to get the
 behaviors that browsers have for them otherwise.

But it can be a Proxy to an *Array*, not to some weird non-Array type.



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Boris Zbarsky

On 10/20/11 10:23 AM, Alex Russell wrote:

On Thu, Oct 20, 2011 at 3:14 PM, Boris Zbarskybzbar...@mit.edu  wrote:
Right. So you need to vend an apparently-immutable Array, one which
can only be changed by the browser. I think that could be accomplished
in terms of Proxies. But it's still an Array type.


I have no problem with Array being on the prototype chain or whatnot. 
But it's not an array in the sense that you can't do a bunch of things 
with it that people do with arrays.



Though I don't know what slots you're talking about; the only sane JS
implementation of live nodelists is as a proxy.  There's no way to get the
behaviors that browsers have for them otherwise.


But it can be a Proxy to an *Array*, not to some weird non-Array type.


Why does it matter what it's a proxy to?  The whole point of being a 
proxy is that you can't tell what it's proxying.


Case in point, in Gecko it's a proxy to something that's not a JS object 
at all and not even implementable in JS (because it uses internal engine 
information that's not available to JS).


So what exactly do you want here other than nodelists having 
Array.prototype on their prototype chain, which is discussed elsewhere?


And again, for static nodelists none of this applies; there's absolutely 
no reason I can think of to not make them arrays, unless you really want 
a .item() on them or unless you really think the length getter should be 
hookable.


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Lachlan Hunt

On 2011-10-20 16:23, Boris Zbarsky wrote:

On 10/20/11 1:08 AM, Tab Atkins Jr. wrote:

I disagree. It's extremely useful and natural for .find(:scope +
div) to match sibling of the context node.


I really don't think it is. If you want that, use document.find(:scope
+ div, context).


Basically, the presence of :scope would turn off *all* the limitations


That's a _really_ bizarre behavior. So in this case:

foo.find(:scope + div, div)

what all divs in the document would be found? Or is the oh, ignore the
reference node except for matching :scope meant to only apply on a
per-selector basis inside the selector list? That has its own issues,
especially with performance (e.g. merging nodesets while preserving DOM
order).


As it was specified in the old draft of queryScopedSelector (which is 
the definition I start with if find/findAll get introduced), it was done 
on a per selector basis, so the above would be equivalent to:


document.querySelector(:scope + div, :scope div, foo);

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



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Erik Arvidsson
On Thu, Oct 20, 2011 at 04:18, Alex Russell slightly...@google.com wrote:
 No we don't. The fact that there's someone else who has a handle to
 the list and can mutate it underneath you is a documentation issue,
 not a question of type...unless the argument is that the slots should
 be non-configurable, non-writable except by the browser that's also
 holding a ref to it.

That is an ES violation. A non configurable, non writable data
property is not allowed to change its value.

var descr = Object.getOwnPropertyDescription(object, name);
if (!descr.configurable  !decsr.writable  ('value' in descr)) {
  var value = descr.value;
  setInterval(function() {
// Must never change
assert(object[name] === value);
  });
}

Therefore there is no such thing as an immutable live NodeList.

There are ways around this.

1. Use a getter
2. Make it configurable

-- 
erik



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Erik Arvidsson
On Thu, Oct 20, 2011 at 04:37, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-20 13:18, Alex Russell wrote:

 On Thu, Oct 20, 2011 at 12:05 PM, Lachlan Huntlachlan.h...@lachy.id.au
  wrote:

 We need NodeList separate from Array where they are live lists.

 No we don't. The fact that there's someone else who has a handle to
 the list and can mutate it underneath you is a documentation issue,
 not a question of type...unless the argument is that the slots should
 be non-configurable, non-writable except by the browser that's also
 holding a ref to it.

 The author cannot be allowed to directly modify a live list, as such it must
 be an immutable object from the script's perspective.  Otherwise, things
 would get really complicated if this happened:

 var p = document.getElementsByTagName(p);
 p.reverse();

Just define [[Put]] to throw (by only having a getter). Since reverse
is defined using [[Put]] things would work as expected.

-- 
erik



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Erik Arvidsson
On Thu, Oct 20, 2011 at 04:49, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-20 13:35, Sean Hogan wrote:

 I wonder if anyone is relying on querySelectorAll() returning a
 StaticNodeList?

 Only if there are people out there using list.item(n) instead of list[n], or
 people extending the NodeList interface and expecting such methods to be
 available on the result.  Though I suspect the former is very rare, and the
 latter doesn't work in all browsers.

Both are rare but they do happen

http://codesearch.google.com/#search/q=%5CsNodeList%5C.prototype%5C.(%5Cw%2B)%5Cs*=type=cs

What is funny is that code search only found one instance of item
being used directly after querySelectorAll(...). Of course, that
search does not tell the whole story.

http://codesearch.google.com/#SjGak5n5VAM/trunk/parsehtml_util.pyq=querySelectorAll%5C(%5B%5E)%5D%2B%5C)%5C.item%20-file:layoutteststype=csl=24

-- 
erik



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Boris Zbarsky

On 10/20/11 12:02 PM, Erik Arvidsson wrote:

That is an ES violation. A non configurable, non writable data
property is not allowed to change its value.


It's not clear what that means in proxy-land; esp. since it's not clear 
whether proxies can even have non-configurable properties... or did that 
discussion come to a conclusion?


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Erik Arvidsson
On Thu, Oct 20, 2011 at 09:28, Boris Zbarsky bzbar...@mit.edu wrote:
 On 10/20/11 12:02 PM, Erik Arvidsson wrote:

 That is an ES violation. A non configurable, non writable data
 property is not allowed to change its value.

 It's not clear what that means in proxy-land; esp. since it's not clear
 whether proxies can even have non-configurable properties... or did that
 discussion come to a conclusion?

We have a solution to that:

http://wiki.ecmascript.org/doku.php?id=strawman:direct_proxies

-- 
erik



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Jonas Sicking
On Thu, Oct 20, 2011 at 3:46 AM, Alex Russell slightly...@google.com wrote:
 However, it does seem like selectors are here to stay. And as much as
 they have shortcomings, people seem to really like them for querying.

 So with that out of the way, I agree that the CSS working group
 shouldn't be what is holding us back. However we do need a precise
 definition of what the new function does. Is prepending :scope  and
 then parsing as a normal selector always going to give the behavior we
 want? This is actually what I think we got stuck on when the original
 querySelector was designed.

 So let's get into specifics about how things should work. According to
 your proposal of simply prepending a conceptual :scope to each
 selector group, for the following DOM:

 body id=3
  div id=context foo=bar
    div id=1/div
    div class=class id=2/div
    div class=withChildren id=3div class=child id=4/div/div
  /div
 /body

 you'd get the following behavior:

 .findAll(div)  // returns ids 1,2,3,4
 .findAll()      // returns the context node itself. This was
 indicated undesirable

 And, in follow-up mail, we talked extensively about why I didn't
 *really* mean just prepend the string ':scope '.

 I think empty string is a special case that we should treat as return
 an empty list.

Sounds reasonable (sorry to bring this case up again, I just wanted to
be comprehensive, though I failed at that, see below)

 .findAll(body  :scope  div)  // returns nothing

 I suggest we treat :scope occurring after the first term of the
 selector as an error.

So how should it work in the first term?

I.e. what should

.findAll(:scope)
.findAll(div:scope)
.findAll([foo=bar]:scope)
.findAll(:scope div)
.findAll(div:scope div)
.findAll(div:scope #3)

return?

Also, why should :scope appearing in the first term be different from
appearing in any other term?

What is the use case?

Do libraries have anything equivalent today?

 .findAll(#3)  // returns id 3, but not the body node

 Correct. Assuming the query is
 document.find(#context).findAll(#3), which is what I think you
 mean for the root to be in these examples?

Yup.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Jonas Sicking
On Thu, Oct 20, 2011 at 3:50 AM, Alex Russell slightly...@google.com wrote:
 On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sicking jo...@sicking.cc wrote:
 On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell slightly...@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. 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?

 Oh, and as a separate issue. I think .findAll should return a plain
 old JS Array. Not a NodeList or any other type of host object.

 I strongly agree that it should be an Array *type*, but I think just
 returning a plain Array is the wrong resolution to our NodeList
 problem. WebIDL should specify that DOM List types *are* Array types.
 It's insane that we even have a NodeList type which isn't a real array
 at all. Adding a parallel system when we could just fix the one we
 have (and preserve the value of a separate prototype for extension) is
 wonky to me.

 That said, I'd *also* support the ability to have some sort of
 decorator mechanism before return on .find() or a way to re-route the
 prototype of the returned Array.

 +heycam to debate this point.

How would this new Array-type be different from an Array? Would it
mutable (your answer below seems to indicate 'yes')? Would it allow
inserting things that aren't Nodes?

 One of
 the use cases is being able to mutate the returned value. This is
 useful if you're for 

Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Jonas Sicking
On Thu, Oct 20, 2011 at 7:23 AM, Alex Russell slightly...@google.com wrote:
 On Thu, Oct 20, 2011 at 3:14 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 10/20/11 7:18 AM, Alex Russell wrote:

 No we don't. The fact that there's someone else who has a handle to
 the list and can mutate it underneath you

 There is no sane way to mutate the list on the part of the browser if
 someone else is also messing with it, because the someone else can violate
 basic invariants the browser's behavior needs to maintain.

 Right. So you need to vend an apparently-immutable Array, one which
 can only be changed by the browser. I think that could be accomplished
 in terms of Proxies. But it's still an Array type.

 unless the argument is that the slots should
 be non-configurable, non-writable except by the browser that's also
 holding a ref to it.

 Yes.

 Though I don't know what slots you're talking about; the only sane JS
 implementation of live nodelists is as a proxy.  There's no way to get the
 behaviors that browsers have for them otherwise.

 But it can be a Proxy to an *Array*, not to some weird non-Array type.

Let's do the general discussion about how live and non-live NodeLists
should behave in a separate thread.

The immediate question here is how should the returned object from
.findAll behave? Should it be mutable? Should you be able to insert
non-Nodes into it? Should it have all of the functions of
Array.prototype or just some subset? Should it have any additional
functions?

Since .findAll is a new function we have absolutely no constraints as
far as how NodeLists behave, we can simply return something that isn't
a NodeList.

/ Jonas



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Tab Atkins Jr.
On Thu, Oct 20, 2011 at 7:23 AM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 10/20/11 1:08 AM, Tab Atkins Jr. wrote:

 I disagree.  It's extremely useful and natural for .find(:scope +
 div) to match sibling of the context node.

 I really don't think it is.  If you want that, use document.find(:scope +
 div, context).

Why do that, when the previous one is shorter and simpler, and unambiguous?

The whole point is that we *know* the behavior I suggest is well-known
and easy to use, because jQuery (and probably other selector engines?)
does it already.  I know for a fact that I've appreciated that
behavior in my own coding.  It would have been very annoying to me had
I been forced to break my chaining just to select a sibling, when the
exact same style works fine to select a child.  It's intuitive and
useful.

The behavior is useful in jQuery because it lets me evaluate a
selector, do some work to the matched elements, and then just
continue the selector to grab more, regardless of what form the
continuation takes.  Forcing me to think about the continuation's form
(and even worse, completely rearrange the call structure) is just
mean.  ^_^


 Basically, the presence of :scope would turn off *all* the limitations

 That's a _really_ bizarre behavior.  So in this case:

  foo.find(:scope + div, div)

 what all divs in the document would be found?  Or is the oh, ignore the
 reference node except for matching :scope meant to only apply on a
 per-selector basis inside the selector list?  That has its own issues,
 especially with performance (e.g. merging nodesets while preserving DOM
 order).

Per-selector basis; we're not talking about naive string manipulation
here.  Your example would return divs that are descendants or an
adjacent sibling of the scoping element.

I don't really see the performance issues.  If you use + or ~ off of
:scope, you know for a fact that all the nodes come *after* any
selectors that don't have :scope.  If you use the subject indicator or
the reference combinator that's not necessarily true, but those
selectors will be slow already.  Even then, sorting them into DOM
order should be relatively easy:

1. Run the :scope-carrying selectors across the document together,
automatically yielding a dom-ordered list.
2. Run the :scope-absent selectors together, automatically yielding a
dom-ordered list.
3. Find where the scoping element would be inserted in the #1 list,
and insert the entire #2 list there.

There's no further interleaving that could cause trouble.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Tab Atkins Jr.
On Thu, Oct 20, 2011 at 12:09 PM, Jonas Sicking jo...@sicking.cc wrote:
 Let's do the general discussion about how live and non-live NodeLists
 should behave in a separate thread.

Yes, let's.  ^_^


 The immediate question here is how should the returned object from
 .findAll behave? Should it be mutable? Should you be able to insert
 non-Nodes into it? Should it have all of the functions of
 Array.prototype or just some subset? Should it have any additional
 functions?

 Since .findAll is a new function we have absolutely no constraints as
 far as how NodeLists behave, we can simply return something that isn't
 a NodeList.

It should absolutely have all the Array functions.  I know that I want
to be able to slice, append, forEach, map, and reduce the list
returned by .find.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Bjoern Hoehrmann
* Alex Russell wrote:
I strongly agree that it should be an Array *type*, but I think just
returning a plain Array is the wrong resolution to our NodeList
problem. WebIDL should specify that DOM List types *are* Array types.
It's insane that we even have a NodeList type which isn't a real array
at all.

It is quite normal to consider lists and arrays to be different things.
In Perl for instance you can use list operations like `grep` on arrays,
but you cannot use array operations like `push` on lists. For JavaScript
programmers it actually seems common to confuse the two, like with

  var node_list = document.getElementsByTagName('example');
  for (var ix = 0; ix  node_list.length; ++ix)
node_list[ix].parentNode.removeChild(node_list[ix]);

which would remove all the children if node_list was an array like any
other. Pretending node lists are arrays in nomenclature would likely add
to that.
-- 
Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/ 



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Boris Zbarsky

On 10/20/11 4:32 PM, Tab Atkins Jr. wrote:

I don't really see the performance issues.  If you use + or ~ off of
:scope, you know for a fact that all the nodes come *after* any
selectors that don't have :scope.


Yes.


1. Run the :scope-carrying selectors across the document together,
automatically yielding a dom-ordered list.
2. Run the :scope-absent selectors together, automatically yielding a
dom-ordered list.
3. Find where the scoping element would be inserted in the #1 list,
and insert the entire #2 list there.


  foo.find(:scope + div, :scope div)

begs to differ.

So does:

  foo.find(span :scope ~ div, span  :scope div)

(which is not quite as trivial to analyze).

You could try to look at the combinator following the part(s) that have 
:scope, but that can get tricky.


And worse yet, the current :scope proposals allow an arbitrary nodeset 
to be specified as matching :scope, at which point this whole thing is 
out the window.


And yes, if you use a subject indicator then performance goes out the 
window too; you basically have to search the whole DOM.


As long as you're ok with searching the whole DOM any time anything 
funny is happening, of course, there's no other performance issue here. 
 But then I suspect this will be slow to start with


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Tab Atkins Jr.
On Thu, Oct 20, 2011 at 2:04 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 10/20/11 4:32 PM, Tab Atkins Jr. wrote:
 1. Run the :scope-carrying selectors across the document together,
 automatically yielding a dom-ordered list.
 2. Run the :scope-absent selectors together, automatically yielding a
 dom-ordered list.
 3. Find where the scoping element would be inserted in the #1 list,
 and insert the entire #2 list there.

  foo.find(:scope + div, :scope div)

 begs to differ.

Well, that would only cause a problem if there were also a
:scope-absent selector in the list, like:

foo.find(:scope + div, :scope div, span)

If they *all* carry :scope, then you can just run them all over the
whole tree and get the ordered set in the normal fashion.


 So does:

  foo.find(span :scope ~ div, span  :scope div)

 (which is not quite as trivial to analyze).

Same here.

Yeah, it's possible to make it necessary to interleave the
:scope-carrying and :scope-absent sets, if you run the two separately
(perhaps because you can optimize the :scope-absent ones to fail when
the search would escape the subtree).

If you internally modify the :scope-absent selectors to start with
:scope and a descendant combinator (in other words, do the add a
unique id trick that selector engines do in this situation), and then
run it with all the rest, though, that disappears.  You might lose
some possible optimization (based on knowing you only need to search a
subtree), but not necessarily, and you're avoiding a potential
slowdown from having to interleave.


 You could try to look at the combinator following the part(s) that have
 :scope, but that can get tricky.

Yeah, I can see some possibilities, but they're not exhaustive.


 And worse yet, the current :scope proposals allow an arbitrary nodeset to be
 specified as matching :scope, at which point this whole thing is out the
 window.

QSA allows that (or plans to?).  Alex's find() proposal does not.  The
scoping element is solely the 'this' in .find.


 And yes, if you use a subject indicator then performance goes out the window
 too; you basically have to search the whole DOM.

 As long as you're ok with searching the whole DOM any time anything funny is
 happening, of course, there's no other performance issue here.  But then I
 suspect this will be slow to start with

It was good enough for jQuery in the pre-QSA days, and it's still good
enough for jQuery now when it can't use QSA, I don't see why it's not
good enough for the rest of us.  We can do at least as good, and
probably still better.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Lachlan Hunt

On 2011-10-20 22:32, Tab Atkins Jr. wrote:

On Thu, Oct 20, 2011 at 7:23 AM, Boris Zbarskybzbar...@mit.edu  wrote:

On 10/20/11 1:08 AM, Tab Atkins Jr. wrote:

Basically, the presence of :scope would turn off *all* the limitations


That's a _really_ bizarre behavior.  So in this case:

  foo.find(:scope + div, div)

what all divs in the document would be found?  Or is the oh, ignore the
reference node except for matching :scope meant to only apply on a
per-selector basis inside the selector list?  That has its own issues,
especially with performance (e.g. merging nodesets while preserving DOM
order).


Per-selector basis; we're not talking about naive string manipulation
here.  Your example would return divs that are descendants or an
adjacent sibling of the scoping element.


Not necessarily.  It depends what exactly it means for a selector to 
contain :scope for determining whether or not to enable the implied 
:scope behaviour.  Consider:


  foo.find(:not(:scope));

If that is deemed to contain :scope and turn off the prepending of 
scope, making it equivalent to:


  document.querySelectorAll(:not(:scope), foo);

Then it matches every element in the document except the context node.

Otherwise, if it we decide that containing :scope means that it contains 
a :scope selector that is not within a functional notation 
pseudo-element, then it would prepend :scope, equivalent to:


  document.querySelectorAll(:scope :not(:scope), foo)

Then it matches all descendants of the context element.

In the latter case, then it would only ever be possible for matches to 
be found as descendants, siblings or descendants of siblings of the 
context element.


That would even be true in cases like:

  foo.find(section:scope+div, div, ~p span, .x :scopeh1+span)

With the selector pre-processing, that selector becomes

  section:scope+div, :scope div, :scope~p span, .x :scopeh1+span

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



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Tab Atkins Jr.
On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-20 22:32, Tab Atkins Jr. wrote:

 On Thu, Oct 20, 2011 at 7:23 AM, Boris Zbarskybzbar...@mit.edu  wrote:

 On 10/20/11 1:08 AM, Tab Atkins Jr. wrote:

 Basically, the presence of :scope would turn off *all* the limitations

 That's a _really_ bizarre behavior.  So in this case:

  foo.find(:scope + div, div)

 what all divs in the document would be found?  Or is the oh, ignore the
 reference node except for matching :scope meant to only apply on a
 per-selector basis inside the selector list?  That has its own issues,
 especially with performance (e.g. merging nodesets while preserving DOM
 order).

 Per-selector basis; we're not talking about naive string manipulation
 here.  Your example would return divs that are descendants or an
 adjacent sibling of the scoping element.

 Not necessarily.  It depends what exactly it means for a selector to contain
 :scope for determining whether or not to enable the implied :scope
 behaviour.  Consider:

  foo.find(:not(:scope));

 If that is deemed to contain :scope and turn off the prepending of scope,
 making it equivalent to:

  document.querySelectorAll(:not(:scope), foo);

 Then it matches every element in the document except the context node.

This seems perfectly fine, since if you just want all the elements
*underneath* the scoping element, you can instead do the much simpler:

foo.find(*)


 Otherwise, if it we decide that containing :scope means that it contains a
 :scope selector that is not within a functional notation pseudo-element,
 then it would prepend :scope, equivalent to:

  document.querySelectorAll(:scope :not(:scope), foo)

 Then it matches all descendants of the context element.

This prevents us from doing things like :matches(:scope, #foo),
which seems potentially useful.  (Plus, :matches(X) should always be
equivalent to just X, possibly modulo specificity differences.)


 In the latter case, then it would only ever be possible for matches to be
 found as descendants, siblings or descendants of siblings of the context
 element.

 That would even be true in cases like:

  foo.find(section:scope+div, div, ~p span, .x :scopeh1+span)

 With the selector pre-processing, that selector becomes

  section:scope+div, :scope div, :scope~p span, .x :scopeh1+span

Unless you use the reference combinator or the subject indicator, or
something else we come up with in the future that lets us do more
complicated searching.

~TJ



Re: QSA, the problem with :scope, and naming

2011-10-20 Thread Boris Zbarsky

On 10/20/11 5:15 PM, Tab Atkins Jr. wrote:

If they *all* carry :scope, then you can just run them all over the
whole tree and get the ordered set in the normal fashion.


You can just prepend :scope to the ones missing it and run them over the 
whole tree too.


But that means that now you're doing work proportional to the size of 
your whole DOM, not the subtree rooted at the context element, which is 
a pretty big difference.



And worse yet, the current :scope proposals allow an arbitrary nodeset to be
specified as matching :scope, at which point this whole thing is out the
window.


QSA allows that (or plans to?).  Alex's find() proposal does not.  The
scoping element is solely the 'this' in .find.


I was assuming we were discussing find() in preference to the QSA 
extensions.  Maybe I was confused?



It was good enough for jQuery in the pre-QSA days, and it's still good
enough for jQuery now when it can't use QSA, I don't see why it's not
good enough for the rest of us.


jQuery takes some shortcuts we can't take (note the getElementById 
comments elsewhere in this thread).


Maybe it'll be ok.  Maybe not.  I'd rather not paint ourselves into the 
not corner if we can avoid it


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Alex Russell
On Wed, Oct 19, 2011 at 2:26 AM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 10/18/11 8:08 PM, Alex Russell wrote:

 The other excuse is that adding special cases (which is what you're
 asking
 for) slows down all the non-special-case codepaths.  That may be fine for
 _your_ usage of querySelectorAll, where you use it with a particular
 limited
 set of selectors, but it's not obvious that this is always a win.

 Most browsers try to optimize what is common.

 Yes, but what is common for Yehuda may well not be globally common.

Yehuda is representing jQuery. I'll take his opinion as the global
view unless he choses to say he's representing a personal opinion.

 There's also the question of premature optimization.  Again, I'd love to see
 a non-synthetic situation where any of this matters.  That would be a much
 more useful point to reason from than some sort of hypothetical faith-based
 optimization.

The jQuery team did look to see what selector are hottest against
their engine at some point and explicitly optimize short selectors as
a result. The simple forms seem to be the most common.

Regards



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Alex Russell
On Wed, Oct 19, 2011 at 4:39 AM, Ojan Vafai o...@chromium.org wrote:
 Overall, I wholeheartedly support the proposal.
 I don't really see the benefit of allowing starting with a combinator. I
 think it's a rare case that you actually care about the scope element and in
 those cases, using :scope is fine. Instead of element.findAll( div 
 .thinger), you use element.findAll(:scope  div  .thinger). That said, I
 don't object to considering the :scope implied if the selector starts with a
 combinator.

Right, I think the argument for allowing a combinator start is two-fold:

1.) the libraries allow it, so should DOM
2.) we know the thing on the left, it's the implicit scope. Shorter is
better, so allowing the implicitness here is a win on that basis

I have a mild preference for argument #2. Shorter, without loss of
clarity, for common stuff should nearly always win.

 On Tue, Oct 18, 2011 at 6:15 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 10/18/11 7:38 PM, Alex Russell wrote:

 The resolution I think is most natural is to split on ,

 That fails with :any, with the expanded :not syntax, on attr selectors,
 etc.

 You can split on ',' while observing proper paren and quote nesting, but
 that can get pretty complicated.

 Can we define it as a sequence of selectors and be done with it? That way it
 can be defined as using the same parsing as CSS.


 A minor point is how to order the
 items in the returned flattened list are ordered (document order? the
 natural result of concat()?).

 Document order.

 Definitely.

 -Boris







Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Anne van Kesteren
On Wed, 19 Oct 2011 17:22:46 +0900, Alex Russell slightly...@google.com  
wrote:

Yehuda is representing jQuery. I'll take his opinion as the global
view unless he choses to say he's representing a personal opinion.


You misunderstand. Boris is contrasting with CSS. Selectors are used in  
more than just querySelectorAll() and their usage differs wildly.



--
Anne van Kesteren
http://annevankesteren.nl/



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Yehuda Katz
Yehuda Katz
(ph) 718.877.1325


On Wed, Oct 19, 2011 at 1:22 AM, Alex Russell slightly...@google.comwrote:

 On Wed, Oct 19, 2011 at 2:26 AM, Boris Zbarsky bzbar...@mit.edu wrote:
  On 10/18/11 8:08 PM, Alex Russell wrote:
 
  The other excuse is that adding special cases (which is what you're
  asking
  for) slows down all the non-special-case codepaths.  That may be fine
 for
  _your_ usage of querySelectorAll, where you use it with a particular
  limited
  set of selectors, but it's not obvious that this is always a win.
 
  Most browsers try to optimize what is common.
 
  Yes, but what is common for Yehuda may well not be globally common.

 Yehuda is representing jQuery. I'll take his opinion as the global
 view unless he choses to say he's representing a personal opinion.


Right. I'm representing the position of jQuery. Sizzle (John's selector
engine, used by jQuery) chose to optimize certain common selectors after an
analysis of selectors used by jQuery found that a large percentage of all
selectors used were a few simple forms that were amenable to
getElement(s)By* optimizations. I provided a link to the code that
implements this earlier in this thread.


  There's also the question of premature optimization.  Again, I'd love to
 see
  a non-synthetic situation where any of this matters.  That would be a
 much
  more useful point to reason from than some sort of hypothetical
 faith-based
  optimization.

 The jQuery team did look to see what selector are hottest against
 their engine at some point and explicitly optimize short selectors as
 a result. The simple forms seem to be the most common.


Yep.



 Regards




Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Alex Russell
On Wed, Oct 19, 2011 at 9:29 AM, Anne van Kesteren ann...@opera.com wrote:
 On Wed, 19 Oct 2011 17:22:46 +0900, Alex Russell slightly...@google.com
 wrote:

 Yehuda is representing jQuery. I'll take his opinion as the global
 view unless he choses to say he's representing a personal opinion.

 You misunderstand. Boris is contrasting with CSS. Selectors are used in more
 than just querySelectorAll() and their usage differs wildly.

Sure, of course, but suggesting that the optimizations for both need
to be the same is also a strange place to start the discussion from.
The QSA or find() implementation *should* differ to the extent that it
provides developer value and is a real-world bottleneck.



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Sean Hogan

On 19/10/11 2:39 PM, Ojan Vafai wrote:

Overall, I wholeheartedly support the proposal.

I don't really see the benefit of allowing starting with a combinator. 
I think it's a rare case that you actually care about the scope 
element and in those cases, using :scope is fine. Instead of 
element.findAll( div  .thinger), you use element.findAll(:scope  
div  .thinger). That said, I don't object to considering the :scope 
implied if the selector starts with a combinator.




I can think of two reasons one might ponder allowing :scope to be explicit.

1. so that the selector string can be a valid CSS selector string. 
(:scopediv.thinger instead of div.thinger). But if this is 
important then :scope should always be explicit, in which case we can 
just use querySelectorAll().


2. to allow break-out behavior. e.g.

div.findAll(body div span); // finds nothing
div.findAll(body div:scope span); // finds span's that are descendants 
of div


In this scenario, the :scope pseudo allows ancestors of div to be 
matched against. (No-one would use body in this context, but it is easy 
to imagine them using a .class selector which matches an ancestor of div.)


But if you want break-out behavior you might not know which part of the 
selector to put the :scope pseudo on. Could it be:

body div:scope span
body *:scope div span
body div *:scope span

So for break-out behavior just use querySelectorAll().

I'm pretty sure previous discussions (before this thread) have covered 
this more thoroughly, and shown that it has to be all or nothing with 
the :scope pseudo-attribute. That is, either

a) :scope MUST be explicit, in which case just use querySelectorAll()
b) :scope MUST be implied at the start of every selector chain.

Sean



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Lachlan Hunt

On 2011-10-19 01:58, Tab Atkins Jr. wrote:

Based on discussion on the mailing list,style scoped  will be
changing to the latter behavior as well, with the ability to invoke
the former behavior in the rare circumstances when you explicitly want
it.


Despite some similarities in appearance, the proposed changes to style 
scoped will still use selectors differently from that proposed here for 
a new findAll() method.


1. Syntax

In style scoped, selectors still can't begin with a combinator, but in 
the proposed API, they can.


The @global at-rule was proposed to


2. Matching the Context Element

In scoped stylesheets, the context element itself can be the subject of 
a selector. But the proposed API will never return the element itself in 
the result.


div.findAll(div) // Does not match the element itself

(same as querySelectorAll() in this case)

div
  style scoped
div { ... } /* Matches the context element */
  /style
/div


3. The Subject of Selectors

In scoped stylesheets, the potential matches of a selector will only 
include:

* The context element itself
* Descendants of the context element

In the proposed API, the potential matches will include:
* Descendants of the context element
* Siblings of the context element

In the existing API, the potential matches include:
* Descendants of the context element only


div.findAll(+p) // Matches sibling p elements

div.querySelectorAll(:scope+p) // Matches nothing
document.querySelectorAll(:scope+p, div) // Matches sibling p elements

div
  style scoped
:scope+p { ... } /* Matches nothing */
  /style
div
p.../p

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



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Lachlan Hunt

On 2011-10-18 18:42, Alex Russell wrote:

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.


I know the names suck.  The names we ended up with certainly weren't the 
first choice of names we were going for, but sadly ended up with after a 
long drawn out naming debate and a misguided consensus poll to override 
what should have been an editorial decision.  So, if we do introduce new 
methods, personally I'd be happy to use sensible names for any them, if 
the rest of the group will allow it this time.



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.


The current design is capable of handling many more use cases than the 
single use case that you are trying to optimise for here.



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);
}


This is an incomplete way of dealing with the problem, as it doesn't 
correctly handle comma separated lists of selectors, so the parsing 
problem cannot be as trivial as prepending :scope .  It would also 
give a strange result if the author passed an empty string


  findAll();

  :scope  +  = :scope = meaning to return itself.

In another email, you wrote:

The resolution I think is most natural is to split on , and assume
that all selectors in the list are :scope prefixed and that.


Simple string processing to split on , is also ineffective as it 
doesn't correctly deal with commas within functional notation 
pseudo-classes, attribute selectors, etc.


I have attempted to address this problem before and the algorithm for 
parsing a *scoped selector string* (basically what you're calling a 
rootedSelector) existed in an old draft [1].


That draft also allowed the flexibility of including an explicit :scope 
pseudo-class in the selector, which allows for conditional expressions 
to be built into the selector itself that can be used to check the state 
of the scope element or any of its ancestors.


(But that draft isn't perfect.  It has a few known bugs in the 
definition, including one that would also make it return the context 
node itself under certain circumstances where an explicit :scope 
selector is used.)


[1] 
http://dev.w3.org/cvsweb/~checkout~/2006/webapi/selectors-api2/Overview.html?rev=1.29;content-type=text%2Fhtml#processing-selectors


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



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Alex Russell
On Wed, Oct 19, 2011 at 1:54 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 On 2011-10-18 18:42, Alex Russell wrote:

 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.

 I know the names suck.  The names we ended up with certainly weren't the
 first choice of names we were going for, but sadly ended up with after a
 long drawn out naming debate and a misguided consensus poll to override what
 should have been an editorial decision.  So, if we do introduce new methods,
 personally I'd be happy to use sensible names for any them, if the rest of
 the group will allow it this time.

It should *still* be an editorial decision. Shorter is better. This is
well-trod ground. We have plenty of evidence for what JS devs really
want. Lets get on with it.

 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.

 The current design is capable of handling many more use cases than the
 single use case that you are trying to optimise for here.

That's OK. I'm not stoning the current design. See below. I'm
suggesting we build on it and provide the API people are making heavy
use of today. This cow path deserves not just paving, but
streetlights, wide shoulders, and a bike lane.

 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);
    }

 This is an incomplete way of dealing with the problem, as it doesn't
 correctly handle comma separated lists of selectors, so the parsing problem
 cannot be as trivial as prepending :scope .  It would also give a strange
 result if the author passed an empty string

  findAll();

  :scope  +  = :scope = meaning to return itself.

Yes, yes. Pseudo-code. I snipped other code I posted to not handle
obvious corner cases to prevent posting eye-watering walls of code as
well. Happy to draft a longer/more-complete straw-man, but nobody's
*actually* going to implement it this way in any case. As an aside,
it's shocking how nit-picky and anti-collaborative this group is.
*sigh*

 In another email, you wrote:

 The resolution I think is most natural is to split on , and assume
 that all selectors in the list are :scope prefixed and that.

 Simple string processing to split on , is also ineffective as it doesn't
 correctly deal with commas within functional notation pseudo-classes,
 attribute selectors, etc.

See, again, subsequent follow-ups.

 I have attempted to address this problem before and the algorithm for
 parsing a *scoped selector string* (basically what you're calling a
 rootedSelector) existed in an old draft [1].

 That draft also allowed the flexibility of including an explicit :scope
 pseudo-class in the selector, which allows for conditional expressions to be
 built into the selector itself that can be used to check the state of the
 scope element or any of its ancestors.

We could accomodate that by looking at the passed selector and trying
to determine if it includes a :scope term. If so, avoid prefixing.
That'd allow this sort of flexibility for folks who want to write
things out long-hand or target the scope root in the selector,
possibly returning itself. I''d also support a resolution for this
sort of power-tool that forces people to use document.qsa(...,
scopeEl) to get at that sort of thing.

 (But that draft isn't perfect.  It has a few known bugs in the definition,
 including one that would also make it return the context node itself under
 certain circumstances where an explicit :scope selector is used.)

 [1]
 http://dev.w3.org/cvsweb/~checkout~/2006/webapi/selectors-api2/Overview.html?rev=1.29;content-type=text%2Fhtml#processing-selectors



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Boris Zbarsky

On 10/19/11 4:22 AM, Alex Russell wrote:

Yehuda is representing jQuery. I'll take his opinion as the global
view unless he choses to say he's representing a personal opinion.


Global jQuery view, yes?  I stand by a slightly statement that what is 
common and needs to be fast for Yehuda may not be common and needing to 
be fast in general.


In particular, lots of jQuery selector usage is not in fact 
performance-sensitive.  Some obviously is.  Again, I'd love to see data 
on the cases where performance matters, both when jQuery is involved and 
when it's not.


I should note that the larger and more complicated a web app the less 
likely it is to use jQuery from what I've seen


I'm absolutely sure that simple selectors dominate complicated ones in 
all contexts, but again I'd really like to have data on what _sort_ of 
simple selectors really need optimizing.



The jQuery team did look to see what selector are hottest against
their engine


Yes.  See above.

-Boris



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Boris Zbarsky

On 10/19/11 4:29 AM, Anne van Kesteren wrote:

On Wed, 19 Oct 2011 17:22:46 +0900, Alex Russell
slightly...@google.com wrote:

Yehuda is representing jQuery. I'll take his opinion as the global
view unless he choses to say he's representing a personal opinion.


You misunderstand. Boris is contrasting with CSS.


No, I'm talking purely about querySelector.  The fact that at least 
Gecko and WebKit implement querySelector in a braindead way because that 
lets them reuse their selector matching code is a somewhat separate 
kettle of fish.


What we're discussing her, in particular, are optimizations that make 
use of the differences in use case between CSS selector matching (match 
one node to a bazillion selectors) and querySelector (match one 
selectors to possibly a bazillion nodes).  There are ways to optimize 
the latter by examining the structure of the selector and making use of 
existing cached information in the browser that make no sense in the CSS 
context and would be implemented as a preprocessing pass before falling 
back on actual selector matching.  WebKit does a few of these, of 
varying utility.  I've considered doing some in Gecko, but again want to 
have hard data that they're actually needed before adding complexity.


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Boris Zbarsky

On 10/19/11 11:17 AM, Boris Zbarsky wrote:

4) Mapping Sizzle(#id) with document a context to
getElementById(id). This isn't a valid optimization for querySelector
because there can be multiple elements with the same id;


And just as a note, since someone asked me off-list how this can 
possibly be true...  Given this markup:


div id=x
  div id=y/div
  div id=y/div
/div

calling

  jQuery.find(#y)

returns an array with one element in it while calling

  jQuery.find(#y, document.getElementById(x))

returns an array with two elements.  I have no idea whether this is 
purposeful behavior or just a bug in Sizzle brought on by the 
optimization listed above.


-Boris



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Lachlan Hunt

On 2011-10-19 16:08, Alex Russell wrote:

On Wed, Oct 19, 2011 at 1:54 PM, Lachlan Huntlachlan.h...@lachy.id.au  wrote:

I have attempted to address this problem before and the algorithm for
parsing a *scoped selector string* (basically what you're calling a
rootedSelector) existed in an old draft [1].

That draft also allowed the flexibility of including an explicit :scope
pseudo-class in the selector, which allows for conditional expressions to be
built into the selector itself that can be used to check the state of the
scope element or any of its ancestors.


We could accomodate that by looking at the passed selector and trying
to determine if it includes a :scope term. If so, avoid prefixing.


Yes, that's exactly what the draft specified.


That'd allow this sort of flexibility for folks who want to write
things out long-hand or target the scope root in the selector,
possibly returning itself.


I don't see a use case for wanting the proposed method to be able to 
return the element itself.  The case where it's useful for elements 
matching :scope to be the subject of a selector is where you're trying 
to filter a list of elements.


e.g.
  document.querySelectorAll(.foo:scope, list);
  // Returns all elements from list that match.

But this wouldn't make sense

  el.find(.foo:scope) // Return itself if it matches.

That result seems effectively like a less efficient boolean check that 
is already handled by el.matchesSelector(.foo).



I''d also support a resolution for this sort of power-tool that
forces people to use document.qsa(...,scopeEl) to get at that sort
of thing.


If there was no special handling to check for an explicit :scope, that 
would mean that any selector that does include :scope explicitly would 
not match anything at all.


e.g. el.findAll(:scopep);

That would be equivalent to:

  document.querySelectorAll(:scope :scopep, el);

Which won't match anything.

That might keep things simpler from an implementation perspective and 
doesn't sacrifice any functionality being requested.


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



Re: QSA, the problem with :scope, and naming

2011-10-19 Thread Lachlan Hunt

On 2011-10-18 18:42, Alex Russell wrote:

   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);
}


What exactly does it mean to have a rootedSelector applied to the 
Document object?  As I understand it, the scoping problem explained only 
seems to apply to running the query on elements, whereas the existing 
document.qsa already behaves as expected by authors.  It doesn't seem to 
make sense to try and prepend :scope to selectors in that case.


e.g. document.find(html) shouldn't be equivalent to 
document.querySelector(:scope html);


So, either we introduce the new method only for elements, or we use a 
similarly named method on document for a similar, but slightly different 
purpose.


A previous use case discussed on this list is the ability to take a 
collection of elements, and execute the same selector on all all of 
them, as if iterating the list, collecting the results and returning a 
single merged collection.


The current API handles this use case with document.querySelectorAll, 
explicitly specifying :scope and passing a collection of refNodes.


e.g.
var list = ...; // Elements (Array, NodeList or indexed object)

// Find the sibling p elements of all elements in the list
document.querySelectorAll(:scope+p, list);

Thus, if we do introduce the proposed method, should it behave 
similarly, but with the implied rather than explicit :scope?


e.g.
document.findAll(+p, list);

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



  1   2   >