Re: [selectors-api] Summary of Feature Requests for v2

2009-09-28 Thread Lachlan Hunt

Garrett Smith wrote:

On Thu, Sep 24, 2009 at 1:28 AM, Lachlan Huntlachlan.h...@lachy.id.au  wrote:

And overload the querySelector() and querySelectorAll() methods to also
accept a Selector object as the selector parameter.

createSelector would allow the browser to parse and compile the selector and
store it, much like createExpression does in DOM 3 XPath.  If a
contextElement is provided, then that element is defined as the Scope
Element that matches the :scope pseudo-class.  If impliedScope is set to
false, the the browser treats it as an ordinary selector.  If it's set to
true, then it's treated as an implicitly scoped selector that needs to be
pre-parsed into a valid selector and imply the presence of :scope (like
em,strong).


Why not use the selector text for the scope?


I already did that 2 days ago when I dropped createSelector() and found 
a way for it to work with the descendant selector.


The spec now defines that if the selector starts with either a 
combinator (, + or ~), or an exclamation point, then it's a scoped 
selector, and the processing requirements are adjusted accordingly.  I 
also attempted to define the processing requirements to interpret a 
selector like em as being equivalent to :referenceem.


I also defined the :reference pseudo class in the spec (formerly known 
as :scope in previous discussions) to match the contextual reference 
elements.


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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-28 Thread Garrett Smith
On Mon, Sep 28, 2009 at 2:31 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 Garrett Smith wrote:

 On Thu, Sep 24, 2009 at 1:28 AM, Lachlan Huntlachlan.h...@lachy.id.au
  wrote:

 And overload the querySelector() and querySelectorAll() methods to also
 accept a Selector object as the selector parameter.

 createSelector would allow the browser to parse and compile the selector
 and
 store it, much like createExpression does in DOM 3 XPath.  If a
 contextElement is provided, then that element is defined as the Scope
 Element that matches the :scope pseudo-class.  If impliedScope is set to
 false, the the browser treats it as an ordinary selector.  If it's set to
 true, then it's treated as an implicitly scoped selector that needs to be
 pre-parsed into a valid selector and imply the presence of :scope (like
 em,strong).

 Why not use the selector text for the scope?

 I already did that 2 days ago when I dropped createSelector() and found a
 way for it to work with the descendant selector.

 The spec now defines that if the selector starts with either a combinator
 (, + or ~), or an exclamation point, then it's a scoped selector, and the
 processing requirements are adjusted accordingly.  I also attempted to
 define the processing requirements to interpret a selector like em as
 being equivalent to :referenceem.

 I also defined the :reference pseudo class in the spec (formerly known as
 :scope in previous discussions) to match the contextual reference elements.

http://dev.w3.org/2006/webapi/selectors-api2/#scoped-selector-string

The proposal for detecting support is then try catch? As in:

  IS_SCOPED_SELECTOR = false;
  try {
document.querySelector(!a);
IS_SCOPED_SELECTOR = true;
  } catch(ex) {}

?

I don't see a form of a createSelector method there.

Garrett



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-25 Thread Boris Zbarsky

On 9/25/09 1:35 AM, Garrett Smith wrote:

No, you did not say it is slow. I'm saying that your laptop is
probably a lot more powerful than a mobile device with a browser, such
as Blackberry9000. Do you agree with that?


Sure.  It's a pretty self-evidently true claim.


that said, note that on a mobile device with 128 MB of RAM the RAM is a lot
more likely to be a problem than the CPU in some ways.  Running out of
memory is strictly worse than being a little bit slower.  So a lookup table
may be more of a loss than a win, depending.


An internal cache for matchesSelector (a lookup table) would be an
implementation detail, wouldn't it?


Sure.  Sean was just saying there probably is one already; I was saying 
there isn't, along with a brief explanation of why.  You apparently 
objected to part of this explanation, but at this point I'm not quite 
sure what your objection was, exactly.  I made two statements:


1)  There seem to be no current parsed-selector caches in Webkit and
Gecko's querySelector implementation.
2)  On my particular hardware, parsing a particular selector in Gecko
takes approximately 5.5us.

Any conclusions to be drawn for other rendering engines, other 
selectors, or other hardware setups should be qualified appropriately 
(for example, Gecko on an N810 would probably end up closer to 500us for 
that same operation, if I recall the typical performance ratios correctly).



The idea for QuerySelector.create is the result would be an object
that the program could hang on to. It would not be recreated and
garbage collected each time.


Yes, I understand the proposal.

-Boris



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Jonas Sicking
On Wed, Sep 23, 2009 at 9:57 PM, Maciej Stachowiak m...@apple.com wrote:

 On Sep 23, 2009, at 5:26 PM, Jonas Sicking wrote:

 On Wed, Sep 23, 2009 at 4:51 AM, Lachlan Hunt lachlan.h...@lachy.id.au
 wrote:

 *Scoped Queries*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5860

 This has been discussed extensively in the past.  Basically, the idea is
 that the selector would be evaluated in the scope of the element, in a
 way
 more compatible with how libraries like JQuery work.  This slightly
 different from the :scope pseudo-class proposal, see bug for details.

 Note that what makes the strong, em selector (which apparently
 some libraries support) hard to support spec-wise is that that is not
 in fact valid CSS syntax. It's certainly possible to define behavior
 for it, it's pretty clear to me how it's intended to work, but it
 would mean specifying our own syntax.

 However if supporting commaseparated queries is critical for libraries
 then I see no other choise. We'll one way or another have to specify
 our own syntax, though it can be heavily based on the productions in
 the Selector spec.

 I think we can define an algorithm for turning an implicitly scoped
 pseudo-selector like strong, em into a proper selector using :scope --
 in this case :scopestrong, :scopeem. We could either have an API entry
 point that takes a scoped pseudo-selector, defined as transforming to a real
 selector plus establishing a scope node, or just present the algorithm as an
 option for libraries that want to expose pseudo-selector syntax.

Indeed, it's certainly possible. I'd like to find out if we can get
away with not doing that though. I'm curious to get feedback on how
far just having a :scope pseudo-class gets us.

/ Jonas



RE: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Mike Wilson
Yes, the base for event delegation is certainly something
like that. I just wanted to make clear that the main reason
for adding this functionality (IMO) is event delegation.
I'll let event delegation library creators chime in on the
details on what is needed for making really efficient
behavioural/delegation implementations, and judge the merits
of various optimizations. There has f ex already been mention
of caching parsed selectors.

Best regards
Mike

Lachlan Hunt wrote:
 Mike Wilson wrote:
  My first priority would be Matches Selector, and see to that
  it fulfills the needs for event delegation.
 
 Is there any special functionality that would be needed to 
 achieve this? 
   If I understand correctly, event delegation just needs to 
 be able to 
 check whether the event target element matches a given 
 selector.  So it 
 would be something like:
 
 if (evt.target.matchesSelector(.fooinput.bar)) {
 ...
 }
 
 -- 
 Lachlan Hunt - Opera Software
 http://lachy.id.au/
 http://www.opera.com/
 




Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Lachlan Hunt

Sean Hogan wrote:

I think a couple of those features are pretty low priority:

- I don't see the point of collective queries on NodeLists.
Are there any references for the proposal?
Otherwise I can't think of any useful queries that can't already be
achieved with a single querySelectorAll().


It was discussed a couple of days ago in IRC.  It's based on the 
functionality provided and needed by javascript libraries.


Garrett Smith wrote:

Lachlan Hunt wrote:

div2.matchesSelector(:scope~div, div1);


The matching seems backwards. Should be on the matcher, instead of the
element? I don't see the role of the element being something that does
matching. The matching should be something left to some sort of a
Matcher.

A function to get an actual Selector object would allow the program to
creating a cached matcher.

var selector = QuerySelector.create(div.panel);
var isPanel = selector.matches(event.target);


That's an interesting concept.  We could perhaps define something like this:

Interface DocumentSelector {
  Selector createSelector(DOMString selector, [Element scopeElement, 
[boolean impliedScope]]);

}
Interface Selector {
  boolean matches(Node element);
}

And overload the querySelector() and querySelectorAll() methods to also 
accept a Selector object as the selector parameter.


createSelector would allow the browser to parse and compile the selector 
and store it, much like createExpression does in DOM 3 XPath.  If a 
contextElement is provided, then that element is defined as the Scope 
Element that matches the :scope pseudo-class.  If impliedScope is set to 
false, the the browser treats it as an ordinary selector.  If it's set 
to true, then it's treated as an implicitly scoped selector that needs 
to be pre-parsed into a valid selector and imply the presence of :scope 
(like em, strong).


A possible extension to consider would be to also allow scopeElement to 
be specified as an array or NodeList of elements, such that :scope will 
match any of the elements in the elements in the array, instead of 
limiting it to just one.


Scripts can then do this:

var selector = document.createSelector(em,strong, elm, true);

Or this:

var selector = document.createSelector(h1+:scopea, [elm1, elm2, 
elm3], false);


And then pass that selector to querySelector*() like

document.querySelectorAll(selector)

And matchesSelector is handled like this:

document.createSelector(input[type=checkbox]).matches(evt.target);

John Resig wrote:

Filtering NodeLists/StaticNodeLists, Queries on NodeLists/StaticNodeLists:
Neither of these are useful, as is, to libraries. What is actually useful is
the ability to run these against an array (or array-like collection) of DOM
nodes.


I believe this would be handled using the Array.filter() method, with a 
callback that checks if the selector matches the element, as Jonas 
pointed out:



filteredArray = myArrayOfNodes.filter(function(node) { return
node.matchesSelector(someselector); });


(That could also work with the above Selector.matches() proposal)


If I can do:
document.querySelectorAll.call([document.getElementById(node1),
document.getElementById(node2)], div  span); then yes, this proposal is
useful. Rarely do libraries store raw NodeLists (they need to be converted
into an array or array-like collection first).


So this means that defining the API directly on NodeLists wouldn't 
handle the use cases dealing with arrays of elements, so the 
NodeList.querySelectorAll() idea is out.


Perhaps on the Selector interface described above, we could also define:

Interface Selector {
  boolean  matches(Node element);
  NodeList querySelector(DOMArray nodes)
  NodeList querySelectorAll(DOMArray nodes)
}

(where nodes either accepts an Array or a NodeList containing a 
collection of Document, Element or DocumentFragment nodes)


Then when these methods are run, they iteratively run querySelector() or 
querySelectorAll() on each of the nodes in the collection, using the 
selector and then return the result as a NodeList containing the union 
of unique elemenets in document order.


e.g.
var selector = document.createSelector(input);
selector.querySelectorAll([elm1, elm2, elm3]);

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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Garrett Smith
On Thu, Sep 24, 2009 at 12:02 AM, Mike Wilson mike...@hotmail.com wrote:
 Yes, the base for event delegation is certainly something
 like that. I just wanted to make clear that the main reason
 for adding this functionality (IMO) is event delegation.
 I'll let event delegation library creators chime in on the
 details on what is needed for making really efficient
 behavioural/delegation implementations, and judge the merits
 of various optimizations. There has f ex already been mention
 of caching parsed selectors.


The benefit to that is that the selector text is parsed once, so
something like:-

document.onmouseover = function(ev) {
  if(ev.target.matchesSelector(.infotip)) { /*...*/ }
};

could probably be made more efficient as:-

var selector = QuerySelector.create(.infotip);
document.onmouseover = function(ev) {
  if(selector.matches(ev.target)) { /*...*/ }
};

The type of context where a QuerySelector object would be useful are
described above. That could be abstracted to a factory pattern that
uses selector to match nodes in a delegated event and lazily construct
a wrapper.

QuerySelector could be extended to have properties:
  readonly attribute boolean valid
  StaticNodeList match(in HTMLElement contextNode)

Garrett



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Lachlan Hunt

Lachlan Hunt wrote:

Sean Hogan wrote:

I think a couple of those features are pretty low priority:

- I don't see the point of collective queries on NodeLists.
Are there any references for the proposal?
Otherwise I can't think of any useful queries that can't already be
achieved with a single querySelectorAll().


It was discussed a couple of days ago in IRC. It's based on the
functionality provided and needed by javascript libraries.


Sorry, I forgot to provide the link.  The relevant discussion is spread 
out quite a bit throughout this log, beginning here.


http://krijnhoetmer.nl/irc-logs/whatwg/20090922#l-

I've highlighted the relevant parts.

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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Lachlan Hunt

Garrett Smith wrote:

QuerySelector could be extended to have properties:
   readonly attribute boolean valid
   StaticNodeList match(in HTMLElement contextNode)


What's the valid property for?  It seems redundant.  If the selector 
isn't valid, then the factory method should throw an error when it tries 
to create it.  Otherwise, it will be valid.


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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sean Hogan

Garrett Smith wrote:

On Thu, Sep 24, 2009 at 12:02 AM, Mike Wilson mike...@hotmail.com wrote:
  

Yes, the base for event delegation is certainly something
like that. I just wanted to make clear that the main reason
for adding this functionality (IMO) is event delegation.
I'll let event delegation library creators chime in on the
details on what is needed for making really efficient
behavioural/delegation implementations, and judge the merits
of various optimizations. There has f ex already been mention
of caching parsed selectors.




The benefit to that is that the selector text is parsed once, so
something like:-

document.onmouseover = function(ev) {
  if(ev.target.matchesSelector(.infotip)) { /*...*/ }
};

could probably be made more efficient as:-

var selector = QuerySelector.create(.infotip);
document.onmouseover = function(ev) {
  if(selector.matches(ev.target)) { /*...*/ }
};

  


I would be surprised if an implementation didn't create an internal 
lookup table keyed off the selector text.





Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sean Hogan

Lachlan Hunt wrote:

Lachlan Hunt wrote:

Sean Hogan wrote:

I think a couple of those features are pretty low priority:

- I don't see the point of collective queries on NodeLists.
Are there any references for the proposal?
Otherwise I can't think of any useful queries that can't already be
achieved with a single querySelectorAll().


It was discussed a couple of days ago in IRC. It's based on the
functionality provided and needed by javascript libraries.


Sorry, I forgot to provide the link.  The relevant discussion is 
spread out quite a bit throughout this log, beginning here.


http://krijnhoetmer.nl/irc-logs/whatwg/20090922#l-

I've highlighted the relevant parts.



I couldn't see where it was needed, only that it was possible in jQuery.
I still can't think of any NodeLists that this could usefully be applied 
to that couldn't be achieved with a single querySelectorAll(). At least 
until we can create arbitrary NodeLists.





Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Lachlan Hunt

John Resig wrote:

Filtering NodeLists/StaticNodeLists, Queries on NodeLists/StaticNodeLists:

Neither of these are useful, as is, to libraries.


I believe this would be handled using the Array.filter() method, with a
callback that checks if the selector matches the element, as Jonas pointed
out:

  filteredArray = myArrayOfNodes.filter(function(node) { return

node.matchesSelector(someselector); });


(That could also work with the above Selector.matches() proposal)



Array.filter() will meet the need of filtering
NodeLists/StaticNodeLists/Arrays of Elements - sure - but it won't meet the
need of NodeList.querySelectorAll (especially if that works with an
array-like collection of DOM elements).


Right, but I'm dealing with that as an entirely separate issue, which I 
disucssed later on in that email.


Basic filtering of nodelists is bug 5864, which I've resolved WONTFIX 
for now because the functionality doesn't seem too desirable or beneficial.


http://www.w3.org/Bugs/Public/show_bug.cgi?id=5864

The issue you're discussing is bug 7707, which is still open.

http://www.w3.org/Bugs/Public/show_bug.cgi?id=7707


The problem is that when you have multiple collections of DOM elements and
you wish to reduce them to a single collection it ends up being a very
expensive task. The steps are as follows:
   - The collections must be merged together into a single array of DOM
elements.
   - The elements must be sorted to be in document order.
   - Duplicate elements must be removed from the collection.


So the question is, at which point in the chain do you want to address 
this issue?  The options are:


A) Have specific selectors API feauture that allowed executing a
   selector query on a whole collection of elements that returns a
   single, sorted collection of unique elements.

B) A more generic API for being able to easily merge and sort
   NodeLists/Arrays of elements.

Option A saves the step of having to run the queries on each individual 
element manually and just returns a merged and sorted collection of 
unique elements.  But it's limited to running selector queries, rather 
than any other getElementsBy*() method to obtain the results.


Option B is more generic in that it could potentially merge and sort any 
set of NodeLists, and those NodeLists could be obtained by any method, 
but would still require running the queries on each element individually 
to obtain the the lists that then need to be merged.


Both options present an issue with sorting, since they could result in 
lists that contain both connected and disconnected elements, and the 
sort order for connected elements in relation to disconnected elements 
would need to be defined.


Option B seems potentially harder to define and possibly implement, 
especially if you want to be able to sort merge NodeList objects with 
Array objects.  Since Arrays aren't limited to just containing DOM 
Nodes, the issue of what to do with other types objects and how to sort 
them along with the Nodes is complicated.



It would be great to have a separate, standalone, function that handles
these merge/sort/unique operations for collections of DOM elements
(especially if they're disconnected from the document!).


The proposal from my previous mail falls into Option A.  Would it 
address this issue adequately?  Specifically, defining 
document.createSelector() and a Selector interface that allows running a 
query like this:


var elements = [...] // Some Array (or NodeList) of Elements
var selector = document.createSelector(em, strong);
var list = selector.querySelectorAll(elements);

This is equivalent to iterating over the elements array, running 
elements[i].querySelectorAll(em, strong) on each, and then 
merging/sorting all of the results into a single collection.



If there was a merge/sort/unique method it would drop the need for having a
NodeList/Array.querySelectorAll.


Whether we should go for the extra complexity required for this really 
depends on the use case you're trying to address.  Do you just need to 
merge NodeLists that are all obtained via querySelector methods, or do 
you need to merge any random NodeLists or Arrays that could be obtained 
via querySelector*() or getElementsBy*(), or wherever else.


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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Lachlan Hunt

Sean Hogan wrote:

http://krijnhoetmer.nl/irc-logs/whatwg/20090922#l-


I couldn't see where it was needed, only that it was possible in jQuery.
I still can't think of any NodeLists that this could usefully be applied
to that couldn't be achieved with a single querySelectorAll(). At least
until we can create arbitrary NodeLists.


It would simplify the issues that John described in his last e-mail, but 
the exact use cases aren't entirely clear which is making finding and 
determining the most appropriate solution difficult.  I'm hoping John 
can answer this question.


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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread John Resig

  So the question is, at which point in the chain do you want to address
 this issue?  The options are:

 A) Have specific selectors API feauture that allowed executing a
   selector query on a whole collection of elements that returns a
   single, sorted collection of unique elements.

 B) A more generic API for being able to easily merge and sort
   NodeLists/Arrays of elements.

 Option A saves the step of having to run the queries on each individual
 element manually and just returns a merged and sorted collection of unique
 elements.  But it's limited to running selector queries, rather than any
 other getElementsBy*() method to obtain the results.

 Option B is more generic in that it could potentially merge and sort any
 set of NodeLists, and those NodeLists could be obtained by any method, but
 would still require running the queries on each element individually to
 obtain the the lists that then need to be merged.

 Both options present an issue with sorting, since they could result in
 lists that contain both connected and disconnected elements, and the sort
 order for connected elements in relation to disconnected elements would need
 to be defined.

 Option B seems potentially harder to define and possibly implement,
 especially if you want to be able to sort merge NodeList objects with Array
 objects.  Since Arrays aren't limited to just containing DOM Nodes, the
 issue of what to do with other types objects and how to sort them along with
 the Nodes is complicated.


B is a subset of A. You need B in order to implement A. Ideally we could
have both options (A for the obvious cases where you already have a NodeList
and which to do another query against the results, which would be faster
than manually going through the results and doing B).

Whereas B is needed in its own right (as I outlined before).


 It would be great to have a separate, standalone, function that handles
 these merge/sort/unique operations for collections of DOM elements
 (especially if they're disconnected from the document!).


 The proposal from my previous mail falls into Option A.  Would it address
 this issue adequately?  Specifically, defining document.createSelector() and
 a Selector interface that allows running a query like this:

 var elements = [...] // Some Array (or NodeList) of Elements
 var selector = document.createSelector(em, strong);
 var list = selector.querySelectorAll(elements);

 This is equivalent to iterating over the elements array, running
 elements[i].querySelectorAll(em, strong) on each, and then merging/sorting
 all of the results into a single collection.


Not a huge fan of that - it seems really backwards. Another alternative
would be to implement the merge/sort/unique method and have it return a
NodeList (which would, then, have qSA).

For example:
document.createNodeList([ ... some elements ... ]).querySelectorAll(em,
strong);

createNodeList would create a NodeList holding the DOM nodes in document
order (with duplicates removed). Since it's a proper NodeList we could then
use qSA to find the elements that we want.

If this is how it's implemented it actually becomes really useful to have
the NodeList-based element filtering.

document.createNodeList([ ... some elements ... ]).filterSelector(em,
strong)

(Since this would be much faster than using Array.filter or some other
method.)


  If there was a merge/sort/unique method it would drop the need for having
 a
 NodeList/Array.querySelectorAll.


 Whether we should go for the extra complexity required for this really
 depends on the use case you're trying to address.  Do you just need to merge
 NodeLists that are all obtained via querySelector methods, or do you need to
 merge any random NodeLists or Arrays that could be obtained via
 querySelector*() or getElementsBy*(), or wherever else.


The latter, absolutely. These results could be coming from anywhere - and
could even be coming from non-query methods (like the aforementioned
.parents() method in jQuery which does its own ancestor traversal).

--John


Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Lachlan Hunt

John Resig wrote:

  So the question is, at which point in the chain do you want to address
this issue?  The options are:

A) Have specific selectors API feauture that allowed executing a
   selector query on a whole collection of elements that returns a
   single, sorted collection of unique elements.

B) A more generic API for being able to easily merge and sort
   NodeLists/Arrays of elements.

Option A saves the step of having to run the queries on each individual
element manually and just returns a merged and sorted collection of unique
elements.  But it's limited to running selector queries, rather than any
other getElementsBy*() method to obtain the results.

Option B is more generic in that it could potentially merge and sort any
set of NodeLists, and those NodeLists could be obtained by any method, but
would still require running the queries on each element individually to
obtain the the lists that then need to be merged.


B is a subset of A. You need B in order to implement A.


Not quite.  It depends what's being done and which steps need to be 
performed and how.  AIUI, there are 3 major steps involved here.


1. Obtain a collection of Elements. This could be in one or more
   Arrays and/or NodeLists, depending on th.
2. Iteratively execute a selector query on all elements in the
   collection, saving the results from each.
3. Merge and sort all elements into a single NodeList, removing
   duplicates.

In order to understand which of those steps need to be optimised by the 
browser with new APIs, it would help if you could explain some typical 
tasks, or use cases, that would need to perform any or all of those steps.


In particular, what type of task would lead to there being more than one 
Array and/or NodeList to be used as input to step 2?


What type of task would require executing the same selector query over a 
whole collection of elements?


And what task would require the results of those to be merged into a 
single list?



It would be great to have a separate, standalone, function that handles

these merge/sort/unique operations for collections of DOM elements
(especially if they're disconnected from the document!).


The proposal from my previous mail falls into Option A.  Would it address
this issue adequately?  Specifically, defining document.createSelector() and
a Selector interface that allows running a query like this:

var elements = [...] // Some Array (or NodeList) of Elements
var selector = document.createSelector(em, strong);
var list = selector.querySelectorAll(elements);

This is equivalent to iterating over the elements array, running
elements[i].querySelectorAll(em, strong) on each, and then merging/sorting
all of the results into a single collection.


Not a huge fan of that - it seems really backwards.


Could you elaborate?


Another alternative would be to implement the merge/sort/unique
method and have it return a NodeList (which would, then, have qSA).


The collection of elements (step 1, above) input into the qSA step (step 
2) wouldn't need to be a sorted list.  Technically, it doesn't even 
necessarily have to be a merged list if the API allows multiple arrays 
and/or nodelists to be provided.  It will have no effect on the result. 
 The important point seems to be that a collection of elements can be 
provided somehow and that the implementation can execute the query on 
each distinct element in that collection.  How exactly that is done is 
just an API design issue.


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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Garrett Smith
On Thu, Sep 24, 2009 at 6:06 AM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 9/24/09 6:29 AM, Sean Hogan wrote:

 I would be surprised if an implementation didn't create an internal
 lookup table keyed off the selector text.

 Gecko doesn't.  Webkit doesn't.

 I just checked really quickly, and on my machine (a year-plus old laptop)

That is probably many times faster, and can probably be much more
liberal, than an optimized browser running on a mobile device with 128
MB RAM.



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sam Weinig


On Sep 23, 2009, at 8:37 PM, Jonas Sicking wrote:


On Wed, Sep 23, 2009 at 8:17 PM, John Resig jere...@gmail.com wrote:

Quick Summary of my opinions:

Matches Selector: Super-super useful - critical, in fact. We're not  
able to
remove jQuery's selector engine until this is implemented. I'm  
working with
the devs at Mozilla to get an implementation landed. Already have a  
test

suite in place.


And we have a patch :) So this should be available in Firefox 3.6 I  
hope.


WebKit now also has an implementation of Element.matchesSelector() (we  
are calling ours webkitMatchesSelector for the time being).  [https://bugs.webkit.org/show_bug.cgi?id=29703 
]


-Sam




Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Boris Zbarsky

On 9/24/09 2:17 PM, Garrett Smith wrote:

On Thu, Sep 24, 2009 at 6:06 AM, Boris Zbarskybzbar...@mit.edu  wrote:

Gecko doesn't.  Webkit doesn't.

I just checked really quickly, and on my machine (a year-plus old laptop)


That is probably many times faster, and can probably be much more
liberal, than an optimized browser running on a mobile device with 128
MB RAM.


Did I imply it's slow?  I just listed approximate hardware so that the 
times can be placed in some sort of context.


that said, note that on a mobile device with 128 MB of RAM the RAM is a 
lot more likely to be a problem than the CPU in some ways.  Running out 
of memory is strictly worse than being a little bit slower.  So a lookup 
table may be more of a loss than a win, depending.


-Boris



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Boris Zbarsky

On 9/24/09 2:36 PM, Sam Weinig wrote:

WebKit now also has an implementation of Element.matchesSelector() (we
are calling ours webkitMatchesSelector for the time being).
[https://bugs.webkit.org/show_bug.cgi?id=29703]


Right.  The Gecko one is mozMatchesSelector.

I bet we'd both love to rename it... ;)

-Boris



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread John Resig
 Not quite.  It depends what's being done and which steps need to be
 performed and how.  AIUI, there are 3 major steps involved here.

 1. Obtain a collection of Elements. This could be in one or more
   Arrays and/or NodeLists, depending on th.
 2. Iteratively execute a selector query on all elements in the
   collection, saving the results from each.
 3. Merge and sort all elements into a single NodeList, removing
   duplicates.

 In order to understand which of those steps need to be optimised by the
 browser with new APIs, it would help if you could explain some typical
 tasks, or use cases, that would need to perform any or all of those steps.

 In particular, what type of task would lead to there being more than one
 Array and/or NodeList to be used as input to step 2?


var foo = document.querySelectorAll(div.foo);
// do stuff with the divs...

var bar = document.querySelectorAll(div.bar);
// do stuff with the divs...

var items = document.createNodeList(foo, bar).querySelectorAll(ul.items);
// do stuff with the items...

Alternatively, in jQuery we would be doing something like this:

var foo = $(div.foo);
// do stuff with the divs...

var bar = $(div.bar);
// do stuff with the divs...

var items = foo.add( bar ).find(ul.items);
// do stuff with the items...

The important thing here is that:
1) There is only one sub-query being done.
2) That all the ul.items are being aggregated into a single collection, in
document order.


 What type of task would require executing the same selector query over a
 whole collection of elements?


The most important case is where there's additional filtering being done.
For example, in jQuery you can do:

$(div.foo)
   .bind(click, function(){})
   .find(span)
 .addClass(foo);

This reduces the total number of query operations down to two if it was
possible to run it against a complete collection.


 And what task would require the results of those to be merged into a single
 list?


The case where $(div).parents() is done, for example. This is a custom
query where we return a set of ancestor elements for each of the divs. This
is not something that I would expect the Selectors API to support but the
case of merging those results, sorting them, and uniqueing them is taking
place and is very costly.

To explain what I mean, let's look at a simple DOM:

html
  body
div id=one
  div id=two/div
/div
  /body
/html

$(div).parents() should return:
[ html, body, div#one, div#two ]

naturally if this query is being done on two elements the result set will
need to be merged/sorted/uniqued before it can be returned.


  It would be great to have a separate, standalone, function that handles

 these merge/sort/unique operations for collections of DOM elements
 (especially if they're disconnected from the document!).

  The proposal from my previous mail falls into Option A.  Would it
 address
 this issue adequately?  Specifically, defining document.createSelector()
 and
 a Selector interface that allows running a query like this:

 var elements = [...] // Some Array (or NodeList) of Elements
 var selector = document.createSelector(em, strong);
 var list = selector.querySelectorAll(elements);

 This is equivalent to iterating over the elements array, running
 elements[i].querySelectorAll(em, strong) on each, and then
 merging/sorting
 all of the results into a single collection.


 Not a huge fan of that - it seems really backwards.


 Could you elaborate?


Right now we have
(Document|Element|DocumentFragment).querySelectorAll(selector) - this makes
sense - you're going from your base root and finding sub-elements using the
selector.

You're proposing sticking the selector some place else and using the
selector as the root, sort of, then passing the collection of elements as
some sort of filter? It's completely backwards.


  Another alternative would be to implement the merge/sort/unique
 method and have it return a NodeList (which would, then, have qSA).


 The collection of elements (step 1, above) input into the qSA step (step 2)
 wouldn't need to be a sorted list.  Technically, it doesn't even necessarily
 have to be a merged list if the API allows multiple arrays and/or nodelists
 to be provided.  It will have no effect on the result.  The important point
 seems to be that a collection of elements can be provided somehow and that
 the implementation can execute the query on each distinct element in that
 collection.  How exactly that is done is just an API design issue.


Sure - but we can kill two birds with one API stone. Having a
document.createNodeList gives us merge/sort/unique (yay!) and it makes
NodeList.querySelectorAll and NodeList.matchesSelector doubly-useful (yay! -
since they can now be used for normal NodeLists and for array-like
collections, thanks to createNodeList).

--John


Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sam Weinig


On Sep 24, 2009, at 11:39 AM, Boris Zbarsky wrote:


On 9/24/09 2:36 PM, Sam Weinig wrote:
WebKit now also has an implementation of Element.matchesSelector()  
(we

are calling ours webkitMatchesSelector for the time being).
[https://bugs.webkit.org/show_bug.cgi?id=29703]


Right.  The Gecko one is mozMatchesSelector.

I bet we'd both love to rename it... ;)


Indeed.  The fact that mozilla was implementing it and picked a vendor  
prefixed name for the time being was part of what encouraged me to  
implement it last night.  So, thanks!


-Sam



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Jonas Sicking
On Thu, Sep 24, 2009 at 11:21 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 It would be great to have a separate, standalone, function that handles

 these merge/sort/unique operations for collections of DOM elements
 (especially if they're disconnected from the document!).

 The proposal from my previous mail falls into Option A.  Would it address
 this issue adequately?  Specifically, defining document.createSelector()
 and
 a Selector interface that allows running a query like this:

 var elements = [...] // Some Array (or NodeList) of Elements
 var selector = document.createSelector(em, strong);
 var list = selector.querySelectorAll(elements);

 This is equivalent to iterating over the elements array, running
 elements[i].querySelectorAll(em, strong) on each, and then
 merging/sorting
 all of the results into a single collection.

 Not a huge fan of that - it seems really backwards.

 Could you elaborate?

I had the same reaction as John, though quite possibly for different reasons.

Currently we have an API like node.querySelector(selector). Your
proposed API is selector.querySelector(node). That seems backwards
compared to existing API.

Quite possibly a namechange would make things better though.

/ Jonas



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Jonas Sicking
On Thu, Sep 24, 2009 at 8:59 AM, John Resig jre...@mozilla.com wrote:
 Another alternative
 would be to implement the merge/sort/unique method and have it return a
 NodeList (which would, then, have qSA).

 For example:
     document.createNodeList([ ... some elements ... ]).querySelectorAll(em,
 strong);

 createNodeList would create a NodeList holding the DOM nodes in document
 order (with duplicates removed). Since it's a proper NodeList we could then
 use qSA to find the elements that we want.

My concern with this API is that it forces the implementation to
always sort the array, even if already sorted, and then do a merge
sort on the individual results from querySelectorAll. It would be
faster to simply run the query on each node, and then merge sort the
results.

 If this is how it's implemented it actually becomes really useful to have
 the NodeList-based element filtering.

     document.createNodeList([ ... some elements ... ]).filterSelector(em,
 strong)

 (Since this would be much faster than using Array.filter or some other
 method.)

Are you sure that Array.filter would result in a significant perf hit?
What with recent jitting and stuff it would be great if we don't have
to rely on making everything a native method, but can rely on
javascript to do part of the work without taking too much of a perf
hit.

/ Jonas



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread John Resig
 My concern with this API is that it forces the implementation to
 always sort the array, even if already sorted, and then do a merge
 sort on the individual results from querySelectorAll. It would be
 faster to simply run the query on each node, and then merge sort the
 results.


That's not a huge issue - if a NodeList is coming in then we can assume that
it's already containing unique results and is in document order. It's only
if it's an array that we have to do the dance. Even in the case where the
array of results is already in document order the sort will be incredibly
fast (O(N)).


   If this is how it's implemented it actually becomes really useful to
 have
  the NodeList-based element filtering.
 
  document.createNodeList([ ... some elements ...
 ]).filterSelector(em,
  strong)
 
  (Since this would be much faster than using Array.filter or some other
  method.)

 Are you sure that Array.filter would result in a significant perf hit?
 What with recent jitting and stuff it would be great if we don't have
 to rely on making everything a native method, but can rely on
 javascript to do part of the work without taking too much of a perf
 hit.


I can guarantee that it'll be slower than doing it natively - especially so
in Internet Explorer 8.next (the more that they do under the covers the
faster we can provide results).

--John


Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Boris Zbarsky

On 9/24/09 5:09 PM, John Resig wrote:

It's only if it's an array that we have to do the dance. Even in the
case where the array of results is already in document order the sort
will be incredibly fast (O(N)).


O(N) in number of nodes in the array, and that assumes that the array is 
not being sorted using quicksort or some such.  But the constant here 
is not actually a constant.  The time required to compare the DOM 
positions of two nodes is very much dependent on the DOM, though clearly 
bounded above for a given DOM.  Last I checked, it's not that hard to 
produce situations in both Gecko and Webkit (haven't looked at the 
Trident and Presto source, so can't comment on those) where each such 
position comparison is O(N) in number of nodes in the DOM (though that 
usually involves having a very shallow DOM with a single node that has 
lots of kids).  So it's not that hard to end up with O(N^2) or worse 
behavior for sorting an array of nodes.  Of course that's true whether 
the sort is done in JS or in C++.  But it might be worth thinking about 
use cases here and whether they can be addressed in ways that don't 
involve sorting node arrays.


-Boris



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Jonas Sicking
On Thu, Sep 24, 2009 at 2:09 PM, John Resig jre...@mozilla.com wrote:

 My concern with this API is that it forces the implementation to
 always sort the array, even if already sorted, and then do a merge
 sort on the individual results from querySelectorAll. It would be
 faster to simply run the query on each node, and then merge sort the
 results.

 That's not a huge issue - if a NodeList is coming in then we can assume that
 it's already containing unique results and is in document order. It's only
 if it's an array that we have to do the dance. Even in the case where the
 array of results is already in document order the sort will be incredibly
 fast (O(N)).

Note that we'd have to do the same work that a JS implementation that
uses Node.compareDocumentPosition. The only win if we have to sort is
that we wouldn't be crossing the JS-C++ bridge as much. The actual
computations would be exactly the same.

  If this is how it's implemented it actually becomes really useful to
  have
  the NodeList-based element filtering.
 
      document.createNodeList([ ... some elements ...
  ]).filterSelector(em,
  strong)
 
  (Since this would be much faster than using Array.filter or some other
  method.)

 Are you sure that Array.filter would result in a significant perf hit?
 What with recent jitting and stuff it would be great if we don't have
 to rely on making everything a native method, but can rely on
 javascript to do part of the work without taking too much of a perf
 hit.

 I can guarantee that it'll be slower than doing it natively - especially so
 in Internet Explorer 8.next (the more that they do under the covers the
 faster we can provide results).

One could argue that microsoft should just shape up and supply a
modern JS engine ;)

In all seriousness though. It'd be nice to get data here. I'm wary of
adding APIs that are there just to work around slowness in
implementations, unless the wins are significant. Once we've added an
API we have to maintain it until the end of time, long after
performance improvements have made them obsolete.

There's definitely cases when this makes sense to do, however it'd be
nice with data to back up that this is one of those times.

/ Jonas



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Jonas Sicking
On Thu, Sep 24, 2009 at 2:41 PM, Jonas Sicking jo...@sicking.cc wrote:
  If this is how it's implemented it actually becomes really useful to
  have
  the NodeList-based element filtering.
 
      document.createNodeList([ ... some elements ...
  ]).filterSelector(em,
  strong)
 
  (Since this would be much faster than using Array.filter or some other
  method.)

 Are you sure that Array.filter would result in a significant perf hit?
 What with recent jitting and stuff it would be great if we don't have
 to rely on making everything a native method, but can rely on
 javascript to do part of the work without taking too much of a perf
 hit.

 I can guarantee that it'll be slower than doing it natively - especially so
 in Internet Explorer 8.next (the more that they do under the covers the
 faster we can provide results).

 One could argue that microsoft should just shape up and supply a
 modern JS engine ;)

 In all seriousness though. It'd be nice to get data here. I'm wary of
 adding APIs that are there just to work around slowness in
 implementations, unless the wins are significant. Once we've added an
 API we have to maintain it until the end of time, long after
 performance improvements have made them obsolete.

 There's definitely cases when this makes sense to do, however it'd be
 nice with data to back up that this is one of those times.

Btw, i got word from our JS engine guys that using
Array.map/Array.filter has bad performance behavior in firefox right
now (it makes you fall off trace). So if you run any perf tests it'd
probably be better not to use those functions, which is probably a
good idea anyway given that I don't think they work in all browsers
yet.

/ Jonas



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sean Hogan

Boris Zbarsky wrote:

On 9/24/09 6:29 AM, Sean Hogan wrote:

I would be surprised if an implementation didn't create an internal
lookup table keyed off the selector text.


Gecko doesn't.  Webkit doesn't.

I just checked really quickly, and on my machine (a year-plus old 
laptop) parsing the .foo .bar .baz selector and destroying the 
selector object before returning in Gecko takes about 80% of the 
overhead (that is, not walking the tree and doing selector matching) 
time of a querySelector() call.  Or, in numbers, about 5.5us per call. 
Webkit's time for executing my testcase is comparable, though I can't 
tell how much of their time is selector parsing.




That is surprising. Does the CSS engine do the same? If the CSS engine 
doesn't store the parsed selector then it probably doesn't matter for JS 
calls either.


If you're doing less than 1,000 calls that involve selectors api per 
second, the selector-parsing time is probably not that relevant.  But 
I don't know what the use cases are here.


-Boris


Take a event-delegation system that uses matchesSelector.
Every event that it handles will walk the event path trying 
element.matchesSelector with every registered handler.
e.g. There are twenty registered click handlers and a click event occurs 
on an element ten levels deep. There could be 20 * 10 = 200 calls to 
matchesSelector. Or 400 if the system simulates capture phase as well.


Or take a framework that adds enhancements to HTML elements based on 
selectors.
The framework wants to handle dynamic insertion to / removal from the 
page, so every DOMNodeInserted / DOMNodeRemoved (or equivalent) it will 
call querySelectorAll for all registered enhancements to see if there is 
any work to do.






Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sean Hogan

Lachlan Hunt wrote:

Mike Wilson wrote:

My first priority would be Matches Selector, and see to that
it fulfills the needs for event delegation.


Is there any special functionality that would be needed to achieve 
this?  If I understand correctly, event delegation just needs to be 
able to check whether the event target element matches a given 
selector.  So it would be something like:


if (evt.target.matchesSelector(.fooinput.bar)) {
   ...
}



In case it isn't obvious, we may want to check every element in the 
event path. i.e. all ancestors of  evt.target.


If matchesSelector could be called with a context element then it would 
become a more powerful version of compareDocumentPosition(). It is also 
more limited because you can't do preceding-siblings.


Examples
I'll use the :scope pseudo-class, although :context would be a better name.

elt.matchesSelector(:scope *, context); // descendant
elt.matchesSelector(:scope  * *, context); // descendant but not child
elt.matchesSelector(:scope ~ *, context); // following-sibling
elt.matchesSelector(:scope ~ *  *, context); // nephew (child of a 
following-sibling)


I would probably use it if it was there, but wouldn't complain if it 
wasn't.







Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Boris Zbarsky

On 9/24/09 6:45 PM, Sean Hogan wrote:

That is surprising. Does the CSS engine do the same? If the CSS engine
doesn't store the parsed selector then it probably doesn't matter for JS
calls either.


In Gecko the CSS engine stores the parsed selector.  In addition, it 
stores the selectors in various bins in a data structure to make 
matching faster.  In practice this means that you don't have to actually 
match most nodes against most selectors when computing the set of rules 
that match a given node.  This makes sense because you're guaranteed 
that every time a node is inserted into the DOM you will have to match 
it against every single one of those selectors. 
https://developer.mozilla.org/en/Writing_Efficient_CSS has a description 
of the setup.  I believe Webkit has something similar.  Again, I can't 
speak to Trident or Presto.


In the querySelector(All) case, the browser has no way to know that the 
selector will ever be reused.  In practice, the native implementations 
were enough faster than what they were replacing, even without any 
particularly fancy optimizations, that simplicity was judged more 
important than squeezing every bit of performance out.  At least in 
Gecko's case.  If we get to the point where they're being a bottleneck 
again, that will likely be revisited.



Take a event-delegation system that uses matchesSelector.
Every event that it handles will walk the event path trying
element.matchesSelector with every registered handler.
e.g. There are twenty registered click handlers and a click event occurs
on an element ten levels deep. There could be 20 * 10 = 200 calls to
matchesSelector. Or 400 if the system simulates capture phase as well.


200 calls would equate to ~1ms of selector parsing time in the the case 
of Gecko.  For a click event, that's not terrible.



Or take a framework that adds enhancements to HTML elements based on
selectors.
The framework wants to handle dynamic insertion to / removal from the
page, so every DOMNodeInserted / DOMNodeRemoved (or equivalent) it will
call querySelectorAll for all registered enhancements to see if there is
any work to do.


This could be much more of a problem.  I'd want be interested in what 
the actual performance is like in this situation.  Remember, the 
selector-parsing time was just the overhead; the real time usage is 
walking the DOM and doing the matching.  For matchesSelector this is 
much less significant, of course, but for querySelectorAll it's likely 
to be the dominating factor (gut feeling; if someone wants to measure 
that would be welcome).


I also wonder how well XBL or something like that would handle cases 
like this...  This setup (matching every node in a subtree against a set 
of selectors) is really not that well served by any of the APIs 
described here.  It's much closer to the CSS use case and would benefit 
from similar optimizations.


Note that I don't have anything against exposing parsed selector 
objects in JS.  I don't think it would be that difficult to implement 
it.  I'm just not sure whether the added complexity is really needed, 
and whether it's the best solution for the use cases.  Maybe it is; I'm 
just gathering data.  This is not exactly my area of expertise.


-Boris



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Sean Hogan

Boris Zbarsky wrote:

On 9/24/09 6:45 PM, Sean Hogan wrote:

That is surprising. Does the CSS engine do the same? If the CSS engine
doesn't store the parsed selector then it probably doesn't matter for JS
calls either.


In Gecko the CSS engine stores the parsed selector.  In addition, it 
stores the selectors in various bins in a data structure to make 
matching faster.  In practice this means that you don't have to 
actually match most nodes against most selectors when computing the 
set of rules that match a given node.  This makes sense because you're 
guaranteed that every time a node is inserted into the DOM you will 
have to match it against every single one of those selectors. 
https://developer.mozilla.org/en/Writing_Efficient_CSS has a 
description of the setup.  I believe Webkit has something similar.  
Again, I can't speak to Trident or Presto.


In the querySelector(All) case, the browser has no way to know that 
the selector will ever be reused.  In practice, the native 
implementations were enough faster than what they were replacing, even 
without any particularly fancy optimizations, that simplicity was 
judged more important than squeezing every bit of performance out.  At 
least in Gecko's case.  If we get to the point where they're being a 
bottleneck again, that will likely be revisited.



Take a event-delegation system that uses matchesSelector.
Every event that it handles will walk the event path trying
element.matchesSelector with every registered handler.
e.g. There are twenty registered click handlers and a click event occurs
on an element ten levels deep. There could be 20 * 10 = 200 calls to
matchesSelector. Or 400 if the system simulates capture phase as well.


200 calls would equate to ~1ms of selector parsing time in the the 
case of Gecko.  For a click event, that's not terrible.


No. It will be negligible compared to everything else that has to be done.




Or take a framework that adds enhancements to HTML elements based on
selectors.
The framework wants to handle dynamic insertion to / removal from the
page, so every DOMNodeInserted / DOMNodeRemoved (or equivalent) it will
call querySelectorAll for all registered enhancements to see if there is
any work to do.


This could be much more of a problem.  I'd want be interested in what 
the actual performance is like in this situation.  Remember, the 
selector-parsing time was just the overhead; the real time usage is 
walking the DOM and doing the matching.  For matchesSelector this is 
much less significant, of course, but for querySelectorAll it's likely 
to be the dominating factor (gut feeling; if someone wants to measure 
that would be welcome).


I also wonder how well XBL or something like that would handle cases 
like this...  This setup (matching every node in a subtree against a 
set of selectors) is really not that well served by any of the APIs 
described here.  It's much closer to the CSS use case and would 
benefit from similar optimizations.




XBL (and standard DOM implementations) is what we want.

Note that I don't have anything against exposing parsed selector 
objects in JS.  I don't think it would be that difficult to implement 
it.  I'm just not sure whether the added complexity is really needed, 
and whether it's the best solution for the use cases.  Maybe it is; 
I'm just gathering data.  This is not exactly my area of expertise.


-Boris



Thanks for that perspective. My main concern was that we don't create 
parsed selectors in JS (at least not for performance reasons).





Re: [selectors-api] Summary of Feature Requests for v2

2009-09-24 Thread Garrett Smith
On Thu, Sep 24, 2009 at 11:38 AM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 9/24/09 2:17 PM, Garrett Smith wrote:

 On Thu, Sep 24, 2009 at 6:06 AM, Boris Zbarskybzbar...@mit.edu  wrote:

 Gecko doesn't.  Webkit doesn't.

 I just checked really quickly, and on my machine (a year-plus old laptop)

 That is probably many times faster, and can probably be much more
 liberal, than an optimized browser running on a mobile device with 128
 MB RAM.

 Did I imply it's slow?  I just listed approximate hardware so that the times
 can be placed in some sort of context.

No, you did not say it is slow. I'm saying that your laptop is
probably a lot more powerful than a mobile device with a browser, such
as Blackberry9000. Do you agree with that?


 that said, note that on a mobile device with 128 MB of RAM the RAM is a lot
 more likely to be a problem than the CPU in some ways.  Running out of
 memory is strictly worse than being a little bit slower.  So a lookup table
 may be more of a loss than a win, depending.

An internal cache for matchesSelector (a lookup table) would be an
implementation detail, wouldn't it?

The idea for QuerySelector.create is the result would be an object
that the program could hang on to. It would not be recreated and
garbage collected each time.

element.matchesSelector would be recreated and collected each time.

The QuerySelector puts selector-related behavior on the selector, not
related to nodes.  For example a match method could match a selector
from a context node:

selector.match( contextNode );

A hand-rolled UserPanel might want to have a delegating listener to
check to see if an LI was selected from a list. So, the delegating
listener would be applied to each Panel instance, checking to see when
an item was selected.

Garrett



RE: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Mike Wilson
My first priority would be Matches Selector, and see to that
it fulfills the needs for event delegation.

Best regards
Mike Wilson

Lachlan Hunt wrote:
 Hi,
I'm planning to look at beginning work on Selectors API v2 soon to 
 add a number of requested features that didn't make it into the first 
 version.  This e-mail is a summary of what is being 
 considered, and is 
 intended to start discussion about which ones are really 
 worth focussing 
 on, and how to ensure they address the use cases appropriately.
 
 
 *Matches Selector*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5865
 
 The suggestion is for being able to check if a given element 
 matches a 
 given selector.  There is already similar functionality provided by 
 JQuery and Mozilla have begun working on an implementation for it in 
 Firefox.
 
 For the basic case, this is fairly trivial.  The method just needs to 
 take a selector and evaluate it against the element, and 
 return true or 
 false.
 
 But considering the proposed :scope pseudo-class that has been 
 previously discussed here and in the CSS WG, it might also be nice to 
 check if the element matches the selector in relation to a specified 
 reference element.
 
 For example, given 2 elements, div1 and div2, you could check 
 if div2 is 
 a sibling of div1 like this:
 
 div2.matchesSelector(:scope~div, div1);
 
 In this case, the div1 would be the reference element that is 
 matched by 
 :scope.  But we still need to determine how useful such functionality 
 would be, and whether it's worth pursuing it in this next version.
 
 
 *Filtering NodeLists*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5864
 
 The suggestion is for being able to take a NodeList, and filter the 
 nodes to obtain a collection of just those that match a given 
 selector.
 
 For example, being able to get a NodeList somehow, do 
 something with it, 
 and then filter it more to work with just a subset:
 
 e.g.
 var list = document.querySelctor(divp);
 // Do something with list, before obtaining the subset
 subset = list.filterSelector(.foo);
 ...
 
 We need to find and document the possible use cases for this feature.
 
 
 *Scoped Queries*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5860
 
 This has been discussed extensively in the past.  Basically, 
 the idea is 
 that the selector would be evaluated in the scope of the 
 element, in a 
 way more compatible with how libraries like JQuery work.  
 This slightly 
 different from the :scope pseudo-class proposal, see bug for details.
 
 
 *Collective Queries on NodeLists*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=7707
 
 The suggestion is to be able to run querySelector() and 
 querySelectorAll() on NodeList, and have the result be the union of 
 results in document order from running the method on each 
 Element in the 
 NodeList.
 
 e.g.
 
 list.querySelectorAll(p);
 
 Would be somewhat equivalent to running 
 list[i].querySelectorAll(p); 
 for  on each element in the list, and then building an array with the 
 union of distinct elements from all the results.  I've been told that 
 similar functionality for this already exists in JQuery.
 
 I believe the expectation is that both NodeList.querySelector() and 
 .querySelectorAll() would work.  The difference is that 
 querySelector() 
 on a NodeList would return a NodeList (unlike on Element which just 
 returns a single element) containing the first matches from 
 each node in 
 the list. i.e. equivalent to running list[i].querySelector() on each 
 node and then combining all results into an array.
 
 It also seems sensible to allow the new scoped methods to be 
 used in an 
 analogous way on NodeLists.
 
 
 *Namespace Prefix Resolution*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=6290
 
 The most controversial issue of the lot.  Need to clearly 
 document the 
 use cases and evaluate the problems being solved, and 
 determine if it's 
 really worth addressing in this version.
 
 -- 
 Lachlan Hunt - Opera Software
 http://lachy.id.au/
 http://www.opera.com/
 
 




Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Lachlan Hunt

Mike Wilson wrote:

My first priority would be Matches Selector, and see to that
it fulfills the needs for event delegation.


Is there any special functionality that would be needed to achieve this? 
 If I understand correctly, event delegation just needs to be able to 
check whether the event target element matches a given selector.  So it 
would be something like:


if (evt.target.matchesSelector(.fooinput.bar)) {
   ...
}

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



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Jonas Sicking
On Wed, Sep 23, 2009 at 4:51 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 *Scoped Queries*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5860

 This has been discussed extensively in the past.  Basically, the idea is
 that the selector would be evaluated in the scope of the element, in a way
 more compatible with how libraries like JQuery work.  This slightly
 different from the :scope pseudo-class proposal, see bug for details.

Note that what makes the strong, em selector (which apparently
some libraries support) hard to support spec-wise is that that is not
in fact valid CSS syntax. It's certainly possible to define behavior
for it, it's pretty clear to me how it's intended to work, but it
would mean specifying our own syntax.

However if supporting commaseparated queries is critical for libraries
then I see no other choise. We'll one way or another have to specify
our own syntax, though it can be heavily based on the productions in
the Selector spec.

/ Jonas



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Sean Hogan

I think a couple of those features are pretty low priority:

- I don't see the point of collective queries on NodeLists.
Are there any references for the proposal?
Otherwise I can't think of any useful queries that can't already be 
achieved with a single querySelectorAll().


- Filtering NodeLists is trivial once we get matchesSelector(). 


Sean


Lachlan Hunt wrote:

Hi,
  I'm planning to look at beginning work on Selectors API v2 soon to 
add a number of requested features that didn't make it into the first 
version.  This e-mail is a summary of what is being considered, and is 
intended to start discussion about which ones are really worth 
focussing on, and how to ensure they address the use cases appropriately.



*Matches Selector*
http://www.w3.org/Bugs/Public/show_bug.cgi?id=5865

*Filtering NodeLists*
http://www.w3.org/Bugs/Public/show_bug.cgi?id=5864

*Scoped Queries*
http://www.w3.org/Bugs/Public/show_bug.cgi?id=5860

*Collective Queries on NodeLists*
http://www.w3.org/Bugs/Public/show_bug.cgi?id=7707

*Namespace Prefix Resolution*
http://www.w3.org/Bugs/Public/show_bug.cgi?id=6290






Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Garrett Smith
On Wed, Sep 23, 2009 at 4:51 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote:
 Hi,
  I'm planning to look at beginning work on Selectors API v2 soon to add a
 number of requested features that didn't make it into the first version.
  This e-mail is a summary of what is being considered, and is intended to
 start discussion about which ones are really worth focussing on, and how to
 ensure they address the use cases appropriately.


 *Matches Selector*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5865

That helps event delegation pattern. That is, adding an event handler
to a container and then inspecting the event's target, to see if what
the user interacted with (and what the program should do about it).
This approach tends to be a much more efficient pattern than
traversing through the entire document to match nodes, and then add
event handler callbacks to them.

The existing draft encourages less efficient programming style of
traversing through the document. Pity.


 The suggestion is for being able to check if a given element matches a given
 selector.  There is already similar functionality provided by JQuery and
 Mozilla have begun working on an implementation for it in Firefox.

http://www.w3.org/Bugs/Public/show_bug.cgi?id=5865


 For the basic case, this is fairly trivial.  The method just needs to take a
 selector and evaluate it against the element, and return true or false.

 But considering the proposed :scope pseudo-class that has been previously
 discussed here and in the CSS WG, it might also be nice to check if the
 element matches the selector in relation to a specified reference element.

 For example, given 2 elements, div1 and div2, you could check if div2 is a
 sibling of div1 like this:

 div2.matchesSelector(:scope~div, div1);


The matching seems backwards. Should be on the matcher, instead of the
element? I don't see the role of the element being something that does
matching. The matching should be something left to some sort of a
Matcher.

A function to get an actual Selector object would allow the program to
creating a cached matcher.

var selector = QuerySelector.create(div.panel);
var isPanel = selector.matches(event.target);

Garrett



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread John Resig
Quick Summary of my opinions:

Matches Selector: Super-super useful - critical, in fact. We're not able to
remove jQuery's selector engine until this is implemented. I'm working with
the devs at Mozilla to get an implementation landed. Already have a test
suite in place.

Filtering NodeLists/StaticNodeLists, Queries on NodeLists/StaticNodeLists:
Neither of these are useful, as is, to libraries. What is actually useful is
the ability to run these against an array (or array-like collection) of DOM
nodes.

If I can do:
document.querySelectorAll.call([document.getElementById(node1),
document.getElementById(node2)], div  span); then yes, this proposal is
useful. Rarely do libraries store raw NodeLists (they need to be converted
into an array or array-like collection first).

Scoped Queries: Also critical. As it stands, in jQuery, we just punt
whenever does a query rooted to a DOM element and fallback to the old
selector engine.

Namespace Prefix Resolution: Indifferent.

--John


On Wed, Sep 23, 2009 at 7:51 AM, Lachlan Hunt lachlan.h...@lachy.id.auwrote:

 Hi,
  I'm planning to look at beginning work on Selectors API v2 soon to add a
 number of requested features that didn't make it into the first version.
  This e-mail is a summary of what is being considered, and is intended to
 start discussion about which ones are really worth focussing on, and how to
 ensure they address the use cases appropriately.


 *Matches Selector*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5865

 The suggestion is for being able to check if a given element matches a
 given selector.  There is already similar functionality provided by JQuery
 and Mozilla have begun working on an implementation for it in Firefox.

 For the basic case, this is fairly trivial.  The method just needs to take
 a selector and evaluate it against the element, and return true or false.

 But considering the proposed :scope pseudo-class that has been previously
 discussed here and in the CSS WG, it might also be nice to check if the
 element matches the selector in relation to a specified reference element.

 For example, given 2 elements, div1 and div2, you could check if div2 is a
 sibling of div1 like this:

 div2.matchesSelector(:scope~div, div1);

 In this case, the div1 would be the reference element that is matched by
 :scope.  But we still need to determine how useful such functionality would
 be, and whether it's worth pursuing it in this next version.


 *Filtering NodeLists*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5864

 The suggestion is for being able to take a NodeList, and filter the nodes
 to obtain a collection of just those that match a given selector.

 For example, being able to get a NodeList somehow, do something with it,
 and then filter it more to work with just a subset:

 e.g.
 var list = document.querySelctor(divp);
 // Do something with list, before obtaining the subset
 subset = list.filterSelector(.foo);
 ...

 We need to find and document the possible use cases for this feature.


 *Scoped Queries*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=5860

 This has been discussed extensively in the past.  Basically, the idea is
 that the selector would be evaluated in the scope of the element, in a way
 more compatible with how libraries like JQuery work.  This slightly
 different from the :scope pseudo-class proposal, see bug for details.


 *Collective Queries on NodeLists*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=7707

 The suggestion is to be able to run querySelector() and querySelectorAll()
 on NodeList, and have the result be the union of results in document order
 from running the method on each Element in the NodeList.

 e.g.

 list.querySelectorAll(p);

 Would be somewhat equivalent to running list[i].querySelectorAll(p); for
  on each element in the list, and then building an array with the union of
 distinct elements from all the results.  I've been told that similar
 functionality for this already exists in JQuery.

 I believe the expectation is that both NodeList.querySelector() and
 .querySelectorAll() would work.  The difference is that querySelector() on a
 NodeList would return a NodeList (unlike on Element which just returns a
 single element) containing the first matches from each node in the list.
 i.e. equivalent to running list[i].querySelector() on each node and then
 combining all results into an array.

 It also seems sensible to allow the new scoped methods to be used in an
 analogous way on NodeLists.


 *Namespace Prefix Resolution*
 http://www.w3.org/Bugs/Public/show_bug.cgi?id=6290

 The most controversial issue of the lot.  Need to clearly document the use
 cases and evaluate the problems being solved, and determine if it's really
 worth addressing in this version.

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




Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Jonas Sicking
On Wed, Sep 23, 2009 at 8:17 PM, John Resig jere...@gmail.com wrote:
 Quick Summary of my opinions:

 Matches Selector: Super-super useful - critical, in fact. We're not able to
 remove jQuery's selector engine until this is implemented. I'm working with
 the devs at Mozilla to get an implementation landed. Already have a test
 suite in place.

And we have a patch :) So this should be available in Firefox 3.6 I hope.

 Filtering NodeLists/StaticNodeLists, Queries on NodeLists/StaticNodeLists:
 Neither of these are useful, as is, to libraries. What is actually useful is
 the ability to run these against an array (or array-like collection) of DOM
 nodes.

Very good input!

 If I can do:
 document.querySelectorAll.call([document.getElementById(node1),
 document.getElementById(node2)], div  span); then yes, this proposal is
 useful. Rarely do libraries store raw NodeLists (they need to be converted
 into an array or array-like collection first).

I think filtering can easily be done using the filter function that's
available in Firefox these days. Don't know what the implementation
situation is for other UAs. But something like

filteredArray = myArrayOfNodes.filter(function(node) { return
node.matchesSelector(someselector); });

For querySelectorAll on arrays to work we'd need some function that
can merge multiple nodelists. Once you have that you can easily use
Array.map to get what you need.

 Scoped Queries: Also critical. As it stands, in jQuery, we just punt
 whenever does a query rooted to a DOM element and fallback to the old
 selector engine.

Does the :scope selector solve things for you? Or does it not because
of selectors like  foo,  bar, or even foo, bar?

/ Jonas



Re: [selectors-api] Summary of Feature Requests for v2

2009-09-23 Thread Maciej Stachowiak


On Sep 23, 2009, at 5:26 PM, Jonas Sicking wrote:

On Wed, Sep 23, 2009 at 4:51 AM, Lachlan Hunt lachlan.h...@lachy.id.au 
 wrote:

*Scoped Queries*
http://www.w3.org/Bugs/Public/show_bug.cgi?id=5860

This has been discussed extensively in the past.  Basically, the  
idea is
that the selector would be evaluated in the scope of the element,  
in a way

more compatible with how libraries like JQuery work.  This slightly
different from the :scope pseudo-class proposal, see bug for details.


Note that what makes the strong, em selector (which apparently
some libraries support) hard to support spec-wise is that that is not
in fact valid CSS syntax. It's certainly possible to define behavior
for it, it's pretty clear to me how it's intended to work, but it
would mean specifying our own syntax.

However if supporting commaseparated queries is critical for libraries
then I see no other choise. We'll one way or another have to specify
our own syntax, though it can be heavily based on the productions in
the Selector spec.


I think we can define an algorithm for turning an implicitly scoped  
pseudo-selector like strong, em into a proper selector  
using :scope -- in this case :scopestrong, :scopeem. We could  
either have an API entry point that takes a scoped pseudo-selector,  
defined as transforming to a real selector plus establishing a scope  
node, or just present the algorithm as an option for libraries that  
want to expose pseudo-selector syntax.


Regards,
Maciej