Re: QSA, the problem with :scope, and naming
On 20/10/11 1:07 PM, Jonas Sicking wrote: On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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. 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. I don't agree with Selectors API supporting invalid selectors, but I guess the discussion is more appropriate here than there. 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 group, for the following DOM: body id=3 div id=context foo=bar div id=1/div div class=class id=2/div div class=withChildren id=3div class=child id=4/div/div /div /body you'd get the following behavior: .findAll(div) // returns ids 1,2,3,4 .findAll() // returns the context node itself. This was indicated undesirable .findAll(body :scope div) // returns nothing .findAll(#3) // returns id 3, but not the body node .findAll( div) // returns ids 1,2,3 .findAll([foo=bar]) // returns nothing .findAll([id=1]) // returns id 1 .findAll(:first-child) // returns id 1 Is this desired behavior in all cases except the empty string? If so this seems very doable to me. We can easily make an exception for the case when the passed in string contains no selectors and make that an error or some such. I know everyone knows this, but... These specific examples (where the selector is not a comma separated list) plus most instances of selector lists (e.g. th, td, ul li, ol li) can be trivially supported by a tiny wrapper around querySelectorAll() as defined in Selectors API v2. In fact, I've never seen a selector list that couldn't be successfully split on , and I wouldn't be surprised if they are never used outside of stylesheets. I do however like the idea that if :scope appears in the selector, then this removes the prepending of :scope to that selector group. Is there a reason not to do that? 1. Already supported (in the draft spec) by querySelectorAll(). 2. Not supported by JS libs. 3. No use cases requiring it. Additionally it seems to me that we could allow the same syntax for style scoped. But maybe others disagree? Surely it is both or neither. You don't want to set a precedent for DOM selectors not matching CSS selectors. I think appropriate optimizations as well as extensible functions should be out-of-scope for this thread. They are both big subjects on their own and we're approaching 50 emails in this thread.
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 11:14 PM, Sean Hogan shogu...@westnet.com.au wrote: I do however like the idea that if :scope appears in the selector, then this removes the prepending of :scope to that selector group. Is there a reason not to do that? 1. Already supported (in the draft spec) by querySelectorAll(). 2. Not supported by JS libs. 3. No use cases requiring it. It's annoying if querying engines have to work with two different query methods (.findAll and .querySelectorAll) and know when to call which. So I don't think 1 is a particularly good point. However 3 is a very good point. If there aren't use cases, then we shouldn't support it. And 2 is a good indicator that there aren't use cases. But if someone knows of use cases then I'm all ears. It's also something that can be added at a later point if use cases arise. / Jonas
Re: QSA, the problem with :scope, and naming
On 20/10/11 5:41 PM, Jonas Sicking wrote: On Wed, Oct 19, 2011 at 11:14 PM, Sean Hoganshogu...@westnet.com.au wrote: I do however like the idea that if :scope appears in the selector, then this removes the prepending of :scope to that selector group. Is there a reason not to do that? 1. Already supported (in the draft spec) by querySelectorAll(). 2. Not supported by JS libs. 3. No use cases requiring it. It's annoying if querying engines have to work with two different query methods (.findAll and .querySelectorAll) and know when to call which. So I don't think 1 is a particularly good point. I don't follow that. If you want style scoped behavior you call findAll(). If not you call querySelectorAll(). Sean
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 14:08, Tab Atkins Jr. jackalm...@gmail.com wrote: 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.) The - very valid IMHO - main argument for style scoped to always include the scoping element was to allow for easy migration. I.e., where currently you'd use style #menu .foo { color: green } /style div id=menu div class=foo Will be green /div /div div class=foo Will NOT be green /div You could just stick the stylesheet under the div and add 'scoped': div id=menu style scoped #menu .foo { color: green } /style div class=foo Will be green /div /div div class=foo Will NOT be green /div In browsers that don't support 'scoped', this would still work. Where 'scoped' is supported, this doesn't change much per se, except that those style rules don't need to be checked outside the scope. Once a majority of browsers support style scoped one can then proceed to simplify the rules and remove '#menu' (admitted caveat: where this then doesn't create an ambiguity with the scoping div). - Roland
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 14:52, Jonas Sicking jo...@sicking.cc wrote: 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. Hixie's - again valid IMHO - counterargument for this was that, with the above proposal: div { background-color-green } would not color the scoping element, while the more specific (!) div:scope { background-color: green } would. I.e., a more specific selector suddenly selecting MORE elements than a not so specific one. - Roland
Re: QSA, the problem with :scope, and naming
On 20/10/11 1:07 PM, Jonas Sicking wrote: On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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. 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); I like the general idea here. I think appropriate optimizations as well as extensible functions should be out-of-scope for this thread. They are both big subjects on their own and we're approaching 50 emails in this thread. If find / findAll are added to the spec there should also be an equivalent of matchesSelector that handles implicitly scoped selector, e.g. div .thinger. To aid discussion I will call this matches(), but I don't think it is a good final choice. The primary use-case for matchesSelector() has been event-delegation, and this is the same for matches(). More specifically, consider the following scenario: jQuery adds a new event registration method that uses event delegation to mimic the behavior of: $(elem).find( div .thinger).bind(eventType, fn); The new method is called proxybind(), and the equivalent of the above is: $(elem).proxybind( div .thinger, eventType, fn); The event handling for proxybind() would invoke matches( div .thinger, [elem]) on elements between the event target and elem to find matching elements. Sean
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 1:14 AM, Sean Hogan shogu...@westnet.com.au wrote: On 20/10/11 1:07 PM, Jonas Sicking wrote: On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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. 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); I like the general idea here. I think appropriate optimizations as well as extensible functions should be out-of-scope for this thread. They are both big subjects on their own and we're approaching 50 emails in this thread. If find / findAll are added to the spec there should also be an equivalent of matchesSelector that handles implicitly scoped selector, e.g. div .thinger. To aid discussion I will call this matches(), but I don't think it is a good final choice. How would .matches() work? For .findAll we basically prepend a :scope selector step where the :scope pseudo-class matches the element on which .findAll was called. If we did the same for .matches() then elem.matches(foo) would try to match elem against the selector :scope foo where :scope only matches elem and thus the selector only matches elements which are descendants of the element on which .matches() was called. In other words, .matches() would never match anything. Clearly you must have some other behavior in mind as a function which always returns false isn't particularly interesting. / Jonas
Re: QSA, the problem with :scope, and naming
On 20/10/11 7:32 PM, Jonas Sicking wrote: On Thu, Oct 20, 2011 at 1:14 AM, Sean Hoganshogu...@westnet.com.au wrote: On 20/10/11 1:07 PM, Jonas Sicking wrote: On Tue, Oct 18, 2011 at 9:42 AM, Alex Russellslightly...@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. 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); I like the general idea here. I think appropriate optimizations as well as extensible functions should be out-of-scope for this thread. They are both big subjects on their own and we're approaching 50 emails in this thread. If find / findAll are added to the spec there should also be an equivalent of matchesSelector that handles implicitly scoped selector, e.g. div .thinger. To aid discussion I will call this matches(), but I don't think it is a good final choice. How would .matches() work? For .findAll we basically prepend a :scope selector step where the :scope pseudo-class matches the element on which .findAll was called. If we did the same for .matches() then elem.matches(foo) would try to match elem against the selector :scope foo where :scope only matches elem and thus the selector only matches elements which are descendants of the element on which .matches() was called. In other words, .matches() would never match anything. Clearly you must have some other behavior in mind as a function which always returns false isn't particularly interesting. / Jonas See the definition of matchesSelector(selector, [ refNodes ]) in the spec: http://www.w3.org/TR/selectors-api2/#matchtesting
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 2:13 AM, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-10-20 07:52, Jonas Sicking wrote: 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 thediv green? This does seem intuitive I agree, but it might also lead to strange behavior since the rendering of thediv will change once the stylesheet is parsed. In other words, it's very easy to get flash-of-unstyled-content behavior. In the majority of cases, that's a very easy problem for authors to avoid by always putting style scoped as the first child of the element. Since a div is invisible in most cases without any content or other styles, any change in rendering from invisible to visible wouldn't be any different from normal incremental rendering. You'd also get the same effect since earlier siblings of the style scoped would be affected, right? I.e. in the following markup, both spans would be blue and the div would be green. div spantext here/span style scoped :scope span { background: green } :scope { background: red } /style spanmore text here/span /div Another problem though is one of performance. Allowing style elements which are later in the DOM affect earlier nodes means that you have to walk significantly more nodes to look for which sheet could apply. You'll have to both look at the elements children, as well as all following siblings. If style scoped elements only affect nodes which are later in DOM order, it's much easier to keep a list of all currently applying style scoped elements as you walk through the DOM tree. However it's possible that this can be optimized satisfactory. But it's something that we need implementation feedback on. / Jonas
Re: QSA, the problem with :scope, and naming
On 20/10/11 8:42 PM, Lachlan Hunt wrote: On 2011-10-20 10:14, Sean Hogan wrote: The primary use-case for matchesSelector() has been event-delegation, and this is the same for matches(). More specifically, consider the following scenario: jQuery adds a new event registration method that uses event delegation to mimic the behavior of: $(elem).find( div .thinger).bind(eventType, fn); The new method is called proxybind(), and the equivalent of the above is: $(elem).proxybind( div .thinger, eventType, fn); The event handling for proxybind() would invoke matches( div .thinger, [elem]) on elements between the event target and elem to find matching elements. It may not be too late to introduce that behaviour into matchesSelector, with a switch based on the presence or absence of the refNodes/refElement parameter. As currently specified, calling the following doesn't and shouldn't prepend :scope. el.matchesSelector(div .foo); This one also matches the prefixed implementations in browsers, since most haven't started supporting :scope yet, and I don't believe Mozilla's experimental implementation [1] has landed yet. As currently specified, calling this: el.matchesSelector(div .foo, ref); Also doesn't prepend :scope automatically, but in that case, the ref nodes do nothing useful. But this selector can still match elements. Admittedly I can't think of a use-case for this, but it is conceivable for someone to expect this to work without an implied :scope. Authors have to use :scope explicitly for them to be useful as in something like: el.matchesSelector(:scope div .foo, ref); Or el.matchesSelector(div:scope .foo, ref); One thing we could possibly do is define that if ref nodes are passed, and the selector doesn't explicitly use :scope, then effectively prepend :scope . This would be exactly the same behaviour as that discussed for .findAll(); That wouldn't break compatibility with anything, optimises for a common case and avoids introducing two separate match methods. I don't see the need for findAll(), but if it is added I think it should always imply :scope at the start of a selector, and I think a separate match method that does the same should be added. To do otherwise seems too ambiguous for a DOM API. e.g. el.matchesSelector(div .foo); // No ref, no magic :scope el.matchesSelector(div .foo, ref);// Implied, magic :scope el.matchesSelector(+.foo, ref); // Implied, magic :scope el.matchesSelector(:scope div .foo, ref); // Explicit, no magic :scope el.matchesSelector(div:scope .foo, ref); // Explicit, no magic :scope [1] https://bugzilla.mozilla.org/show_bug.cgi?id=648722
Re: QSA, the problem with :scope, and naming
On Wed, Oct 19, 2011 at 7:01 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote: 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. Great! So if we specify this behavior for .find() too, I think we're in good shape. 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. Ok, I'm fine with not allowing that. That result seems effectively like a less efficient boolean check that is already handled by el.matchesSelector(.foo). matchesSelector...really? We've gotta get a better name for that = ) 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); yeah, that occurred to me after sending the last mail. 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. Eh, I'm not sure it's sane though. Putting in checking for :scope in the selector and not prefixing if it occurs seems the only reasonable thing. There's a corner case I haven't formed an opinion on though: el.find(div span :scope .whatevs); ...does what? I think it's an error. :scope will need to occur in the first term or not at all for .find(). -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 3:07 AM, 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. So long as the slots are still writable, no loss. Their patches into the prototype chain still exist. Being afraid of this when we're on top seems really, *REALLY* strange to me. Say that we come up with an even better query language than selectors, at that point .find will simply not be available to us. Premature optimization. And $ is still available ;-) 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
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 6:55 AM, 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? 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. I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. It's insane that we even have a NodeList type which isn't a real array at all. Adding a parallel system when we could just fix the one we have (and preserve the value of a separate prototype for extension) is wonky to me. That said, I'd *also* support the ability to have some sort of decorator mechanism before return on .find() or a way to re-route the prototype of the returned Array. +heycam to debate this point. 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. Agreed. An end to the Array.slice() hacks would be great.
Re: QSA, the problem with :scope, and naming
On 2011-10-20 12:50, Alex Russell wrote: On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sickingjo...@sicking.cc wrote: 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. I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. We need NodeList separate from Array where they are live lists. I forget the reason we originally opted for a static NodeList rather than Array when this issue was originally discussed a few years ago. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 12:05 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-10-20 12:50, Alex Russell wrote: On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sickingjo...@sicking.cc wrote: 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. I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. We need NodeList separate from Array where they are live lists. No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you is a documentation issue, not a question of type...unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. I forget the reason we originally opted for a static NodeList rather than Array when this issue was originally discussed a few years ago.
Re: QSA, the problem with :scope, and naming
On 20/10/11 10:05 PM, Lachlan Hunt wrote: On 2011-10-20 12:50, Alex Russell wrote: On Thu, Oct 20, 2011 at 6:55 AM, Jonas Sickingjo...@sicking.cc wrote: 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. I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. We need NodeList separate from Array where they are live lists. I forget the reason we originally opted for a static NodeList rather than Array when this issue was originally discussed a few years ago. I wonder if anyone is relying on querySelectorAll() returning a StaticNodeList?
Re: QSA, the problem with :scope, and naming
On 2011-10-20 13:18, Alex Russell wrote: On Thu, Oct 20, 2011 at 12:05 PM, Lachlan Huntlachlan.h...@lachy.id.au wrote: We need NodeList separate from Array where they are live lists. No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you is a documentation issue, not a question of type...unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. The author cannot be allowed to directly modify a live list, as such it must be an immutable object from the script's perspective. Otherwise, things would get really complicated if this happened: var p = document.getElementsByTagName(p); p.reverse(); p.push(x); p.shift(); document.body.insertBefore(document.createElement(p), p[2]); Where in the array would that new P element get added? NodeLists are supposed to be live and in document order. Ordinarily, that new P element would be inserted into the document and the change reflected in the NodeList. By allowing an author to modify the list in some way, that completely breaks the way NodeLists are defined to work. Now while it's arguable that live node lists were a mistake and that it would have been better if static Arrays were returned, we are stuck with them and cannot change that. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 3:39 AM, Alex Russell slightly...@google.com wrote: There's a corner case I haven't formed an opinion on though: el.find(div span :scope .whatevs); ...does what? I think it's an error. :scope will need to occur in the first term or not at all for .find(). Disagree. If :scope appears in the selector, just match across the whole document. It's simple and useful. (It's equivalent to document.querySelector(div span :scope .whatevs, el), except shorter and amenable to chaining.) ~TJ
Re: QSA, the problem with :scope, and naming
On 2011-10-20 13:35, Sean Hogan wrote: I wonder if anyone is relying on querySelectorAll() returning a StaticNodeList? Only if there are people out there using list.item(n) instead of list[n], or people extending the NodeList interface and expecting such methods to be available on the result. Though I suspect the former is very rare, and the latter doesn't work in all browsers. -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On 20/10/11 10:49 PM, Lachlan Hunt wrote: On 2011-10-20 13:35, Sean Hogan wrote: I wonder if anyone is relying on querySelectorAll() returning a StaticNodeList? Only if there are people out there using list.item(n) instead of list[n], or people extending the NodeList interface and expecting such methods to be available on the result. Though I suspect the former is very rare, and the latter doesn't work in all browsers. And I wonder if one of the browser vendors would be willing to silently change the behavior and see if they get any bug reports.
Re: QSA, the problem with :scope, and naming
On 10/20/11 6:50 AM, Alex Russell wrote: 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. I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. You missed the point of Jonas's suggestion. DOM NodeLists are not mutable via direct manipulation of indexed properties. Jonas is saying that we want the return value here to be thus mutable. Making all DOM NodeLists mutable won't really work because a bunch of them are live; there's no sane way to combine liveness and mutability. The non-live lists (e.g. the one involved here) could be made mutable, but then why make then nodelists at all? What's the point? It's insane that we even have a NodeList type which isn't a real array at all. It's not at all insane for the live lists. See previous discussion about this. I think any solution here that tries to treat live and non-live lists identically is doomed to failure. -Boris
Re: QSA, the problem with :scope, and naming
On 10/20/11 7:18 AM, Alex Russell wrote: No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you There is no sane way to mutate the list on the part of the browser if someone else is also messing with it, because the someone else can violate basic invariants the browser's behavior needs to maintain. unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. Yes. Though I don't know what slots you're talking about; the only sane JS implementation of live nodelists is as a proxy. There's no way to get the behaviors that browsers have for them otherwise. -Boris
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 3:14 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/20/11 7:18 AM, Alex Russell wrote: No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you There is no sane way to mutate the list on the part of the browser if someone else is also messing with it, because the someone else can violate basic invariants the browser's behavior needs to maintain. Right. So you need to vend an apparently-immutable Array, one which can only be changed by the browser. I think that could be accomplished in terms of Proxies. But it's still an Array type. unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. Yes. Though I don't know what slots you're talking about; the only sane JS implementation of live nodelists is as a proxy. There's no way to get the behaviors that browsers have for them otherwise. But it can be a Proxy to an *Array*, not to some weird non-Array type.
Re: QSA, the problem with :scope, and naming
On 10/20/11 10:23 AM, Alex Russell wrote: On Thu, Oct 20, 2011 at 3:14 PM, Boris Zbarskybzbar...@mit.edu wrote: Right. So you need to vend an apparently-immutable Array, one which can only be changed by the browser. I think that could be accomplished in terms of Proxies. But it's still an Array type. I have no problem with Array being on the prototype chain or whatnot. But it's not an array in the sense that you can't do a bunch of things with it that people do with arrays. Though I don't know what slots you're talking about; the only sane JS implementation of live nodelists is as a proxy. There's no way to get the behaviors that browsers have for them otherwise. But it can be a Proxy to an *Array*, not to some weird non-Array type. Why does it matter what it's a proxy to? The whole point of being a proxy is that you can't tell what it's proxying. Case in point, in Gecko it's a proxy to something that's not a JS object at all and not even implementable in JS (because it uses internal engine information that's not available to JS). So what exactly do you want here other than nodelists having Array.prototype on their prototype chain, which is discussed elsewhere? And again, for static nodelists none of this applies; there's absolutely no reason I can think of to not make them arrays, unless you really want a .item() on them or unless you really think the length getter should be hookable. -Boris
Re: QSA, the problem with :scope, and naming
On 2011-10-20 16:23, Boris Zbarsky wrote: On 10/20/11 1:08 AM, Tab Atkins Jr. wrote: I disagree. It's extremely useful and natural for .find(:scope + div) to match sibling of the context node. I really don't think it is. If you want that, use document.find(:scope + div, context). Basically, the presence of :scope would turn off *all* the limitations That's a _really_ bizarre behavior. So in this case: foo.find(:scope + div, div) what all divs in the document would be found? Or is the oh, ignore the reference node except for matching :scope meant to only apply on a per-selector basis inside the selector list? That has its own issues, especially with performance (e.g. merging nodesets while preserving DOM order). As it was specified in the old draft of queryScopedSelector (which is the definition I start with if find/findAll get introduced), it was done on a per selector basis, so the above would be equivalent to: document.querySelector(:scope + div, :scope div, foo); -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 04:18, Alex Russell slightly...@google.com wrote: No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you is a documentation issue, not a question of type...unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. That is an ES violation. A non configurable, non writable data property is not allowed to change its value. var descr = Object.getOwnPropertyDescription(object, name); if (!descr.configurable !decsr.writable ('value' in descr)) { var value = descr.value; setInterval(function() { // Must never change assert(object[name] === value); }); } Therefore there is no such thing as an immutable live NodeList. There are ways around this. 1. Use a getter 2. Make it configurable -- erik
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 04:37, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-10-20 13:18, Alex Russell wrote: On Thu, Oct 20, 2011 at 12:05 PM, Lachlan Huntlachlan.h...@lachy.id.au wrote: We need NodeList separate from Array where they are live lists. No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you is a documentation issue, not a question of type...unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. The author cannot be allowed to directly modify a live list, as such it must be an immutable object from the script's perspective. Otherwise, things would get really complicated if this happened: var p = document.getElementsByTagName(p); p.reverse(); Just define [[Put]] to throw (by only having a getter). Since reverse is defined using [[Put]] things would work as expected. -- erik
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 04:49, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-10-20 13:35, Sean Hogan wrote: I wonder if anyone is relying on querySelectorAll() returning a StaticNodeList? Only if there are people out there using list.item(n) instead of list[n], or people extending the NodeList interface and expecting such methods to be available on the result. Though I suspect the former is very rare, and the latter doesn't work in all browsers. Both are rare but they do happen http://codesearch.google.com/#search/q=%5CsNodeList%5C.prototype%5C.(%5Cw%2B)%5Cs*=type=cs What is funny is that code search only found one instance of item being used directly after querySelectorAll(...). Of course, that search does not tell the whole story. http://codesearch.google.com/#SjGak5n5VAM/trunk/parsehtml_util.pyq=querySelectorAll%5C(%5B%5E)%5D%2B%5C)%5C.item%20-file:layoutteststype=csl=24 -- erik
Re: QSA, the problem with :scope, and naming
On 10/20/11 12:02 PM, Erik Arvidsson wrote: That is an ES violation. A non configurable, non writable data property is not allowed to change its value. It's not clear what that means in proxy-land; esp. since it's not clear whether proxies can even have non-configurable properties... or did that discussion come to a conclusion? -Boris
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 09:28, Boris Zbarsky bzbar...@mit.edu wrote: On 10/20/11 12:02 PM, Erik Arvidsson wrote: That is an ES violation. A non configurable, non writable data property is not allowed to change its value. It's not clear what that means in proxy-land; esp. since it's not clear whether proxies can even have non-configurable properties... or did that discussion come to a conclusion? We have a solution to that: http://wiki.ecmascript.org/doku.php?id=strawman:direct_proxies -- erik
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 3:46 AM, Alex Russell slightly...@google.com wrote: 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 group, for the following DOM: body id=3 div id=context foo=bar div id=1/div div class=class id=2/div div class=withChildren id=3div class=child id=4/div/div /div /body you'd get the following behavior: .findAll(div) // returns ids 1,2,3,4 .findAll() // returns the context node itself. This was indicated undesirable And, in follow-up mail, we talked extensively about why I didn't *really* mean just prepend the string ':scope '. I think empty string is a special case that we should treat as return an empty list. Sounds reasonable (sorry to bring this case up again, I just wanted to be comprehensive, though I failed at that, see below) .findAll(body :scope div) // returns nothing I suggest we treat :scope occurring after the first term of the selector as an error. So how should it work in the first term? I.e. what should .findAll(:scope) .findAll(div:scope) .findAll([foo=bar]:scope) .findAll(:scope div) .findAll(div:scope div) .findAll(div:scope #3) return? Also, why should :scope appearing in the first term be different from appearing in any other term? What is the use case? Do libraries have anything equivalent today? .findAll(#3) // returns id 3, but not the body node Correct. Assuming the query is document.find(#context).findAll(#3), which is what I think you mean for the root to be in these examples? Yup. / Jonas
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 3:50 AM, Alex Russell slightly...@google.com wrote: On Thu, Oct 20, 2011 at 6:55 AM, 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? 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. I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. It's insane that we even have a NodeList type which isn't a real array at all. Adding a parallel system when we could just fix the one we have (and preserve the value of a separate prototype for extension) is wonky to me. That said, I'd *also* support the ability to have some sort of decorator mechanism before return on .find() or a way to re-route the prototype of the returned Array. +heycam to debate this point. How would this new Array-type be different from an Array? Would it mutable (your answer below seems to indicate 'yes')? Would it allow inserting things that aren't Nodes? One of the use cases is being able to mutate the returned value. This is useful if you're for
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 7:23 AM, Alex Russell slightly...@google.com wrote: On Thu, Oct 20, 2011 at 3:14 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/20/11 7:18 AM, Alex Russell wrote: No we don't. The fact that there's someone else who has a handle to the list and can mutate it underneath you There is no sane way to mutate the list on the part of the browser if someone else is also messing with it, because the someone else can violate basic invariants the browser's behavior needs to maintain. Right. So you need to vend an apparently-immutable Array, one which can only be changed by the browser. I think that could be accomplished in terms of Proxies. But it's still an Array type. unless the argument is that the slots should be non-configurable, non-writable except by the browser that's also holding a ref to it. Yes. Though I don't know what slots you're talking about; the only sane JS implementation of live nodelists is as a proxy. There's no way to get the behaviors that browsers have for them otherwise. But it can be a Proxy to an *Array*, not to some weird non-Array type. Let's do the general discussion about how live and non-live NodeLists should behave in a separate thread. The immediate question here is how should the returned object from .findAll behave? Should it be mutable? Should you be able to insert non-Nodes into it? Should it have all of the functions of Array.prototype or just some subset? Should it have any additional functions? Since .findAll is a new function we have absolutely no constraints as far as how NodeLists behave, we can simply return something that isn't a NodeList. / Jonas
Re: before/after editaction
On Thu, Oct 13, 2011 at 7:20 PM, Ojan Vafai o...@chromium.org wrote: Overall I really like the proposal (both having the events and Jonas's addition to include them in the undo transaction). We'd fire the afterEditAction exactly everywhere we currently fire the input event though. Instead of adding two new events, could we instead add a beforeInput event as the beforeEditAction. Then add to both beforeInput and input an action property that is the edit action that was taken.* Yeah that'll be clean and neat way to support this. We probably need to add two properties though because some execCommand takes string value. The only downside I see to reusing input is that it might complicate Jonas's suggestion to include edits during the afterEditAction in the undo transaction. Although, my intuition is that there is *not* web content that depends on script executed during the input event not entering the undo stack. Right. I think we probably need to avoid firing them inside a transaction to maintain the backward compatibility. - Ryosuke
Proposal for a new Matrix API
Hello, Currently CSSMatrix and SVGMatrix has an immutable API. None of the method calls change the Matrix, instead, it creates a new Matrix with the changed value. It can be a problem specially when CSSMatrix is used together with WebGL. [1] We from WebKit are proposing a new Matrix API(simple as possible), see below or [2], where the standard methods change the matrix(in place operations) and additional methods (multipliedBy, scaledBy and so on) create a new Matrix as is done by CSSMatrix and SVGMatrix. The idea is make this class accepted where CSSMatrix and SVGMatrix is used and be the preferred class for all Matrix needs. [3] Any comments or suggestions? [1] http://www.khronos.org/webgl/public-mailing-list/archives/1006/msg00171.html [2] https://gist.github.com/1301236 [3] https://bugs.webkit.org/show_bug.cgi?id=50633 - IDL file for WebKitMatrix: module css { // Introduced in DOM Level ?: interface [ CanBeConstructed, JSCustomConstructor, ConstructorParameters=1, Constructor(in [Optional=CallWithNullValue] DOMString cssValue), ConstructorRaisesException, ] WebKitMatrix { // These attributes are simple aliases for certain elements of the 4x4 matrix attribute double a; // alias for m11 attribute double b; // alias for m12 attribute double c; // alias for m21 attribute double d; // alias for m22 attribute double e; // alias for m41 attribute double f; // alias for m42 attribute double m11; attribute double m12; attribute double m13; attribute double m14; attribute double m21; attribute double m22; attribute double m23; attribute double m24; attribute double m31; attribute double m32; attribute double m33; attribute double m34; attribute double m41; attribute double m42; attribute double m43; attribute double m44; void setMatrixValue(in [Optional=CallWithDefaultValue] DOMString string) raises (DOMException); // Copy the matrix elements for a single precision float point array void toArray(in Float32Array array); // Copy the matrix elements for a double precision float point array void toArray(in Float64Array array); // Multiply this matrix by secondMatrix, on the right (result = this * secondMatrix) [Immutable] WebKitMatrix multipliedBy(in [Optional=CallWithDefaultValue] WebKitMatrix secondMatrix); // Multiply itself by a secondMatrix, on the right (this = this * secondMatrix) void multiply(in [Optional=CallWithDefaultValue] WebKitMatrix secondMatrix); // Inverse this matrix. Throw an exception if the matrix is not invertible void inverse() raises (DOMException) // Return the inverse of this matrix. Throw an exception if the matrix is not invertible [Immutable] WebKitMatrix inversedBy() raises (DOMException); // Return this matrix translated by the passed values. // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations [Immutable] WebKitMatrix translatedBy(in [Optional=CallWithDefaultValue] double x, in [Optional=CallWithDefaultValue] double y, in [Optional=CallWithDefaultValue] double z); // Translate itself using the passed values. // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations void translate(in [Optional=CallWithDefaultValue] double x, in [Optional=CallWithDefaultValue] double y, in [Optional=CallWithDefaultValue] double z); // Returns this matrix scaled by the passed values. // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN // makes it the same as scaleX. This allows the 3D form to used for 2D operations [Immutable] WebKitMatrix scaledBy(in [Optional=CallWithDefaultValue] double scaleX, in [Optional=CallWithDefaultValue] double scaleY, in [Optional=CallWithDefaultValue] double scaleZ); // Scale itself using the passed values. // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN // makes it the same as scaleX. This allows the 3D form to used for 2D operations void scale(in [Optional=CallWithDefaultValue] double scaleX, in [Optional=CallWithDefaultValue] double scaleY, in [Optional=CallWithDefaultValue] double scaleZ); // Returns this matrix rotated by the passed values. // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX). // Otherwise use a rotation value of 0 for any passed
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 7:23 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/20/11 1:08 AM, Tab Atkins Jr. wrote: I disagree. It's extremely useful and natural for .find(:scope + div) to match sibling of the context node. I really don't think it is. If you want that, use document.find(:scope + div, context). Why do that, when the previous one is shorter and simpler, and unambiguous? The whole point is that we *know* the behavior I suggest is well-known and easy to use, because jQuery (and probably other selector engines?) does it already. I know for a fact that I've appreciated that behavior in my own coding. It would have been very annoying to me had I been forced to break my chaining just to select a sibling, when the exact same style works fine to select a child. It's intuitive and useful. The behavior is useful in jQuery because it lets me evaluate a selector, do some work to the matched elements, and then just continue the selector to grab more, regardless of what form the continuation takes. Forcing me to think about the continuation's form (and even worse, completely rearrange the call structure) is just mean. ^_^ Basically, the presence of :scope would turn off *all* the limitations That's a _really_ bizarre behavior. So in this case: foo.find(:scope + div, div) what all divs in the document would be found? Or is the oh, ignore the reference node except for matching :scope meant to only apply on a per-selector basis inside the selector list? That has its own issues, especially with performance (e.g. merging nodesets while preserving DOM order). Per-selector basis; we're not talking about naive string manipulation here. Your example would return divs that are descendants or an adjacent sibling of the scoping element. I don't really see the performance issues. If you use + or ~ off of :scope, you know for a fact that all the nodes come *after* any selectors that don't have :scope. If you use the subject indicator or the reference combinator that's not necessarily true, but those selectors will be slow already. Even then, sorting them into DOM order should be relatively easy: 1. Run the :scope-carrying selectors across the document together, automatically yielding a dom-ordered list. 2. Run the :scope-absent selectors together, automatically yielding a dom-ordered list. 3. Find where the scoping element would be inserted in the #1 list, and insert the entire #2 list there. There's no further interleaving that could cause trouble. ~TJ
[Bug 14527] New: cfgdfg dfg dfg dfg fgfdg sdftgf dhfghgdhfghfgdh fgh dfhdfhfghfghghhd
http://www.w3.org/Bugs/Public/show_bug.cgi?id=14527 Summary: cfgdfg dfg dfg dfg fgfdg sdftgf dhfghgdhfghfgdh fgh dfhdfhfghfghghhd Product: WebAppsWG Version: unspecified Platform: Other URL: http://www.whatwg.org/specs/web-apps/current-work/#top OS/Version: other Status: NEW Severity: normal Priority: P3 Component: WebSocket API (editor: Ian Hickson) AssignedTo: i...@hixie.ch ReportedBy: contribu...@whatwg.org QAContact: member-webapi-...@w3.org CC: m...@w3.org, public-webapps@w3.org Specification: http://www.w3.org/TR/2011/WD-websockets-20110929/ Multipage: http://www.whatwg.org/C#top Complete: http://www.whatwg.org/c#top Comment: cfgdfg dfg dfg dfg fgfdg sdftgf dhfghgdhfghfgdh fgh dfhdfhfghfghghhd Posted from: 190.165.72.99 User agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.23) Gecko/20110920 Firefox/3.6.23 -- 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 Thu, Oct 20, 2011 at 12:09 PM, Jonas Sicking jo...@sicking.cc wrote: Let's do the general discussion about how live and non-live NodeLists should behave in a separate thread. Yes, let's. ^_^ The immediate question here is how should the returned object from .findAll behave? Should it be mutable? Should you be able to insert non-Nodes into it? Should it have all of the functions of Array.prototype or just some subset? Should it have any additional functions? Since .findAll is a new function we have absolutely no constraints as far as how NodeLists behave, we can simply return something that isn't a NodeList. It should absolutely have all the Array functions. I know that I want to be able to slice, append, forEach, map, and reduce the list returned by .find. ~TJ
[Bug 14527] cfgdfg dfg dfg dfg fgfdg sdftgf dhfghgdhfghfgdh fgh dfhdfhfghfghghhd
http://www.w3.org/Bugs/Public/show_bug.cgi?id=14527 Ross Nicoll j...@jrn.me.uk changed: What|Removed |Added Status|NEW |RESOLVED CC||j...@jrn.me.uk Resolution||INVALID -- 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
* Alex Russell wrote: I strongly agree that it should be an Array *type*, but I think just returning a plain Array is the wrong resolution to our NodeList problem. WebIDL should specify that DOM List types *are* Array types. It's insane that we even have a NodeList type which isn't a real array at all. It is quite normal to consider lists and arrays to be different things. In Perl for instance you can use list operations like `grep` on arrays, but you cannot use array operations like `push` on lists. For JavaScript programmers it actually seems common to confuse the two, like with var node_list = document.getElementsByTagName('example'); for (var ix = 0; ix node_list.length; ++ix) node_list[ix].parentNode.removeChild(node_list[ix]); which would remove all the children if node_list was an array like any other. Pretending node lists are arrays in nomenclature would likely add to that. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: QSA, the problem with :scope, and naming
On 10/20/11 4:32 PM, Tab Atkins Jr. wrote: I don't really see the performance issues. If you use + or ~ off of :scope, you know for a fact that all the nodes come *after* any selectors that don't have :scope. Yes. 1. Run the :scope-carrying selectors across the document together, automatically yielding a dom-ordered list. 2. Run the :scope-absent selectors together, automatically yielding a dom-ordered list. 3. Find where the scoping element would be inserted in the #1 list, and insert the entire #2 list there. foo.find(:scope + div, :scope div) begs to differ. So does: foo.find(span :scope ~ div, span :scope div) (which is not quite as trivial to analyze). You could try to look at the combinator following the part(s) that have :scope, but that can get tricky. And worse yet, the current :scope proposals allow an arbitrary nodeset to be specified as matching :scope, at which point this whole thing is out the window. And yes, if you use a subject indicator then performance goes out the window too; you basically have to search the whole DOM. As long as you're ok with searching the whole DOM any time anything funny is happening, of course, there's no other performance issue here. But then I suspect this will be slow to start with -Boris
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 2:04 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 10/20/11 4:32 PM, Tab Atkins Jr. wrote: 1. Run the :scope-carrying selectors across the document together, automatically yielding a dom-ordered list. 2. Run the :scope-absent selectors together, automatically yielding a dom-ordered list. 3. Find where the scoping element would be inserted in the #1 list, and insert the entire #2 list there. foo.find(:scope + div, :scope div) begs to differ. Well, that would only cause a problem if there were also a :scope-absent selector in the list, like: foo.find(:scope + div, :scope div, span) If they *all* carry :scope, then you can just run them all over the whole tree and get the ordered set in the normal fashion. So does: foo.find(span :scope ~ div, span :scope div) (which is not quite as trivial to analyze). Same here. Yeah, it's possible to make it necessary to interleave the :scope-carrying and :scope-absent sets, if you run the two separately (perhaps because you can optimize the :scope-absent ones to fail when the search would escape the subtree). If you internally modify the :scope-absent selectors to start with :scope and a descendant combinator (in other words, do the add a unique id trick that selector engines do in this situation), and then run it with all the rest, though, that disappears. You might lose some possible optimization (based on knowing you only need to search a subtree), but not necessarily, and you're avoiding a potential slowdown from having to interleave. You could try to look at the combinator following the part(s) that have :scope, but that can get tricky. Yeah, I can see some possibilities, but they're not exhaustive. And worse yet, the current :scope proposals allow an arbitrary nodeset to be specified as matching :scope, at which point this whole thing is out the window. QSA allows that (or plans to?). Alex's find() proposal does not. The scoping element is solely the 'this' in .find. And yes, if you use a subject indicator then performance goes out the window too; you basically have to search the whole DOM. As long as you're ok with searching the whole DOM any time anything funny is happening, of course, there's no other performance issue here. But then I suspect this will be slow to start with It was good enough for jQuery in the pre-QSA days, and it's still good enough for jQuery now when it can't use QSA, I don't see why it's not good enough for the rest of us. We can do at least as good, and probably still better. ~TJ
Re: QSA, the problem with :scope, and naming
On 2011-10-20 22:32, Tab Atkins Jr. wrote: On Thu, Oct 20, 2011 at 7:23 AM, Boris Zbarskybzbar...@mit.edu wrote: On 10/20/11 1:08 AM, Tab Atkins Jr. wrote: Basically, the presence of :scope would turn off *all* the limitations That's a _really_ bizarre behavior. So in this case: foo.find(:scope + div, div) what all divs in the document would be found? Or is the oh, ignore the reference node except for matching :scope meant to only apply on a per-selector basis inside the selector list? That has its own issues, especially with performance (e.g. merging nodesets while preserving DOM order). Per-selector basis; we're not talking about naive string manipulation here. Your example would return divs that are descendants or an adjacent sibling of the scoping element. Not necessarily. It depends what exactly it means for a selector to contain :scope for determining whether or not to enable the implied :scope behaviour. Consider: foo.find(:not(:scope)); If that is deemed to contain :scope and turn off the prepending of scope, making it equivalent to: document.querySelectorAll(:not(:scope), foo); Then it matches every element in the document except the context node. Otherwise, if it we decide that containing :scope means that it contains a :scope selector that is not within a functional notation pseudo-element, then it would prepend :scope, equivalent to: document.querySelectorAll(:scope :not(:scope), foo) Then it matches all descendants of the context element. In the latter case, then it would only ever be possible for matches to be found as descendants, siblings or descendants of siblings of the context element. That would even be true in cases like: foo.find(section:scope+div, div, ~p span, .x :scopeh1+span) With the selector pre-processing, that selector becomes section:scope+div, :scope div, :scope~p span, .x :scopeh1+span -- Lachlan Hunt - Opera Software http://lachy.id.au/ http://www.opera.com/
Re: QSA, the problem with :scope, and naming
On Thu, Oct 20, 2011 at 2:33 PM, Lachlan Hunt lachlan.h...@lachy.id.au wrote: On 2011-10-20 22:32, Tab Atkins Jr. wrote: On Thu, Oct 20, 2011 at 7:23 AM, Boris Zbarskybzbar...@mit.edu wrote: On 10/20/11 1:08 AM, Tab Atkins Jr. wrote: Basically, the presence of :scope would turn off *all* the limitations That's a _really_ bizarre behavior. So in this case: foo.find(:scope + div, div) what all divs in the document would be found? Or is the oh, ignore the reference node except for matching :scope meant to only apply on a per-selector basis inside the selector list? That has its own issues, especially with performance (e.g. merging nodesets while preserving DOM order). Per-selector basis; we're not talking about naive string manipulation here. Your example would return divs that are descendants or an adjacent sibling of the scoping element. Not necessarily. It depends what exactly it means for a selector to contain :scope for determining whether or not to enable the implied :scope behaviour. Consider: foo.find(:not(:scope)); If that is deemed to contain :scope and turn off the prepending of scope, making it equivalent to: document.querySelectorAll(:not(:scope), foo); Then it matches every element in the document except the context node. This seems perfectly fine, since if you just want all the elements *underneath* the scoping element, you can instead do the much simpler: foo.find(*) Otherwise, if it we decide that containing :scope means that it contains a :scope selector that is not within a functional notation pseudo-element, then it would prepend :scope, equivalent to: document.querySelectorAll(:scope :not(:scope), foo) Then it matches all descendants of the context element. This prevents us from doing things like :matches(:scope, #foo), which seems potentially useful. (Plus, :matches(X) should always be equivalent to just X, possibly modulo specificity differences.) In the latter case, then it would only ever be possible for matches to be found as descendants, siblings or descendants of siblings of the context element. That would even be true in cases like: foo.find(section:scope+div, div, ~p span, .x :scopeh1+span) With the selector pre-processing, that selector becomes section:scope+div, :scope div, :scope~p span, .x :scopeh1+span Unless you use the reference combinator or the subject indicator, or something else we come up with in the future that lets us do more complicated searching. ~TJ
Re: QSA, the problem with :scope, and naming
On 10/20/11 5:15 PM, Tab Atkins Jr. wrote: If they *all* carry :scope, then you can just run them all over the whole tree and get the ordered set in the normal fashion. You can just prepend :scope to the ones missing it and run them over the whole tree too. But that means that now you're doing work proportional to the size of your whole DOM, not the subtree rooted at the context element, which is a pretty big difference. And worse yet, the current :scope proposals allow an arbitrary nodeset to be specified as matching :scope, at which point this whole thing is out the window. QSA allows that (or plans to?). Alex's find() proposal does not. The scoping element is solely the 'this' in .find. I was assuming we were discussing find() in preference to the QSA extensions. Maybe I was confused? It was good enough for jQuery in the pre-QSA days, and it's still good enough for jQuery now when it can't use QSA, I don't see why it's not good enough for the rest of us. jQuery takes some shortcuts we can't take (note the getElementById comments elsewhere in this thread). Maybe it'll be ok. Maybe not. I'd rather not paint ourselves into the not corner if we can avoid it -Boris
Re: before/after editaction
On Thu, Oct 20, 2011 at 6:35 PM, Ojan Vafai o...@chromium.org wrote: On Thu, Oct 20, 2011 at 1:06 PM, Ryosuke Niwa rn...@webkit.org wrote: On Thu, Oct 13, 2011 at 7:20 PM, Ojan Vafai o...@chromium.org wrote: Overall I really like the proposal (both having the events and Jonas's addition to include them in the undo transaction). We'd fire the afterEditAction exactly everywhere we currently fire the input event though. Instead of adding two new events, could we instead add a beforeInput event as the beforeEditAction. Then add to both beforeInput and input an action property that is the edit action that was taken.* Yeah that'll be clean and neat way to support this. We probably need to add two properties though because some execCommand takes string value. The only downside I see to reusing input is that it might complicate Jonas's suggestion to include edits during the afterEditAction in the undo transaction. Although, my intuition is that there is *not* web content that depends on script executed during the input event not entering the undo stack. Right. I think we probably need to avoid firing them inside a transaction to maintain the backward compatibility. I really don't expect this to cause compat problems. I think we can move forward with whichever API we think is best assuming no compat problems and revise it should we hit compat problems once vendors start implementing it. I don't think we can make such an assumption. People mutate DOM on input event all the time: http://codesearch.google.com/#search/q=%20oninput=type=cs Including any DOM mutations in the on-going transaction would mean that UA will end up trying to revert those changes since the entire document shares the one undo scope by default, and may end up mutation DOM in unexpected ways. - Ryosuke
Re: before/after editaction
On Thu, Oct 20, 2011 at 6:57 PM, Ryosuke Niwa rn...@webkit.org wrote: I don't think we can make such an assumption. People mutate DOM on input event all the time: http://codesearch.google.com/#search/q=%20oninput=type=cs Including any DOM mutations in the on-going transaction would mean that UA will end up trying to revert those changes since the entire document shares the one undo scope by default, and may end up mutation DOM in unexpected ways. I'll add that, most significantly, when reverting DOM changes made in the input event listener fails, the UA may end up aborting the undo/redo process before even get to revert the actual DOM changes made by the user editing action or execCommand. - Ryosuke
[Bug 14214] missing definition of Transferable
http://www.w3.org/Bugs/Public/show_bug.cgi?id=14214 Ian 'Hixie' Hickson i...@hixie.ch changed: What|Removed |Added Status|ASSIGNED|RESOLVED Resolution||WONTFIX Status Whiteboard|K | --- Comment #2 from Ian 'Hixie' Hickson i...@hixie.ch 2011-10-21 02:54:49 UTC --- There's already a reference to the HTML spec. It's assumed that the reader is familiar with the basic types defined in that spec. -- 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.
[Bug 14144] Adding link to resolve the URL
http://www.w3.org/Bugs/Public/show_bug.cgi?id=14144 Ian 'Hixie' Hickson i...@hixie.ch changed: What|Removed |Added Status|ASSIGNED|RESOLVED Resolution||FIXED Status Whiteboard|K | -- 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.