- From: Sean Hogan <shogun70@westnet.com.au>
- Date: Thu, 18 Sep 2014 13:46:36 +1000
- To: Anne van Kesteren <annevk@annevk.nl>
- CC: Boris Zbarsky <bzbarsky@mit.edu>, "Tab Atkins Jr." <jackalmage@gmail.com>, "www-style@w3.org" <www-style@w3.org>, "www-dom@w3.org" <www-dom@w3.org>, David Håsäther <hasather@gmail.com>
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). > > It doesn't sound like you are considering the explicit passing of a scope element yet, but for when you do, here is a use-case for element.closest(scopedSelector, ancestor). Say I want to use event delegation by registering an event listener on ancestor (A) to respond to events that would have bubbled through some descendant (D) which matches a selector scoped to A, say ":scope > li.enabled > a[href]". Now say D (in this case <a href="...">) has a child <span> element (E) on which a click occurs. When the click event propagates to the listener on A, it has a target of E and a currentTarget of A. I want to find if it bubbled through some descendant D. Ideally I could call: D = E.closest(':scope > li.enabled > a[href]', A); or even with a relative selector D = E.closest('> li.enabled > a[href]', A); The explicit or implicit ':scope' would refer to A. For this use-case, the upwards DOM traversal for matching would also terminate on reaching **the- scope-boundary**, A. This seems intuitive to me, and implies that E.closest(scopedSelector) // no explicit scope element is the equivalent of E.closest(scopedSelector, document-or-fragment-or-root) Or maybe it implies that the ':scope' selector is a nonsense for .matches() and .closest() when there is no explicit scope element. I can't recall for sure, but I thought the original discussion of matches() did conclude that if there was an explicit scope element E.matches(selector, A) then selector was a scoped-selector - loosely the inverse of A.query(selector) - and otherwise E.matches(selector) the selector was unscoped - and loosely the inverse of A.querySelector(selector) I would expect: E = A.query('> ul > li'); // assuming E exists ... E.matches('> ul > li', A) // true And I would expect: E = A.querySelector('ul > li'); // assuming E (a descendant of A) exists ... E.matches('ul > li') // true I might even expect: E = A.query(':scope ul > li'); // assuming E exists ... E.matches(':scope ul > li') // true - equivalent of E.matches(':scope ul > li', document) But I wouldn't expect: E = A.query(':scope ul > li'); // assuming E exists ... E.matches(':scope ul > li') // false - equivalent of E.matches(':scope ul > li', E) Sean
Received on Thursday, 18 September 2014 03:47:19 UTC