Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 2:26 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/18/11 8:08 PM, Alex Russell wrote: The other excuse is that adding special cases (which is what you're asking for) slows down all the non-special-case codepaths. That may be fine for _your_ usage of querySelectorAll, where you use it with a particular limited set of selectors, but it's not obvious that this is always a win. Most browsers try to optimize what is common. Yes, but what is common for Yehuda may well not be globally common. Yehuda is representing jQuery. I'll take his opinion as the global view unless he choses to say he's representing a personal opinion. There's also the question of premature optimization. Again, I'd love to see a non-synthetic situation where any of this matters. That would be a much more useful point to reason from than some sort of hypothetical faith-based optimization. The jQuery team did look to see what selector are hottest against their engine at some point and explicitly optimize short selectors as a result. The simple forms seem to be the most common. Regards
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 4:39 AM, Ojan Vafai o...@chromium.org wrote: Overall, I wholeheartedly support the proposal. I don't really see the benefit of allowing starting with a combinator. I think it's a rare case that you actually care about the scope element and in those cases, using :scope is fine. Instead of element.findAll( div .thinger), you use element.findAll(:scope div .thinger). That said, I don't object to considering the :scope implied if the selector starts with a combinator. Right, I think the argument for allowing a combinator start is two-fold: 1.) the libraries allow it, so should DOM 2.) we know the thing on the left, it's the implicit scope. Shorter is better, so allowing the implicitness here is a win on that basis I have a mild preference for argument #2. Shorter, without loss of clarity, for common stuff should nearly always win. On Tue, Oct 18, 2011 at 6:15 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/18/11 7:38 PM, Alex Russell wrote: The resolution I think is most natural is to split on , That fails with :any, with the expanded :not syntax, on attr selectors, etc. You can split on ',' while observing proper paren and quote nesting, but that can get pretty complicated. Can we define it as a sequence of selectors and be done with it? That way it can be defined as using the same parsing as CSS. A minor point is how to order the items in the returned flattened list are ordered (document order? the natural result of concat()?). Document order. Definitely. -Boris
Re: QSA, the problem with :scope, and naming
On Wed, 19 Oct 2011 17:22:46 +0900, Alex Russell slightly...@google.com wrote: Yehuda is representing jQuery. I'll take his opinion as the global view unless he choses to say he's representing a personal opinion. You misunderstand. Boris is contrasting with CSS. Selectors are used in more than just querySelectorAll() and their usage differs wildly. -- Anne van Kesteren http://annevankesteren.nl/
Re: QSA, the problem with :scope, and naming
Yehuda Katz (ph) 718.877.1325 On Wed, Oct 19, 2011 at 1:22 AM, Alex Russell slightly...@google.comwrote: On Wed, Oct 19, 2011 at 2:26 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/18/11 8:08 PM, Alex Russell wrote: The other excuse is that adding special cases (which is what you're asking for) slows down all the non-special-case codepaths. That may be fine for _your_ usage of querySelectorAll, where you use it with a particular limited set of selectors, but it's not obvious that this is always a win. Most browsers try to optimize what is common. Yes, but what is common for Yehuda may well not be globally common. Yehuda is representing jQuery. I'll take his opinion as the global view unless he choses to say he's representing a personal opinion. Right. I'm representing the position of jQuery. Sizzle (John's selector engine, used by jQuery) chose to optimize certain common selectors after an analysis of selectors used by jQuery found that a large percentage of all selectors used were a few simple forms that were amenable to getElement(s)By* optimizations. I provided a link to the code that implements this earlier in this thread. There's also the question of premature optimization. Again, I'd love to see a non-synthetic situation where any of this matters. That would be a much more useful point to reason from than some sort of hypothetical faith-based optimization. The jQuery team did look to see what selector are hottest against their engine at some point and explicitly optimize short selectors as a result. The simple forms seem to be the most common. Yep. Regards
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 9:29 AM, Anne van Kesteren ann...@opera.com wrote: On Wed, 19 Oct 2011 17:22:46 +0900, Alex Russell slightly...@google.com wrote: Yehuda is representing jQuery. I'll take his opinion as the global view unless he choses to say he's representing a personal opinion. You misunderstand. Boris is contrasting with CSS. Selectors are used in more than just querySelectorAll() and their usage differs wildly. Sure, of course, but suggesting that the optimizations for both need to be the same is also a strange place to start the discussion from. The QSA or find() implementation *should* differ to the extent that it provides developer value and is a real-world bottleneck.
Re: QSA, the problem with :scope, and naming
On 19/10/11 2:39 PM, Ojan Vafai wrote: Overall, I wholeheartedly support the proposal. I don't really see the benefit of allowing starting with a combinator. I think it's a rare case that you actually care about the scope element and in those cases, using :scope is fine. Instead of element.findAll( div .thinger), you use element.findAll(:scope div .thinger). That said, I don't object to considering the :scope implied if the selector starts with a combinator. I can think of two reasons one might ponder allowing :scope to be explicit. 1. so that the selector string can be a valid CSS selector string. (:scopediv.thinger instead of div.thinger). But if this is important then :scope should always be explicit, in which case we can just use querySelectorAll(). 2. to allow break-out behavior. e.g. div.findAll(body div span); // finds nothing div.findAll(body div:scope span); // finds span's that are descendants of div In this scenario, the :scope pseudo allows ancestors of div to be matched against. (No-one would use body in this context, but it is easy to imagine them using a .class selector which matches an ancestor of div.) But if you want break-out behavior you might not know which part of the selector to put the :scope pseudo on. Could it be: body div:scope span body *:scope div span body div *:scope span So for break-out behavior just use querySelectorAll(). I'm pretty sure previous discussions (before this thread) have covered this more thoroughly, and shown that it has to be all or nothing with the :scope pseudo-attribute. That is, either a) :scope MUST be explicit, in which case just use querySelectorAll() b) :scope MUST be implied at the start of every selector chain. Sean
Re: QSA, the problem with :scope, and naming
On 2011-10-19 01:58, Tab Atkins Jr. wrote: Based on discussion on the mailing list,style scoped will be changing to the latter behavior as well, with the ability to invoke the former behavior in the rare circumstances when you explicitly want it. Despite some similarities in appearance, the proposed changes to style scoped will still use selectors differently from that proposed here for a new findAll() method. 1. Syntax In style scoped, selectors still can't begin with a combinator, but in the proposed API, they can. The @global at-rule was proposed to 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 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 -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On 2011-10-18 18:42, Alex Russell wrote: Related and equally important, that querySelector and querySelectorAll are often referred to by the abbreviation QSA suggests that its name is bloated and improved versions should have shorter names. I know the names suck. The names we ended up with certainly weren't the first choice of names we were going for, but sadly ended up with after a long drawn out naming debate and a misguided consensus poll to override what should have been an editorial decision. So, if we do introduce new methods, personally I'd be happy to use sensible names for any them, if the rest of the group will allow it this time. I therefore believe that this group's current design for scoped selection could be improved significantly. If I understand the latest draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class) correctly, a scoped search for multiple elements would be written as: element.querySelectorAll(:scope div .thinger); Both then name and the need to specify :scope are punitive to readers and writers of this code. The selector is *obviously* happening in relationship to element somehow. The only sane relationship (from a modern JS hacker's perspective) is that it's where our selector starts from. The current design is capable of handling many more use cases than the single use case that you are trying to optimise for here. Ah, but we don't need to care what CSS thinks of our DOM-only API. We can live and let live by building on :scope and specifying find* as syntactic sugar, defined as: HTMLDocument.prototype.find = HTMLElement.prototype.find = function(rootedSelector) { return this.querySelector(:scope + rootedSelector); } HTMLDocument.prototype.findAll = HTMLElement.prototype.findAll = function(rootedSelector) { return this.querySelectorAll(:scope + rootedSelector); } This is an incomplete way of dealing with the problem, as it doesn't correctly handle comma separated lists of selectors, so the parsing problem cannot be as trivial as prepending :scope . It would also give a strange result if the author passed an empty string findAll(); :scope + = :scope = meaning to return itself. In another email, you wrote: The resolution I think is most natural is to split on , and assume that all selectors in the list are :scope prefixed and that. Simple string processing to split on , is also ineffective as it doesn't correctly deal with commas within functional notation pseudo-classes, attribute selectors, etc. I have attempted to address this problem before and the algorithm for parsing a *scoped selector string* (basically what you're calling a rootedSelector) existed in an old draft [1]. That draft also allowed the flexibility of including an explicit :scope pseudo-class in the selector, which allows for conditional expressions to be built into the selector itself that can be used to check the state of the scope element or any of its ancestors. (But that draft isn't perfect. It has a few known bugs in the definition, including one that would also make it return the context node itself under certain circumstances where an explicit :scope selector is used.) [1] http://dev.w3.org/cvsweb/~checkout~/2006/webapi/selectors-api2/Overview.html?rev=1.29;content-type=text%2Fhtml#processing-selectors -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 1:54 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-10-18 18:42, Alex Russell wrote: Related and equally important, that querySelector and querySelectorAll are often referred to by the abbreviation QSA suggests that its name is bloated and improved versions should have shorter names. I know the names suck. The names we ended up with certainly weren't the first choice of names we were going for, but sadly ended up with after a long drawn out naming debate and a misguided consensus poll to override what should have been an editorial decision. So, if we do introduce new methods, personally I'd be happy to use sensible names for any them, if the rest of the group will allow it this time. It should *still* be an editorial decision. Shorter is better. This is well-trod ground. We have plenty of evidence for what JS devs really want. Lets get on with it. I therefore believe that this group's current design for scoped selection could be improved significantly. If I understand the latest draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class) correctly, a scoped search for multiple elements would be written as: element.querySelectorAll(:scope div .thinger); Both then name and the need to specify :scope are punitive to readers and writers of this code. The selector is *obviously* happening in relationship to element somehow. The only sane relationship (from a modern JS hacker's perspective) is that it's where our selector starts from. The current design is capable of handling many more use cases than the single use case that you are trying to optimise for here. That's OK. I'm not stoning the current design. See below. I'm suggesting we build on it and provide the API people are making heavy use of today. This cow path deserves not just paving, but streetlights, wide shoulders, and a bike lane. Ah, but we don't need to care what CSS thinks of our DOM-only API. We can live and let live by building on :scope and specifying find* as syntactic sugar, defined as: HTMLDocument.prototype.find = HTMLElement.prototype.find = function(rootedSelector) { return this.querySelector(:scope + rootedSelector); } HTMLDocument.prototype.findAll = HTMLElement.prototype.findAll = function(rootedSelector) { return this.querySelectorAll(:scope + rootedSelector); } This is an incomplete way of dealing with the problem, as it doesn't correctly handle comma separated lists of selectors, so the parsing problem cannot be as trivial as prepending :scope . It would also give a strange result if the author passed an empty string findAll(); :scope + = :scope = meaning to return itself. Yes, yes. Pseudo-code. I snipped other code I posted to not handle obvious corner cases to prevent posting eye-watering walls of code as well. Happy to draft a longer/more-complete straw-man, but nobody's *actually* going to implement it this way in any case. As an aside, it's shocking how nit-picky and anti-collaborative this group is. *sigh* In another email, you wrote: The resolution I think is most natural is to split on , and assume that all selectors in the list are :scope prefixed and that. Simple string processing to split on , is also ineffective as it doesn't correctly deal with commas within functional notation pseudo-classes, attribute selectors, etc. See, again, subsequent follow-ups. I have attempted to address this problem before and the algorithm for parsing a *scoped selector string* (basically what you're calling a rootedSelector) existed in an old draft [1]. That draft also allowed the flexibility of including an explicit :scope pseudo-class in the selector, which allows for conditional expressions to be built into the selector itself that can be used to check the state of the scope element or any of its ancestors. We could accomodate that by looking at the passed selector and trying to determine if it includes a :scope term. If so, avoid prefixing. That'd allow this sort of flexibility for folks who want to write things out long-hand or target the scope root in the selector, possibly returning itself. I''d also support a resolution for this sort of power-tool that forces people to use document.qsa(..., scopeEl) to get at that sort of thing. (But that draft isn't perfect. It has a few known bugs in the definition, including one that would also make it return the context node itself under certain circumstances where an explicit :scope selector is used.) [1] http://dev.w3.org/cvsweb/~checkout~/2006/webapi/selectors-api2/Overview.html?rev=1.29;content-type=text%2Fhtml#processing-selectors
Re: QSA, the problem with :scope, and naming
On 10/19/11 4:22 AM, Alex Russell wrote: Yehuda is representing jQuery. I'll take his opinion as the global view unless he choses to say he's representing a personal opinion. Global jQuery view, yes? I stand by a slightly statement that what is common and needs to be fast for Yehuda may not be common and needing to be fast in general. In particular, lots of jQuery selector usage is not in fact performance-sensitive. Some obviously is. Again, I'd love to see data on the cases where performance matters, both when jQuery is involved and when it's not. I should note that the larger and more complicated a web app the less likely it is to use jQuery from what I've seen I'm absolutely sure that simple selectors dominate complicated ones in all contexts, but again I'd really like to have data on what _sort_ of simple selectors really need optimizing. The jQuery team did look to see what selector are hottest against their engine Yes. See above. -Boris
Re: QSA, the problem with :scope, and naming
On 10/19/11 4:29 AM, Anne van Kesteren wrote: On Wed, 19 Oct 2011 17:22:46 +0900, Alex Russell slightly...@google.com wrote: Yehuda is representing jQuery. I'll take his opinion as the global view unless he choses to say he's representing a personal opinion. You misunderstand. Boris is contrasting with CSS. No, I'm talking purely about querySelector. The fact that at least Gecko and WebKit implement querySelector in a braindead way because that lets them reuse their selector matching code is a somewhat separate kettle of fish. What we're discussing her, in particular, are optimizations that make use of the differences in use case between CSS selector matching (match one node to a bazillion selectors) and querySelector (match one selectors to possibly a bazillion nodes). There are ways to optimize the latter by examining the structure of the selector and making use of existing cached information in the browser that make no sense in the CSS context and would be implemented as a preprocessing pass before falling back on actual selector matching. WebKit does a few of these, of varying utility. I've considered doing some in Gecko, but again want to have hard data that they're actually needed before adding complexity. -Boris
Re: QSA, the problem with :scope, and naming
On 10/19/11 11:17 AM, Boris Zbarsky wrote: 4) Mapping Sizzle(#id) with document a context to getElementById(id). This isn't a valid optimization for querySelector because there can be multiple elements with the same id; And just as a note, since someone asked me off-list how this can possibly be true... Given this markup: div id=x div id=y/div div id=y/div /div calling jQuery.find(#y) returns an array with one element in it while calling jQuery.find(#y, document.getElementById(x)) returns an array with two elements. I have no idea whether this is purposeful behavior or just a bug in Sizzle brought on by the optimization listed above. -Boris
[Bug 14513] New: WebSocket API: Missing reference for definition of MessageEvent
http://www.w3.org/Bugs/Public/show_bug.cgi?id=14513 Summary: WebSocket API: Missing reference for definition of MessageEvent Product: WebAppsWG Version: unspecified Platform: PC OS/Version: Windows NT Status: NEW Severity: normal Priority: P2 Component: WebSocket API (editor: Ian Hickson) AssignedTo: i...@hixie.ch ReportedBy: tyosh...@google.com QAContact: member-webapi-...@w3.org CC: m...@w3.org, public-webapps@w3.org As communications section has been split out from HTML5 spec, we no longer have reference for definition of MessageEvent. How about referring HTML5 Web Messaging spec? http://dev.w3.org/html5/postmsg/ -- Configure bugmail: http://www.w3.org/Bugs/Public/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are on the CC list for the bug.
Re: QSA, the problem with :scope, and naming
On 2011-10-19 16:08, Alex Russell wrote: On Wed, Oct 19, 2011 at 1:54 PM, Lachlan Huntlachlan.h...@lachy.id.au wrote: I have attempted to address this problem before and the algorithm for parsing a *scoped selector string* (basically what you're calling a rootedSelector) existed in an old draft [1]. That draft also allowed the flexibility of including an explicit :scope pseudo-class in the selector, which allows for conditional expressions to be built into the selector itself that can be used to check the state of the scope element or any of its ancestors. We could accomodate that by looking at the passed selector and trying to determine if it includes a :scope term. If so, avoid prefixing. Yes, that's exactly what the draft specified. That'd allow this sort of flexibility for folks who want to write things out long-hand or target the scope root in the selector, possibly returning itself. I don't see a use case for wanting the proposed method to be able to return the element itself. The case where it's useful for elements matching :scope to be the subject of a selector is where you're trying to filter a list of elements. e.g. document.querySelectorAll(.foo:scope, list); // Returns all elements from list that match. But this wouldn't make sense el.find(.foo:scope) // Return itself if it matches. That result seems effectively like a less efficient boolean check that is already handled by el.matchesSelector(.foo). I''d also support a resolution for this sort of power-tool that forces people to use document.qsa(...,scopeEl) to get at that sort of thing. If there was no special handling to check for an explicit :scope, that would mean that any selector that does include :scope explicitly would not match anything at all. e.g. el.findAll(:scopep); That would be equivalent to: document.querySelectorAll(:scope :scopep, el); Which won't match anything. That might keep things simpler from an implementation perspective and doesn't sacrifice any functionality being requested. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On 2011-10-18 18:42, Alex Russell wrote: HTMLDocument.prototype.find = HTMLElement.prototype.find = function(rootedSelector) { return this.querySelector(:scope + rootedSelector); } HTMLDocument.prototype.findAll = HTMLElement.prototype.findAll = function(rootedSelector) { return this.querySelectorAll(:scope + rootedSelector); } What exactly does it mean to have a rootedSelector applied to the Document object? As I understand it, the scoping problem explained only seems to apply to running the query on elements, whereas the existing document.qsa already behaves as expected by authors. It doesn't seem to make sense to try and prepend :scope to selectors in that case. e.g. document.find(html) shouldn't be equivalent to document.querySelector(:scope html); So, either we introduce the new method only for elements, or we use a similarly named method on document for a similar, but slightly different purpose. A previous use case discussed on this list is the ability to take a collection of elements, and execute the same selector on all all of them, as if iterating the list, collecting the results and returning a single merged collection. The current API handles this use case with document.querySelectorAll, explicitly specifying :scope and passing a collection of refNodes. e.g. var list = ...; // Elements (Array, NodeList or indexed object) // Find the sibling p elements of all elements in the list document.querySelectorAll(:scope+p, list); Thus, if we do introduce the proposed method, should it behave similarly, but with the implied rather than explicit :scope? e.g. document.findAll(+p, list); -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 5:17 AM, Lachlan Hunt lachlan.h...@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
Re: QSA, the problem with :scope, and naming
On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell slightly...@google.com wrote: Lachlan and I have been having an...um...*spirited* twitter discussion regarding querySelectorAll, the (deceased?) queryScopedSelectorAll, and :scope. He asked me to continue here, so I'll try to keep it short: The rooted forms of querySelector and querySelectorAll are mis-designed. Discussions about a Scoped variant or :scope pseudo tacitly acknowledge this, and the JS libraries are proof in their own right: no major JS library exposes the QSA semantic, instead choosing to implement a rooted search. Related and equally important, that querySelector and querySelectorAll are often referred to by the abbreviation QSA suggests that its name is bloated and improved versions should have shorter names. APIs gain use both through naming and through use. On today's internet -- the one where 50% of all websites include jQuery -- you could even go with element.$(selector) and everyone would know what you mean: it's clearly a search rooted at the element on the left-hand side of the dot. Ceteris peribus, shorter is better. When there's a tie that needs to be broken, the more frequently used the API, the shorter the name it deserves -- i.e., the larger the component of its meaning it will gain through use and repetition and not naming and documentation. I know some on this list might disagree, but all of the above is incredibly non-controversial today. Even if there may have been debates about scoping or naming when QSA was originally designed, history has settled them. And QSA lost on both counts. I therefore believe that this group's current design for scoped selection could be improved significantly. If I understand the latest draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class) correctly, a scoped search for multiple elements would be written as: element.querySelectorAll(:scope div .thinger); Both then name and the need to specify :scope are punitive to readers and writers of this code. The selector is *obviously* happening in relationship to element somehow. The only sane relationship (from a modern JS hacker's perspective) is that it's where our selector starts from. I'd like to instead propose that we shorten all of this up and kill both stones by introducing a new API pair, find and findAll, that are rooted as JS devs expect. The above becomes: element.findAll( div .thinger); Out come the knives! You can't start a selector with a combinator! Ah, but we don't need to care what CSS thinks of our DOM-only API. We can live and let live by building on :scope and specifying find* as syntactic sugar, defined as: HTMLDocument.prototype.find = HTMLElement.prototype.find = function(rootedSelector) { return this.querySelector(:scope + rootedSelector); } HTMLDocument.prototype.findAll = HTMLElement.prototype.findAll = function(rootedSelector) { return this.querySelectorAll(:scope + rootedSelector); } Of course, :scope in this case is just a special case of the ID rooting hack, but if we're going to have it, we can kill both birds with it. Obvious follow up questions: Q.) Why do we need this at all? Don't the toolkits already just do this internally? A.) Are you saying everyone, everywhere, all the time should need to use a toolkit to get sane behavior from the DOM? If so, what are we doing here, exactly? Q.) Shorter names? Those are for weaklings! A.) And humans. Who still constitute most of our developers. Won't someone please think of the humans? Q.) You're just duplicating things! A.) If you ignore all of the things that are different, then that's true. If not, well, then no. This is a change. And a good one for the reasons listed above. Thoughts? I like the general idea here. And since we're changing behavior, I think it's a good opportunity to come up with shorter names. Naming is really hard. The shorter names we use, the more likely it is that we're going to break webpages which are messing around with the prototype chain and it increases the risk that we'll regret it later when we come up with even better functions which should use those names. Say that we come up with an even better query language than selectors, at that point .find will simply not be available to us. However, it does seem like selectors are here to stay. And as much as they have shortcomings, people seem to really like them for querying. So with that out of the way, I agree that the CSS working group shouldn't be what is holding us back. However we do need a precise definition of what the new function does. Is prepending :scope and then parsing as a normal selector always going to give the behavior we want? This is actually what I think we got stuck on when the original querySelector was designed. So let's get into specifics about how things should work. According to your proposal of simply prepending a conceptual :scope to each selector
Re: QSA, the problem with :scope, and naming
On 10/19/11 10:07 PM, Jonas Sicking wrote: I like the general idea here. And since we're changing behavior, I think it's a good opportunity to come up with shorter names. Naming is really hard. The shorter names we use, the more likely it is that we're going to break webpages which are messing around with the prototype chain Not just the proto chain. Every method you add on Element or Document will break any inline event handler attributes that happen to use that name as a bareword. We had some amount of that with the list property on inputs, and that only added a property on HTMLInputElement Again, in this case a shorter name may make sense, but in general there are good reasons for not using short names all the time. -Boris
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 7:22 PM, Ojan Vafai o...@chromium.org wrote: On Wed, Oct 19, 2011 at 7:07 PM, Jonas Sicking jo...@sicking.cc wrote: .findAll(body :scope div) // returns nothing Wouldn't this return ids 1,2,3 if we're not prepending :scope as you say below? Yes, but he was answering those questions based on the assumption of always prepending :scope. Additionally it seems to me that we could allow the same syntax for style scoped. But maybe others disagree? Sounds good to me. A sticky case you left out is parent, sibling and reference combinators. .findAll(+ div) Assuming the context node has siblings, should that return them? If so, should it match siblings when using style scoped. IMO, it shouldn't match anything in either case. We should assert that only descendants of the scope element will ever be returned. This would also make it naturally match style scoped where only descendants of the scope element are ever affected. I disagree. It's extremely useful and natural for .find(:scope + div) to match sibling of the context node. Basically, the presence of :scope would turn off *all* the limitations; the only thing that the context node still does is match the :scope pseudo. The selector should match across and return elements from anywhere in the document. This is where I think that .find and style scoped should diverge in behavior. .find should have two cases: 1. Selector without :scope - run the selector only across the descendants of the context node. (No need to explicitly filter, since the results will only contain descendants of the context node already.) 2. Selector with :scope - run the selector across the entire document, with :scope matching the context node. (No filtering here, either.) style scoped should (I think) have three cases: 1. Selector without :scope - same as .find 2. Selector with :scope - Same as #1, but also including the context node. 3. Selector in @global - run the selector across the entire document, filter the results to only be the context node and its descendants. (Some people disagree with me on this, and think that #1 and #2 should be merged to always include the context node. That's acceptable, but I don't like it as much.) I think it's perfectly okay that these two APIs have different cases. ~TJ
Re: Mouse Lock
WebEvents WG is taking up this spec. I've created a new Mouse Lock thread on public-webevents: http://lists.w3.org/Archives/Public/public-webevents/2011OctDec/0066.html
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 7:22 PM, Ojan Vafai o...@chromium.org wrote: On Wed, Oct 19, 2011 at 7:07 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell slightly...@google.com wrote: Lachlan and I have been having an...um...*spirited* twitter discussion regarding querySelectorAll, the (deceased?) queryScopedSelectorAll, and :scope. He asked me to continue here, so I'll try to keep it short: The rooted forms of querySelector and querySelectorAll are mis-designed. Discussions about a Scoped variant or :scope pseudo tacitly acknowledge this, and the JS libraries are proof in their own right: no major JS library exposes the QSA semantic, instead choosing to implement a rooted search. Related and equally important, that querySelector and querySelectorAll are often referred to by the abbreviation QSA suggests that its name is bloated and improved versions should have shorter names. APIs gain use both through naming and through use. On today's internet -- the one where 50% of all websites include jQuery -- you could even go with element.$(selector) and everyone would know what you mean: it's clearly a search rooted at the element on the left-hand side of the dot. Ceteris peribus, shorter is better. When there's a tie that needs to be broken, the more frequently used the API, the shorter the name it deserves -- i.e., the larger the component of its meaning it will gain through use and repetition and not naming and documentation. I know some on this list might disagree, but all of the above is incredibly non-controversial today. Even if there may have been debates about scoping or naming when QSA was originally designed, history has settled them. And QSA lost on both counts. I therefore believe that this group's current design for scoped selection could be improved significantly. If I understand the latest draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class) correctly, a scoped search for multiple elements would be written as: element.querySelectorAll(:scope div .thinger); Both then name and the need to specify :scope are punitive to readers and writers of this code. The selector is *obviously* happening in relationship to element somehow. The only sane relationship (from a modern JS hacker's perspective) is that it's where our selector starts from. I'd like to instead propose that we shorten all of this up and kill both stones by introducing a new API pair, find and findAll, that are rooted as JS devs expect. The above becomes: element.findAll( div .thinger); Out come the knives! You can't start a selector with a combinator! Ah, but we don't need to care what CSS thinks of our DOM-only API. We can live and let live by building on :scope and specifying find* as syntactic sugar, defined as: HTMLDocument.prototype.find = HTMLElement.prototype.find = function(rootedSelector) { return this.querySelector(:scope + rootedSelector); } HTMLDocument.prototype.findAll = HTMLElement.prototype.findAll = function(rootedSelector) { return this.querySelectorAll(:scope + rootedSelector); } Of course, :scope in this case is just a special case of the ID rooting hack, but if we're going to have it, we can kill both birds with it. Obvious follow up questions: Q.) Why do we need this at all? Don't the toolkits already just do this internally? A.) Are you saying everyone, everywhere, all the time should need to use a toolkit to get sane behavior from the DOM? If so, what are we doing here, exactly? Q.) Shorter names? Those are for weaklings! A.) And humans. Who still constitute most of our developers. Won't someone please think of the humans? Q.) You're just duplicating things! A.) If you ignore all of the things that are different, then that's true. If not, well, then no. This is a change. And a good one for the reasons listed above. Thoughts? I like the general idea here. And since we're changing behavior, I think it's a good opportunity to come up with shorter names. Naming is really hard. The shorter names we use, the more likely it is that we're going to break webpages which are messing around with the prototype chain and it increases the risk that we'll regret it later when we come up with even better functions which should use those names. Say that we come up with an even better query language than selectors, at that point .find will simply not be available to us. However, it does seem like selectors are here to stay. And as much as they have shortcomings, people seem to really like them for querying. So with that out of the way, I agree that the CSS working group shouldn't be what is holding us back. However we do need a precise definition of what the new function does. Is prepending :scope and then parsing as a normal selector always going to give the
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 10:08 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: On Wed, Oct 19, 2011 at 7:22 PM, Ojan Vafai o...@chromium.org wrote: On Wed, Oct 19, 2011 at 7:07 PM, Jonas Sicking jo...@sicking.cc wrote: .findAll(body :scope div) // returns nothing Wouldn't this return ids 1,2,3 if we're not prepending :scope as you say below? Yes, but he was answering those questions based on the assumption of always prepending :scope. Exactly. Additionally it seems to me that we could allow the same syntax for style scoped. But maybe others disagree? Sounds good to me. A sticky case you left out is parent, sibling and reference combinators. .findAll(+ div) Assuming the context node has siblings, should that return them? If so, should it match siblings when using style scoped. IMO, it shouldn't match anything in either case. We should assert that only descendants of the scope element will ever be returned. This would also make it naturally match style scoped where only descendants of the scope element are ever affected. I disagree. It's extremely useful and natural for .find(:scope + div) to match sibling of the context node. Basically, the presence of :scope would turn off *all* the limitations; the only thing that the context node still does is match the :scope pseudo. The selector should match across and return elements from anywhere in the document. This is where I think that .find and style scoped should diverge in behavior. .find should have two cases: 1. Selector without :scope - run the selector only across the descendants of the context node. (No need to explicitly filter, since the results will only contain descendants of the context node already.) 2. Selector with :scope - run the selector across the entire document, with :scope matching the context node. (No filtering here, either.) style scoped should (I think) have three cases: 1. Selector without :scope - same as .find 2. Selector with :scope - Same as #1, but also including the context node. 3. Selector in @global - run the selector across the entire document, filter the results to only be the context node and its descendants. (Some people disagree with me on this, and think that #1 and #2 should be merged to always include the context node. That's acceptable, but I don't like it as much.) I think it's perfectly okay that these two APIs have different cases. I'm not sure I understand what you are proposing here. Are you saying that div style scoped :scope { background: green; } /style /div should set the background of the div green? This does seem intuitive I agree, but it might also lead to strange behavior since the rendering of the div will change once the stylesheet is parsed. In other words, it's very easy to get flash-of-unstyled-content behavior. / Jonas
Re: QSA, the problem with :scope, and naming
On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell slightly...@google.com wrote: Lachlan and I have been having an...um...*spirited* twitter discussion regarding querySelectorAll, the (deceased?) queryScopedSelectorAll, and :scope. He asked me to continue here, so I'll try to keep it short: The rooted forms of querySelector and querySelectorAll are mis-designed. Discussions about a Scoped variant or :scope pseudo tacitly acknowledge this, and the JS libraries are proof in their own right: no major JS library exposes the QSA semantic, instead choosing to implement a rooted search. Related and equally important, that querySelector and querySelectorAll are often referred to by the abbreviation QSA suggests that its name is bloated and improved versions should have shorter names. APIs gain use both through naming and through use. On today's internet -- the one where 50% of all websites include jQuery -- you could even go with element.$(selector) and everyone would know what you mean: it's clearly a search rooted at the element on the left-hand side of the dot. Ceteris peribus, shorter is better. When there's a tie that needs to be broken, the more frequently used the API, the shorter the name it deserves -- i.e., the larger the component of its meaning it will gain through use and repetition and not naming and documentation. I know some on this list might disagree, but all of the above is incredibly non-controversial today. Even if there may have been debates about scoping or naming when QSA was originally designed, history has settled them. And QSA lost on both counts. I therefore believe that this group's current design for scoped selection could be improved significantly. If I understand the latest draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class) correctly, a scoped search for multiple elements would be written as: element.querySelectorAll(:scope div .thinger); Both then name and the need to specify :scope are punitive to readers and writers of this code. The selector is *obviously* happening in relationship to element somehow. The only sane relationship (from a modern JS hacker's perspective) is that it's where our selector starts from. I'd like to instead propose that we shorten all of this up and kill both stones by introducing a new API pair, find and findAll, that are rooted as JS devs expect. The above becomes: element.findAll( div .thinger); Out come the knives! You can't start a selector with a combinator! Ah, but we don't need to care what CSS thinks of our DOM-only API. We can live and let live by building on :scope and specifying find* as syntactic sugar, defined as: HTMLDocument.prototype.find = HTMLElement.prototype.find = function(rootedSelector) { return this.querySelector(:scope + rootedSelector); } HTMLDocument.prototype.findAll = HTMLElement.prototype.findAll = function(rootedSelector) { return this.querySelectorAll(:scope + rootedSelector); } Of course, :scope in this case is just a special case of the ID rooting hack, but if we're going to have it, we can kill both birds with it. Obvious follow up questions: Q.) Why do we need this at all? Don't the toolkits already just do this internally? A.) Are you saying everyone, everywhere, all the time should need to use a toolkit to get sane behavior from the DOM? If so, what are we doing here, exactly? Q.) Shorter names? Those are for weaklings! A.) And humans. Who still constitute most of our developers. Won't someone please think of the humans? Q.) You're just duplicating things! A.) If you ignore all of the things that are different, then that's true. If not, well, then no. This is a change. And a good one for the reasons listed above. Thoughts? Oh, and as a separate issue. I think .findAll should return a plain old JS Array. Not a NodeList or any other type of host object. One of the use cases is being able to mutate the returned value. This is useful if you're for example doing multiple .findAll calls (possibly with different context nodes) and want to merge the resulting lists into a single list. / Jonas