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

On Wed, Oct 19, 2011 at 5:17 AM, Lachlan Hunt <lachlan.hunt@lachy.id.au> wrote:
> 1. Syntax
>
> In <style scoped>, selectors still can't begin with a combinator, but in the
> proposed API, they can.

I agree with Lachy here.  I think it's valuable to have consistency
with <style scoped>, so that a selector passed to el.findAll() and one
put in a <style scoped> that's a child of el return the same results.

You already have to explicitly add :scope if you want to do some
additional selecting of the scoping element anyway.

This breaks consistency with jQuery, but it maintains consistency with
the rest of the platform.  I think this is important enough to justify
the slight loss in terseness in the situations where you want a child
or reference combinator off of the scoping element.


> The @global at-rule was proposed to

I'll make a reasonable assumption about what Lachy was planning to say
here, and say that QSA seems to already solve the "consistency with
@global within <style scoped>" issue.  At least as far as I can tell,
it acts the same.


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

While I think we should match <style scoped> here, I believe the
conflict should be resolved by changing <style scoped>.  A few people
in the last discussion preferred selectors to automatically match the
scoping element, but I still think that's a bad decision.  The scoping
element should only be returned if a selector is a single compound
selector containing :scope.  It makes selectors a little bit more
complex to understand, but in an intuitive way.

Regardless of what ends up happening in <style scoped>, I agree with
the API choice here to make div.find("div") not match the calling
element.  The common case is that I'm descending into the element and
wouldn't expect the calling element to match.  I'd like to write naive
algorithms that don't need to either manually check the results
against the calling element or defensively write
div.find(":not(:scope) div").  I'm okay with using the presence of
:scope in the selector as a declaration of intent here, and switch
behavior accordingly.


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

I am okay with this behavioral split from <style scoped>, and believe
it's both useful and intuitive.

(Note that the function can actually return elements from *anywhere*
given the current Selectors 4 draft, as it can follow a reference
combinator which can point to an arbitrary position in the doc.)

~TJ

Received on Wednesday, 19 October 2011 19:52:20 UTC