Re: Behavior of matches() and closest() with :scope()

On 4/09/14 7:54 PM, Anne van Kesteren wrote:
> On Tue, Sep 2, 2014 at 6:53 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote:
>> ...
> So let's see. If we don't pass a :scope elements argument we get
>
>    E.matches(":scope") -> false
>    E.closest(":scope") -> null
>    E.closest(":has(> :scope)" -> null
>
> If we pass E as :scope elements we get
>
>    E.matches(":scope") -> true
>    E.closest(":scope") -> E
>    E.closest(":has(> :scope)" -> E's parent
>
> Now for closest() we could also pass the current ancestor A as :scope
> elements, then we get
>
>    E.closest(":scope") -> E
>    E.closest(":has(> :scope)" -> null
>
> It seems to me that passing the element on which the method is invoked
> as :scope elements (i.e. E) makes the most sense. That argues for 1).
>
>

My last response was a bit disorganized, mostly because I was thinking 
aloud.
Take 2:

E.closest() and E.matches() should take an additional argument - an 
explicit scoping root.

If the explicit scoping root is not an ancestor of E then E.matches() 
will fail and E.closest() will find nothing.

If no explicit scoping root is passed then EITHER:
     the selector must be an absolute selector
OR
     the implied scoping root is assumed to be the **document** or 
fragment or virtual fragment of E.

E.closest(selector, scope) attempts to find a matching element by 
testing E against the selector, and if that fails then testing E's 
parent, and-so-on until the scoping root is reached. The scoping root is 
NOT tested, even if it is an element.

The use-cases for this form of call are in scoped-event-delegation.

E.matches(selector, scope) will be used when the event listener at the 
scoping root needs to detect that the event-target matches the scoped 
selector. e.g.

     function listener(event) {
         if (!event.target.matches(relativeSelector, 
event.currentTarget)) return;
         // event.target does match. Perform handler
     }

E.closest(selector, scope) will be used when the event listener at the 
scoping root needs to detect that the event bubbles through an element 
that matches the scoped selector. e.g.

     function listener(event) {
         var myTarget = event.target.closest(relativeSelector, 
event.currentTarget);
          if (!myTarget) return;
         // event has bubbled thru a matching element. Perform handler
     }

If no explicit scoping root is passed and no explicit ":scope" is in the 
selector, e.g.
     E.matches('ul li')
then
     assuming this is an absolute selector
is equivalent to
     assuming it has an implied :scope which matches the document.

If the scoping root is assumed to be E then you can only have absolute 
selectors.

regards,
Sean

Received on Sunday, 21 September 2014 12:02:46 UTC