[Prototype-core] Hi Dears,
I want to chat with you on google talk,. I love you, --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Hi Dears,
I want to chat with you on google talk,. I love you, --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
Hey folks, Weighing in briefly (being hammered at work and at home, and not in that fun way). Great stuff so far! Thoughts/opinions/questions: 1. IMHO, $$() should _always_ return a list/array/whatever, even if there's only one element; it should never return the NodeWrapper itself. Two reasons: A) Having a function that returns a list in some situations and a single element in another situations just means that every use of it has to check what it got back, leading to unnecessarily-verbose code and confusion on the part of users. If people are doing things like $$(#thingy), tell them to use $(), that's what it's for. :-) If there's a really really good reason they're using $$() (for instance, they don't know what the selector is, it's supplied from elsewhere), well, then they should always be expecting to get back a list. B) That's what it does now. I don't think there would be confusion with things like $$ (..).getValue() here. Keep in mind users do use the equiv of $$('#myId') and that in those cases you are expecting 1 result so the desired behavior of a readAttribute, or getValue or anything getting a property is to return from the only matched item. True. We could reduce ambiguity by having some kind of a generic rule - e.g. all accessor methods always act on the first item. This should be fine, as long as there are no (or not many) exceptions. 2. FWIW, it seems to me that calling an accessor on a list should return a list of the accessor results for each list element. Always. Similarly, calling a setter on the list [e.g., $$ ('.blarg').update('yada')] should call the setter on all list elements. 1) NodeWrapper always exposes a public `source` property, which is a reference to a wrapped element: 3. Still don't like source. That word is just way too overloaded, and again, it's as much a target (e.g., of an update() call) as a source. raw is the best general term I've thought of, but I'm not married to it. Whatever we use should be *short* (so not wrappedThingamajig) and as clear as feasible. Maybe we should give up on the generic term (I *know* it was my idea, but...) and just use something meaningful for each wrapper, e.g. NodeWrapper.node, ListWrapper.list, etc. Keep 'em short, document 'em, and if people forget what the property for the wrapped thingy inside a NodeListWrapper is, too bad, at least the terms are short and clear. 4. get() and set() methods: Great to have them, but I think it's important that we not expect/require that people _use_ them. We're not, right? I don't want to make a function call to access tagName, I'll want to use wrapper.source.tagName (or wrapper.raw.tagName) without the wrapper getting confused somehow. 5. How will the list wrapper handle indexing into the list? E.g.: var items; var n; items = $$('div.item'); for (n = 0; n items.length; ++n) { items[n].update('This is item ' + n); } I'm not aware of a standard, widely-supported JavaScript feature that lets us define the subscript operator, so I'm guessing the above is out. Again I hate to introduce a function call for simple access [e.g., list.item(n), a'la Microsoft collections], so would I go to the underlying raw/source? 6. Question on $$(): I think the idea so far is that it returns a NodeListWrapper. I'm guessing that that's a list of NodeWrappers around the results of the query, right? So I could reliably rewrite my code above like this (I'll use 'source' rather than 'raw' here): var items; var list; var n; items = $$('div.item'); list = items.source; for (n = 0; n list.length; ++n) { list[n].update('This is item ' + n); } ...because although I'm accessing the raw list, it contains wrapped nodes. Is that the idea? -- T.J. Crowder tj / crowder software / com On Aug 21, 6:37 am, kangax [EMAIL PROTECTED] wrote: On Aug 21, 12:15 am, Ken Snyder [EMAIL PROTECTED] wrote: ... I forked prototype, and started working on NodeWrapper/NodeListWrapper -http://github.com/kangax/prototype/tree/master/src/element.js Accompanying tests are there as well (although the test suite is far from being complete). -- kangax Exciting to see in code! What about adding caching instances and maybe even using a double-duty constructor instead of Class.create? See what I mean below. - Ken Snyder Prototype.Element = function(element) { if (this instanceof Prototype.Element) { // constructor element.__prototypeWrapper = this; this.raw = element; } else { // getInstance function // allow element to be string, dom node, or Prototype.Element instance element = (typeof element === 'string' ? document.getElementById(element) : element); if (element instanceof Prototype.Element) { return element; } if (element element.__prototypeWrapper) { return element.__prototypeWrapper; } else { return new
[Prototype-core] Re: Element wrapper draft notes
On Aug 21, 7:13 am, T.J. Crowder [EMAIL PROTECTED] wrote: Hey folks, Weighing in briefly (being hammered at work and at home, and not in that fun way). Great stuff so far! Thoughts/opinions/questions: 1. IMHO, $$() should _always_ return a list/array/whatever, even if there's only one element; it should never return the NodeWrapper itself. Two reasons: A) Having a function that returns a list in some situations and a single element in another situations just means that every use of it has to check what it got back, leading to unnecessarily-verbose code and confusion on the part of users. If people are doing things like $$(#thingy), tell them to use $(), that's what it's for. :-) If there's a really really good reason they're using $$() (for instance, they don't know what the selector is, it's supplied from elsewhere), well, then they should always be expecting to get back a list. B) That's what it does now. I don't think there would be confusion with things like $$ (..).getValue() here. Keep in mind users do use the equiv of $$('#myId') and that in those cases you are expecting 1 result so the desired behavior of a readAttribute, or getValue or anything getting a property is to return from the only matched item. True. We could reduce ambiguity by having some kind of a generic rule - e.g. all accessor methods always act on the first item. This should be fine, as long as there are no (or not many) exceptions. 2. FWIW, it seems to me that calling an accessor on a list should return a list of the accessor results for each list element. Always. Similarly, calling a setter on the list [e.g., $$ ('.blarg').update('yada')] should call the setter on all list elements. This is tricky : ) On one hand, having accessor act on all elements seems most intuitive and consistent with the current API. On the other hand, I can clearly see a case when getting first value is much more convenient. Considering that NodeList items can not be accessed via brackets, wouldn't we end up with a somewhat verbose syntax? $$('#sidebar #expandAll')[0].observe('click', function(){}); becomes: $W('#sidebar #expandAll').source[0].observe('click', function(){}); Perhaps, if we give NodeList a `first` method, it will make things a little less cryptic: $W('#sidebar #expandAll').first().observe('click', function(){}); 1) NodeWrapper always exposes a public `source` property, which is a reference to a wrapped element: 3. Still don't like source. That word is just way too overloaded, and again, it's as much a target (e.g., of an update() call) as a source. raw is the best general term I've thought of, but I'm not married to it. Whatever we use should be *short* (so not wrappedThingamajig) and as clear as feasible. Maybe we should give I really like `source` but let's keep the naming aside for now : ) up on the generic term (I *know* it was my idea, but...) and just use something meaningful for each wrapper, e.g. NodeWrapper.node, ListWrapper.list, etc. Keep 'em short, document 'em, and if people forget what the property for the wrapped thingy inside a NodeListWrapper is, too bad, at least the terms are short and clear. 4. get() and set() methods: Great to have them, but I think it's important that we not expect/require that people _use_ them. We're not, right? I don't want to make a function call to access tagName, I'll want to use wrapper.source.tagName (or wrapper.raw.tagName) without the wrapper getting confused somehow. Sure. We should recommend using them wisely and whenever it makes sense. 5. How will the list wrapper handle indexing into the list? E.g.: var items; var n; items = $$('div.item'); for (n = 0; n items.length; ++n) { items[n].update('This is item ' + n); } I'm not aware of a standard, widely-supported JavaScript feature that lets us define the subscript operator, so I'm guessing the above is out. Again I hate to introduce a function call for simple access [e.g., list.item(n), a'la Microsoft collections], so would I go to the underlying raw/source? each always passes index as a second argument to iterator function: $$('div.item').each(function(node, n) { node.update('This is item ' + n); }); 6. Question on $$(): I think the idea so far is that it returns a NodeListWrapper. I'm guessing that that's a list of NodeWrappers around the results of the query, right? So I could reliably rewrite my code above like this (I'll use 'source' rather than 'raw' here): var items; var list; var n; items = $$('div.item'); list = items.source; for (n = 0; n list.length; ++n) { list[n].update('This is item ' + n); } ...because although I'm accessing the raw list, it contains wrapped nodes. Is that the idea? Yep, `source` of NodeList is an array of `Node`s. -- kangax --~--~-~--~~~---~--~~ You
[Prototype-core] Re: Element wrapper draft notes
@T. J. Crowder take some time to look at the jQuery source, it might help with the wrapper discussion. I was not suggesting that $$() return a list in some cases and a single item in others. I was saying that getter/setter methods would execute on the first matched item. In jQuery (jQuery syntax): $('#footer') - returns a jQuery instance (in our case it would be a NodeListWrapper); If you example the object it looks like: NodeListWrapper[0] - div#footer (the html element) NodeListWrapper.length - 1 NodeListWrapper.observe - method NodeListWrapper.toggle - method NodeListWrapper.each - method NodeListWrapper._each - method NodeListWrapper.show - method NodeListWrapper.getValue - method NodeListWrapper.update - method the jQuery object and thus our NodeListWrapper will mimic an array, it has a length, and index properties. When you call a getter method then it executes on the first matched item NodeListWrapper.getHeight - execute on the first matched element and not iterate over the list NodeListWrapper.getStyle - execute on ... NodeListWrapper.getDimensions() - ... so $$W('#id').getHeight() - is the same as - $$W('#id') [0].getHeight(); $$W('#id')[0] is an element in jQuery but if we wrap ours in a NodeWrapper too then $$W('#id')[0] would be the NodeWrapper $$W('#id')[0] instanceof NodeWrapper would be true. $$W('#id')[0].raw() would be the element, now we can talk about if thats too many wrappers or what not, but I think the approach of $$(selector)method is a good one. Now we could do this: NodeWrapper.raw() - gives you the element; NodeWrapper.raw(element) - sets the element; and the internal var _raw is private; so that by the rules above if Prototype were modified $$W - $$, $W - $ $('id').raw() - the element $$('#id').raw() - the element (its a getter/setter so it executes on the first matched) $$('.panels').hide(); $$('.panels:first').hide(); $('myPanel).raw().tagName $('myPanel).get('tagName'); There would be no internal raw item for the NodeListWrapper because like the jQuery object its items are part of its indexed properties. - JDD --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
On Aug 21, 9:21 am, T.J. Crowder [EMAIL PROTECTED] wrote: Hiya, 2. FWIW, it seems to me that calling an accessor on a list should return a list of the accessor results for each list element. Always. ... This is tricky : ) On one hand, having accessor act on all elements seems most intuitive and consistent with the current API. On the other hand, I can clearly see a case when getting first value is much more convenient. Considering that NodeList items can not be accessed via brackets, wouldn't we end up with a somewhat verbose syntax? $$('#sidebar #expandAll')[0].observe('click', function(){}); becomes: $W('#sidebar #expandAll').source[0].observe('click', function(){}); Maybe I'm not understanding the example; I'm not a CSS guru by any means. To me that looks like you're selecting an element with the ID 'expandAll' if and only if it exists within an element with the ID Correct. 'sidebar'. If so, that seems like quite an edge case to me (wouldn't you know whether it was inside the sidebar?), but again, I think I probably just don't get it. This happens anytime one needs to reference an element without id: $$('[name='+prop+']')[0]; // get element by name $$('tbody tr:first-child')[0]; // get first row of a table $$('img[src^=data:image]')[0]; // get image with specified src attribute etc. Perhaps, if we give NodeList a `first` method, it will make things a little less cryptic: That sounds good. But separately, if we think it's common to need to select a single element on the basis of a CSS selector, I'd suggest an explicit means of doing that (e.g., a separate function -- $$First() comes to mind) that returns a NodeWrapper (or undefined, of course) and is optimized for that operation -- specifically, it stops as soon as it's found one. More readable, perhaps slightly faster. Another global function? ; ) 3. Still don't like source. That word is just way too overloaded, ... I really like `source` but let's keep the naming aside for now : ) No problem. But you know I'll come back to it. :-) I know : ) 4. get() and set() methods: Great to have them, but I think it's important that we not expect/require that people _use_ them. ... Sure. We should recommend using them wisely and whenever it makes sense. Good good, just checking. 5. How will the list wrapper handle indexing into the list? E.g.: var items; var n; items = $$('div.item'); for (n = 0; n items.length; ++n) { items[n].update('This is item ' + n); } ... each always passes index as a second argument to iterator function: I don't use each() unless I have a really good reason for the added overhead or I know I'm dealing with so few elements that the added overhead (dramatic, in IE's case) doesn't matter. I don't want people to think I'm dissing each() and I don't want to start an each() conversation. But it seems like people get so caught up in the coolness of this stuff they they forget that function calls have a cost, inline closures have an even higher cost. each() is really cool and I love it, love the idea of it, love the expressiveness of it. And implementations are making progress. But for now my default mode will continue to be boring old-fashioned for/next loops (backward if it doesn't matter and time is *really* of the essence) barring a strong reason to do something else. JS1.7 introduces iterators but as of now they are of little use (in a web environment) : / If `each` is out of the question, then yes, your previous example should be fine. 6. Question on $$(): I think the idea so far is that it returns a NodeListWrapper. I'm guessing that that's a list of NodeWrappers around the results of the query, right? ... Yep, `source` of NodeList is an array of `Node`s. Nodes? Or NodeWrappers? NodeWrappers. -- kangax --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
@JDD: Thanks. I understood your suggsetion about the accessors, I thought I'd also (separately) seen a suggestion that $$() return a single wrapped element when it only finds one, but I'm not immediately finding what it was that made me thing that. Sounds like we're all on the same page wrt always returning a list. Apologies for muddying the waters there. I disagree on the list applying accessors to only the first element. From an API perspective I just don't see that it makes sense. I'd much rather see a first() method or property, or better yet (as I suggested to kangax) an explicit means of saying give me the first (and only the first) element that matches this CSS spec). If I see the code list.highlight(), I'm going to expect the highlight method to be applied to the list, not to the first entry on the list. Now we could do this: NodeWrapper.raw() - gives you the element; NodeWrapper.raw(element) - sets the element; and the internal var _raw is private; We'll be using the raw underlying item a LOT, the last thing we want to do is make accessing it a function call. There would be no internal raw item for the NodeListWrapper because like the jQuery object its items are part of its indexed properties. If it's not literally a wrapper, if it's a replacement, that's great and it's certainly the simplest solution. But we keep calling it a wrapper, which is the only reason for the question about indexed access. -- T.J. Crowder tj / crowder software / On Aug 21, 3:44 pm, John-David Dalton [EMAIL PROTECTED] wrote: @T. J. Crowder take some time to look at the jQuery source, it might help with the wrapper discussion. I was not suggesting that $$() return a list in some cases and a single item in others. I was saying that getter/setter methods would execute on the first matched item. In jQuery (jQuery syntax): $('#footer') - returns a jQuery instance (in our case it would be a NodeListWrapper); If you example the object it looks like: NodeListWrapper[0] - div#footer (the html element) NodeListWrapper.length - 1 NodeListWrapper.observe - method NodeListWrapper.toggle - method NodeListWrapper.each - method NodeListWrapper._each - method NodeListWrapper.show - method NodeListWrapper.getValue - method NodeListWrapper.update - method the jQuery object and thus our NodeListWrapper will mimic an array, it has a length, and index properties. When you call a getter method then it executes on the first matched item NodeListWrapper.getHeight - execute on the first matched element and not iterate over the list NodeListWrapper.getStyle - execute on ... NodeListWrapper.getDimensions() - ... so $$W('#id').getHeight() - is the same as - $$W('#id') [0].getHeight(); $$W('#id')[0] is an element in jQuery but if we wrap ours in a NodeWrapper too then $$W('#id')[0] would be the NodeWrapper $$W('#id')[0] instanceof NodeWrapper would be true. $$W('#id')[0].raw() would be the element, now we can talk about if thats too many wrappers or what not, but I think the approach of $$(selector)method is a good one. Now we could do this: NodeWrapper.raw() - gives you the element; NodeWrapper.raw(element) - sets the element; and the internal var _raw is private; so that by the rules above if Prototype were modified $$W - $$, $W - $ $('id').raw() - the element $$('#id').raw() - the element (its a getter/setter so it executes on the first matched) $$('.panels').hide(); $$('.panels:first').hide(); $('myPanel).raw().tagName $('myPanel).get('tagName'); There would be no internal raw item for the NodeListWrapper because like the jQuery object its items are part of its indexed properties. - JDD --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
I like the wrapper tack (same way Ext does it). .raw doesn't sound intuitive to me though. Why not just use .dom for the underlying element (also like Ext)? Or .el? .raw just doesn't make for a beautiful API, IMHO :) And no, don't make it a function call. On Thu, Aug 21, 2008 at 10:41 AM, T.J. Crowder [EMAIL PROTECTED]wrote: @JDD: Thanks. I understood your suggsetion about the accessors, I thought I'd also (separately) seen a suggestion that $$() return a single wrapped element when it only finds one, but I'm not immediately finding what it was that made me thing that. Sounds like we're all on the same page wrt always returning a list. Apologies for muddying the waters there. I disagree on the list applying accessors to only the first element. From an API perspective I just don't see that it makes sense. I'd much rather see a first() method or property, or better yet (as I suggested to kangax) an explicit means of saying give me the first (and only the first) element that matches this CSS spec). If I see the code list.highlight(), I'm going to expect the highlight method to be applied to the list, not to the first entry on the list. Now we could do this: NodeWrapper.raw() - gives you the element; NodeWrapper.raw(element) - sets the element; and the internal var _raw is private; We'll be using the raw underlying item a LOT, the last thing we want to do is make accessing it a function call. There would be no internal raw item for the NodeListWrapper because like the jQuery object its items are part of its indexed properties. If it's not literally a wrapper, if it's a replacement, that's great and it's certainly the simplest solution. But we keep calling it a wrapper, which is the only reason for the question about indexed access. -- T.J. Crowder tj / crowder software / On Aug 21, 3:44 pm, John-David Dalton [EMAIL PROTECTED] wrote: @T. J. Crowder take some time to look at the jQuery source, it might help with the wrapper discussion. I was not suggesting that $$() return a list in some cases and a single item in others. I was saying that getter/setter methods would execute on the first matched item. In jQuery (jQuery syntax): $('#footer') - returns a jQuery instance (in our case it would be a NodeListWrapper); If you example the object it looks like: NodeListWrapper[0] - div#footer (the html element) NodeListWrapper.length - 1 NodeListWrapper.observe - method NodeListWrapper.toggle - method NodeListWrapper.each - method NodeListWrapper._each - method NodeListWrapper.show - method NodeListWrapper.getValue - method NodeListWrapper.update - method the jQuery object and thus our NodeListWrapper will mimic an array, it has a length, and index properties. When you call a getter method then it executes on the first matched item NodeListWrapper.getHeight - execute on the first matched element and not iterate over the list NodeListWrapper.getStyle - execute on ... NodeListWrapper.getDimensions() - ... so $$W('#id').getHeight() - is the same as - $$W('#id') [0].getHeight(); $$W('#id')[0] is an element in jQuery but if we wrap ours in a NodeWrapper too then $$W('#id')[0] would be the NodeWrapper $$W('#id')[0] instanceof NodeWrapper would be true. $$W('#id')[0].raw() would be the element, now we can talk about if thats too many wrappers or what not, but I think the approach of $$(selector)method is a good one. Now we could do this: NodeWrapper.raw() - gives you the element; NodeWrapper.raw(element) - sets the element; and the internal var _raw is private; so that by the rules above if Prototype were modified $$W - $$, $W - $ $('id').raw() - the element $$('#id').raw() - the element (its a getter/setter so it executes on the first matched) $$('.panels').hide(); $$('.panels:first').hide(); $('myPanel).raw().tagName $('myPanel).get('tagName'); There would be no internal raw item for the NodeListWrapper because like the jQuery object its items are part of its indexed properties. - JDD -- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- WebWidgetry.com / MashupStudio.com Future Home of the World's First Complete Web Platform -- Inquire: 1-920-574-2218 Blog: http://www.someElement.com LinkedIn Profile: http://www.linkedin.com/in/ryangahl --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
I disagree on the list applying accessors to only the first element. From an API perspective I just don't see that it makes sense. I'd much rather see a first() method or property, or better yet (as I suggested to kangax) an explicit means of saying give me the first (and only the first) element that matches this CSS spec). If I see the code list.highlight(), I'm going to expect the highlight method to be applied to the list, not to the first entry on the list. I agree with that disagreement. Although it shortens up the syntax, to me it's counter intuitive for a list to operate on the first element for item related functions. Darrin --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
This happens anytime one needs to reference an element without id: $$('[name='+prop+']')[0]; // get element by name $$('tbody tr:first-child')[0]; // get first row of a table $$('img[src^=data:image]')[0]; // get image with specified src attribute Sure, that makes much more sense to me than '#sidebar #expandAll'. ...But separately, if we think it's common to need to select a single element on the basis of a CSS selector, I'd suggest an explicit means of doing that (e.g., a separate function -- $$First() comes to mind)... Another global function? ; ) Nah, we're namepsacing it, remember? ;-) Seriously, though, if it's common to need to select a single element not by ID and act on it, let's make that an explicit and efficient thing, rather than bending the API of the node list thingy to suit the case of only *really* wanting the first element. Doesn't matter (much) whether it's another top-level function (although please, not literally with the name $ $First() -- blech) or an extension to something else (although I'd leave $() -- which is otherwise very tempting -- lean and mean), whatever. But using $$() to go get a single element seems wasteful to me, it'll continue its recursive descent even after it has what you want, and then it goes and puts a list around it, all to be thrown away because you're just going to use the first element anyway. FWIW. -- T.J. :-) On Aug 21, 3:45 pm, kangax [EMAIL PROTECTED] wrote: On Aug 21, 9:21 am, T.J. Crowder [EMAIL PROTECTED] wrote: Hiya, 2. FWIW, it seems to me that calling an accessor on a list should return a list of the accessor results for each list element. Always. ... This is tricky : ) On one hand, having accessor act on all elements seems most intuitive and consistent with the current API. On the other hand, I can clearly see a case when getting first value is much more convenient. Considering that NodeList items can not be accessed via brackets, wouldn't we end up with a somewhat verbose syntax? $$('#sidebar #expandAll')[0].observe('click', function(){}); becomes: $W('#sidebar #expandAll').source[0].observe('click', function(){}); Maybe I'm not understanding the example; I'm not a CSS guru by any means. To me that looks like you're selecting an element with the ID 'expandAll' if and only if it exists within an element with the ID Correct. 'sidebar'. If so, that seems like quite an edge case to me (wouldn't you know whether it was inside the sidebar?), but again, I think I probably just don't get it. This happens anytime one needs to reference an element without id: $$('[name='+prop+']')[0]; // get element by name $$('tbody tr:first-child')[0]; // get first row of a table $$('img[src^=data:image]')[0]; // get image with specified src attribute etc. Perhaps, if we give NodeList a `first` method, it will make things a little less cryptic: That sounds good. But separately, if we think it's common to need to select a single element on the basis of a CSS selector, I'd suggest an explicit means of doing that (e.g., a separate function -- $$First() comes to mind) that returns a NodeWrapper (or undefined, of course) and is optimized for that operation -- specifically, it stops as soon as it's found one. More readable, perhaps slightly faster. Another global function? ; ) 3. Still don't like source. That word is just way too overloaded, ... I really like `source` but let's keep the naming aside for now : ) No problem. But you know I'll come back to it. :-) I know : ) 4. get() and set() methods: Great to have them, but I think it's important that we not expect/require that people _use_ them. ... Sure. We should recommend using them wisely and whenever it makes sense. Good good, just checking. 5. How will the list wrapper handle indexing into the list? E.g.: var items; var n; items = $$('div.item'); for (n = 0; n items.length; ++n) { items[n].update('This is item ' + n); } ... each always passes index as a second argument to iterator function: I don't use each() unless I have a really good reason for the added overhead or I know I'm dealing with so few elements that the added overhead (dramatic, in IE's case) doesn't matter. I don't want people to think I'm dissing each() and I don't want to start an each() conversation. But it seems like people get so caught up in the coolness of this stuff they they forget that function calls have a cost, inline closures have an even higher cost. each() is really cool and I love it, love the idea of it, love the expressiveness of it. And implementations are making progress. But for now my default mode will continue to be boring old-fashioned for/next loops (backward if it doesn't matter and time is *really* of the essence) barring a strong reason to do something
[Prototype-core] Re: Element wrapper draft notes
On Aug 21, 10:44 am, John-David Dalton [EMAIL PROTECTED] wrote: @T. J. Crowder take some time to look at the jQuery source, it might help with the wrapper discussion. I was not suggesting that $$() return a list in some cases and a single item in others. I was saying that getter/setter methods would execute on the first matched item. In jQuery (jQuery syntax): $('#footer') - returns a jQuery instance (in our case it would be a NodeListWrapper); If you example the object it looks like: NodeListWrapper[0] - div#footer (the html element) NodeListWrapper.length - 1 NodeListWrapper.observe - method NodeListWrapper.toggle - method NodeListWrapper.each - method NodeListWrapper._each - method NodeListWrapper.show - method NodeListWrapper.getValue - method NodeListWrapper.update - method the jQuery object and thus our NodeListWrapper will mimic an array, it has a length, and index properties. Are we going to make `ListWrapper` pretend it's an array? I agree that it's convenient to be able to access single elements of a list with brackets, but wouldn't exposing all these properties break the integrity/abstraction of a `ListWrapper`? jQuery fills its instance with such properties and seems to adjust `length` accordingly, but it's far from being an array: var j = $('div'); j.length; // 14 j[14] = 'foo'; j.length; // 14 (not 15) - no magic length behavior obviously j.push; // undefined j.pop; // undefined j.concat; // undefined I think the only array-like method they have is `slice`. -- kangax --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
// if source is a method $$(css).source() - equiv $$(css)[0].source() - equiv $$(css).first().source() - equiv you could always cache it var source = $$(css).source(); // an array of sources $$(css).invoke('source'); // OR $$(css).each($$.source); //notice static $$.source method $$(css)._each($$.source); // faster than all of them :P if source is a property //no soup for $$().method $$(css)[0].source $$(css).first().source $$(css).pluck('source'); //get height of first matched item (equivs) $$(css).first().getHeight(), $$(css)[0].getHeight(), and $$(css).getHeight() are equivs. // array of heights (equivs) $$(css).invoke('getHeight'); $$(css).each($$.getHeight); $$(css)._each($$.getHeight); //setters $$(css).update(...); //sets all matched items $$(css).setStyle(...) //sets all matched items $$(css).addClassName(...) // does it to all matched items $$(css).show().observer('click', ...); // shows all matches and attached an onclick observer to all of them. // get element by id $(id).hide(); $(id).source() or $(id).source (whichever we decide) $(id).source()._prototypeWrapperID //the id that the cache looks at $(id).source()._prototypeWrapperID - [2] // its an array with a number in it because it wont transfer when you clone the node, this is how its done in the current event system when element._prototypeEventID is set. We mod Class.create to allow the initialize method to return a value so then: Prototype.NodeWrapper = Class.create({ initialize: function(...) { // ... if (Prototype.isWrapper(element)) { // some check for wrapper return element; } // ... resolve element from ID or whatnot var cacheID = (element._prototypeWrapperID || [null])[0]; if (cacheID) { return Prototype.NodeWrapper.cache[cacheID]; } // set source, however that is decided on. this._source = element; }, // ... }) The reason we name it source instead of element or dom is so we can always know what the source of a wrapper is without having to guess if its an Element wrapper to check for element if its an event wrapper to check for .event. we would know its always .source. - JDD --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Element wrapper draft notes
kangax wrote: ... Ken, I wanted to keep $W consistent with the rest of the library - be a simple shortcut for creating a new instance of NodeWrapper. Just like ` $H` returns `new Hash` and $R returns `new ObjectRange`, $W should probably return `new NodeWrapper`. $W is also responsible for transforming string parameter into an actual element (via `document.getElementById`): ... this.$W = function(element) { if (typeof element == 'string') { element = document.getElementById(element); } return new Prototype.Node(element); }; ... Using such proxy helper ($W) also ensures NodeWrapper is always called as a constructor. There are less chances that a user will mistakenly call `NodeWrapper` as a function and pollute the global scope. It, therefore, allows us to get rid of this instanceof Prototype.Node check: new Prototype.Node('foo'); // returns a wrapper Prototype.Node('foo'); // boom! returns undefined and creates a global `source`/`raw` property That makes sense. I was just thinking where it might be confusing that: $W('foo') instanceof Prototype.Node; // true but seeing it written out like that does make sense. Good point about passing a wrapper into a wrapper : ) Would it make sense to return a wrapper itself or a clone of it? Would there ever be a need for a cloned wrapper? The only case I can think of is when there is an item in memory with the same id as one on the page. I don't know how we would handle that case. Maybe the caching system could handle that somehow. As far as caching, I'm afraid that storing reference to a wrapper on a node itself could lead to circular references (which as we know leak in IE's JScript). Having a separate cache-table and map elements to wrappers by an element's id (or a custom property of an element) seems more appropriate. What about this caching idea: http://gist.github.com/6609 I also think that #update, #insert, #replace, etc. should allow to accept a wrapper (besides an element or a string): $W('foo').insert($W('bar')); This should be as easy as giving wrapper `toElement`/`toHTML` methods (since `update`/`insert` delegate to those when available) Definitely. -- kangax Ken Snyder --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---