Re: [SelectorsAPI] Thoughts on querySelectorAll

> If we were to do the implementation similarly to Dojo, then it would
> be 
> impossible to select only child elements on the context node. 
> Consider 
> this:
> 
> <div id=foo>
>    <div> <!-- A -->
>      <div> <!-- B -->
>      </div>
>    </div>
> </div>
> 
> foo.querySelectorAll("div");

Isn't that what the purpose of :root/:scope/$self/etc. was?

  foo.querySelectorAll(":scope > div")

The above would return only the child nodes of the #foo div.

> Assuming the selector won't match the context node (foo) itself, that
> would contain both descendant div elements (A and B).  But in the case
> where only child nodes of foo are wanted (A), this is impossible.
> This following would not work because the previous assumption was that
> selectors would not match the element itself.
> 
> foo.querySelectorAll("#foo>div");
> 
> Dojo gives the same result for that scenario.
> 
> dojo.query('#foo>div', foo);

That's a bug in Dojo. Notice that the following returns the correct result (using the above test page):

  var foo = document.getElementById("foo");
  dojo.query("p > span", foo)
  // => []

jQuery is the same (only without the obvious bug):
http://ejohn.org/files/bugs/qsa-root/jquery.html

  var foo = document.getElementById("foo");
  jQuery(foo).find("#foo > span")
  // => []
  jQuery(foo).find("p > span")
  // => []

> There are several reasons the spec is defined the way it is on this
> issue.
> 
> 1. It's how selectors work in existing Selector implementations. i.e.
> Given any element, the selector is evaluated against it in the context
> of the entire document tree. That makes it easier for implementations
> to 
> implement this API without requiring them to significantly alter their
> selector engines.

That's a fine goal - however wouldn't a better goal have been to base the work on all of the JavaScript libraries that are being emulated with this specification?

Considering that jQuery, alone, has millions of users it seems like it would be a smart choice to at least think about how things are currently being done:
http://code.google.com/p/jqueryjs/downloads/list

If the only thing that is kept in mind is how to best implement an API then you'll never succeed in creating a usable API: The two concepts are completely disassociated from each other. Of course it's completely possible to do both - but as we can see here, usability is being sacrificed on the altar of implementation simplicity.

> 2. This makes it more flexible for authors, so that they can select 
> based upon ancestor elements if needed.

When has that ever been a concern? I would think that there'd be, at least, a few users clamoring for that, right now, with jQuery - when that's hardly the case. Conflating two separate concerns: Finding elements beneath the current element that match an expression (contextually) versus one that matches globally (and, thus, matching ancestors) deserve two separate APIs. And if implementation, history, and massive, widespread, use are any indicator then contextual searching is the superior way of making this happen.

> 3. Introducing a :scope selector (or equivalent) solves all the issues
> you have raised, without sacrificing potentially useful functionality.
> :scope would also be useful in contexts outside of Selectors API, such
> as within HTML5's scoped stylesheets and possibly XBL.

Sure, it solves the technical problem but it doesn't solve the actual problem: The API is broken in its current state. Doing .querySelectorAll("div span") has the potential to return completely incorrect results - while, at the same time, providing no information as to how they should be used correctly. If everyone (save for the implementors, apparently) expects it to work in a contextual manner why should they even come to think about using a new selector expression to make it work?

> So while you haven't convinced me that we need to significantly alter
> the spec to address this issue, you have convinced me that we should
> try 
> to expedite the specification and implementation of a :scope selector
> (or equivalent).

I've lost something here: At one point you explain how it would be really hard for implementors to adjust their selector implementations to match contextually - and on the other hand you are now actively arguing for that exact feature to be included. Either it's hard, or not (regardless, that should have no affect on the actual API).

With the addition of :scope (or similar) useragents will now have to support contextual selectors - which completely removes any argument for not having them in the first place (other than "we don't want to change the spec because useragents started to implement it too early").

I would rather have one useragent that implements this specification correctly than 8 useragents that implement it incorrectly.

--John

Received on Friday, 2 May 2008 22:00:54 UTC