[Proto-Scripty] Re: Can't call a function within a class using each or invoke
great readings suggested. when you finish, you can try the following :) $$('.editable').each(function(e) {e.observe('click', (function() {this._editField(e)}).bind(this))}, this); the problem is that when you iterate, you have to specify the context. On Mon, Nov 17, 2008 at 2:15 PM, T.J. Crowder [EMAIL PROTECTED] wrote: Hi George, Go back to school! ;-) No, seriously, you don't need to wrap the call to bindAsEventListener () in a function; that's its job. You also don't have to pass the event object to it. (And you probably want bind()[1] rather than bindAsEventListener().) [1] http://prototypejs.org/api/function/bind Some resources that will probably help, both with the concept... http://blog.niftysnippets.org/2008/04/you-must-remember-this.html http://www.alistapart.com/articles/getoutbindingsituations ...and the details: http://proto-scripty.wikidot.com/prototype:how-to-hooking-events (the example near the end alks about instance methods, but I recommend reading through from the beginning). HTH, -- T.J. Crowder tj / crowder software / com On Nov 17, 1:00 pm, George [EMAIL PROTECTED] wrote: Hi Folks, I'm pretty sure that I'm going to be told to go back to school here, but I've wasted a whole morning trying to figure this out - now it's time to ask the experts. I've simplified my code here to demonstrate what I'm trying to do: [CODE] var buildPage = {}; buildPage = Class.create(); buildPage.prototype = { initialize: function() { this.rowTemplate = 'tr...' this.rs = []; this._getData(); },// initialize _getData : function() {//using AJAX to grab a JSON array from the server and store it in this.rs}, _parseTemplate : function() {//write data to screen then add event listeners $$('.editable').invoke('observe', 'mouseover',function(e){e.element ().addClassName('pseudo-text-box')}); $$('.editable').invoke('observe', 'mouseout',function(e){e.element ().removeClassName('pseudo-text-box')}); $$('.editable').invoke('observe', 'click', function(e) {this._editField.bindAsEventListener(this, e) }); }, _editField : function(e) { //Inject INPUT field} }; [/CODE] My problem is with this line: $$('.editable').invoke('observe', 'click', function(e) {this._editField.bindAsEventListener(this, e) }); At runtime, I always get the message that this._editField is not a function, no matter how I try the binding. The only way I can get this to work is to initiate the class (var a = new buildPage) than call c._editField from within the function - but that's not much good when I come to re-use it. Can someone explain to me what's going on here - I'm stumped. Many thanks George --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype script.aculo.us group. To post to this group, send email to prototype-scriptaculous@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-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Can't call a function within a class using each or invoke
T.J. - Mona, Thank you both very much for your solutions, recommended reading lists and T.J, for your event delegation suggestion. FYI Mona's solution worked out of the box but T.J. your event delegation suggestion makes a lot of sense - I suspect I will add a new method to my class to handle all clicks. I'm going to do some reading first though - will start with ALA's article on binding. Many thanks George On Nov 17, 1:54 pm, T.J. Crowder [EMAIL PROTECTED] wrote: Doh! I missed he was doing all of this in an invoke, what I get for skimming. Wow, that's convoluted. Good answer, though. George, AFAICS Mona's solution will work for your _editField function as defined. But FWIW, I'd probably define a separate function intended as an event handler. (The reason Mona's had to create an anonymous function to bind is that she needs to ditch the event object parameter _editField isn't expecting to see.) Doing that would simplify things a bit, I think, and make it easier for debugging. Another thing you might consider is event delegation: Hook the 'click' event on whatever the container of these 'editable's is, and use one event handler rather than many. Clicks on descendent elements bubble up to the parent container, and you can get the element on which the click actually happened from the event object. So given this, for instance: div id='container' span class='editable'foo foo foo/span span class='editable'bar bar barspan /div You can just hook 'click' on the 'container' rather than the editables: $('container').observe('click', this.handleContainerClick.bind(this)); and your handler might look like this: function handleContainerClick(event) { var elm; // Get the element on which the click actually occurred elm = event.findElement(); // Does it exist, and is it editable? if (elm elm.hasClassName('editable')) { // Yes, edit it this._editField(elm); } } Various links on event delegation can be found here:http://proto-scripty.wikidot.com/faq#delegation HTH, -- T.J. Crowder tj / crowder software / com On Nov 17, 1:34 pm, Mona Remlawi [EMAIL PROTECTED] wrote: great readings suggested. when you finish, you can try the following :) $$('.editable').each(function(e) {e.observe('click', (function() {this._editField(e)}).bind(this))}, this); the problem is that when you iterate, you have to specify the context. On Mon, Nov 17, 2008 at 2:15 PM, T.J. Crowder [EMAIL PROTECTED] wrote: Hi George, Go back to school! ;-) No, seriously, you don't need to wrap the call to bindAsEventListener () in a function; that's its job. You also don't have to pass the event object to it. (And you probably want bind()[1] rather than bindAsEventListener().) [1]http://prototypejs.org/api/function/bind Some resources that will probably help, both with the concept... http://blog.niftysnippets.org/2008/04/you-must-remember-this.html http://www.alistapart.com/articles/getoutbindingsituations ...and the details: http://proto-scripty.wikidot.com/prototype:how-to-hooking-events (the example near the end alks about instance methods, but I recommend reading through from the beginning). HTH, -- T.J. Crowder tj / crowder software / com On Nov 17, 1:00 pm, George [EMAIL PROTECTED] wrote: Hi Folks, I'm pretty sure that I'm going to be told to go back to school here, but I've wasted a whole morning trying to figure this out - now it's time to ask the experts. I've simplified my code here to demonstrate what I'm trying to do: [CODE] var buildPage = {}; buildPage = Class.create(); buildPage.prototype = { initialize: function() { this.rowTemplate = 'tr...' this.rs = []; this._getData(); },// initialize _getData : function() {//using AJAX to grab a JSON array from the server and store it in this.rs}, _parseTemplate : function() {//write data to screen then add event listeners $$('.editable').invoke('observe', 'mouseover',function(e){e.element ().addClassName('pseudo-text-box')}); $$('.editable').invoke('observe', 'mouseout',function(e){e.element ().removeClassName('pseudo-text-box')}); $$('.editable').invoke('observe', 'click', function(e) {this._editField.bindAsEventListener(this, e) }); }, _editField : function(e) { //Inject INPUT field} }; [/CODE] My problem is with this line: $$('.editable').invoke('observe', 'click', function(e) {this._editField.bindAsEventListener(this, e) }); At runtime, I always get the message that this._editField is not a function, no matter how I try the binding. The only way I can get this to work is to initiate the class (var a = new buildPage) than call c._editField from within the function - but that's not much good when I come to re-use it. Can someone explain to me what's going on here -
[Proto-Scripty] Re: Can't call a function within a class using each or invoke
Good call George, I'll do the same :) cheers -- mona [EMAIL PROTECTED] On Mon, Nov 17, 2008 at 4:13 PM, George [EMAIL PROTECTED] wrote: T.J. - Mona, Thank you both very much for your solutions, recommended reading lists and T.J, for your event delegation suggestion. FYI Mona's solution worked out of the box but T.J. your event delegation suggestion makes a lot of sense - I suspect I will add a new method to my class to handle all clicks. I'm going to do some reading first though - will start with ALA's article on binding. Many thanks George On Nov 17, 1:54 pm, T.J. Crowder [EMAIL PROTECTED] wrote: Doh! I missed he was doing all of this in an invoke, what I get for skimming. Wow, that's convoluted. Good answer, though. George, AFAICS Mona's solution will work for your _editField function as defined. But FWIW, I'd probably define a separate function intended as an event handler. (The reason Mona's had to create an anonymous function to bind is that she needs to ditch the event object parameter _editField isn't expecting to see.) Doing that would simplify things a bit, I think, and make it easier for debugging. Another thing you might consider is event delegation: Hook the 'click' event on whatever the container of these 'editable's is, and use one event handler rather than many. Clicks on descendent elements bubble up to the parent container, and you can get the element on which the click actually happened from the event object. So given this, for instance: div id='container' span class='editable'foo foo foo/span span class='editable'bar bar barspan /div You can just hook 'click' on the 'container' rather than the editables: $('container').observe('click', this.handleContainerClick.bind(this)); and your handler might look like this: function handleContainerClick(event) { var elm; // Get the element on which the click actually occurred elm = event.findElement(); // Does it exist, and is it editable? if (elm elm.hasClassName('editable')) { // Yes, edit it this._editField(elm); } } Various links on event delegation can be found here:http://proto-scripty.wikidot.com/faq#delegation HTH, -- T.J. Crowder tj / crowder software / com On Nov 17, 1:34 pm, Mona Remlawi [EMAIL PROTECTED] wrote: great readings suggested. when you finish, you can try the following :) $$('.editable').each(function(e) {e.observe('click', (function() {this._editField(e)}).bind(this))}, this); the problem is that when you iterate, you have to specify the context. On Mon, Nov 17, 2008 at 2:15 PM, T.J. Crowder [EMAIL PROTECTED] wrote: Hi George, Go back to school! ;-) No, seriously, you don't need to wrap the call to bindAsEventListener () in a function; that's its job. You also don't have to pass the event object to it. (And you probably want bind()[1] rather than bindAsEventListener().) [1]http://prototypejs.org/api/function/bind Some resources that will probably help, both with the concept... http://blog.niftysnippets.org/2008/04/you-must-remember-this.html http://www.alistapart.com/articles/getoutbindingsituations ...and the details: http://proto-scripty.wikidot.com/prototype:how-to-hooking-events (the example near the end alks about instance methods, but I recommend reading through from the beginning). HTH, -- T.J. Crowder tj / crowder software / com On Nov 17, 1:00 pm, George [EMAIL PROTECTED] wrote: Hi Folks, I'm pretty sure that I'm going to be told to go back to school here, but I've wasted a whole morning trying to figure this out - now it's time to ask the experts. I've simplified my code here to demonstrate what I'm trying to do: [CODE] var buildPage = {}; buildPage = Class.create(); buildPage.prototype = { initialize: function() { this.rowTemplate = 'tr...' this.rs = []; this._getData(); },// initialize _getData : function() {//using AJAX to grab a JSON array from the server and store it in this.rs}, _parseTemplate : function() {//write data to screen then add event listeners $$('.editable').invoke('observe', 'mouseover',function(e){e.element ().addClassName('pseudo-text-box')}); $$('.editable').invoke('observe', 'mouseout',function(e){e.element ().removeClassName('pseudo-text-box')}); $$('.editable').invoke('observe', 'click', function(e) {this._editField.bindAsEventListener(this, e) }); }, _editField : function(e) { //Inject INPUT field} }; [/CODE] My problem is with this line: $$('.editable').invoke('observe', 'click', function(e) {this._editField.bindAsEventListener(this, e) }); At runtime, I always get the message that this._editField is not a function, no matter how I try the binding. The only way I can get this to work is to initiate the class (var a = new buildPage) than