[Proto-Scripty] Re: Using this.arrayname to add data to an array not working
Hi, Yes I found some good info by Mr Crockford and friends a few weeks ago. I was looking up some info on advanced AJAX security techniques. Found these pages: http://www.webdirections.org/resources/douglas-crockford-ajax-security/ Some interesting presentation slides... and from there a link to: http://www.codinghorror.com/blog/archives/001175.html Unfortunatly I wont be buying any more books untill I get a job. Have an Interview with a 'recruiting crowd' today [friday]. Fingers crossed.. I have now replaced the XML in the Q and A app with JSON, and, added caching for the fetched q and a sets. Works like a dream. Any thoughts yet on why the bind() function won't work within the Ajax.Request?? Not important, just curious.. Mabye its an unexpected bug in the prototype AJAX implementation? Is there another group/list where that question might be more appropriate? Thanks Again! Gilbert R.. --~--~-~--~~~---~--~~ 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 prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Using this.arrayname to add data to an array not working
Your problem is that you are making (reasonable but wrong) assumptions about what 'this' is bound to. Inside a function (which is the only level of scope that Javascript has), 'this' is not set, and therefore refers to the global object (the window) unless you have done something explicit to cause it to be bound to something else. The usual case is that you call the function using the 'method' invocation, in which case 'this' is bound to the object on which the method was called. I'm not certain what 'this' will be bound to in your example, ('new' confuses me) but I think it is the new Ajax.Request object you are creating, Whatever, it will *not* be whatever 'this' is bound to outside the call. Prototype has a method Function#bind for setting 'this' explicitly in a function. Colin Fine --~--~-~--~~~---~--~~ 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 prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Using this.arrayname to add data to an array not working
Hi Gilbert, Building on what Colin said, I'd suggest reading up a bit on JavaScript and this, it's not quite the same as some other languages you might be familiar with. If you don't already have a good JavaScript book, I'd recommend JavaScript: The Definitive Guide by David Flanagan[1][2]. I've done a couple of blog entries[3][4] that may help as well. You have a couple of options for solving the problem. One is to use Function#bind[5] as Colin said. You can do that with a named function, or even with your current anonymous function by wrapping the whole thing in () and putting .bind(this) at the end of it: * * * * var url = path-to-php-script-sid=+Math.random(); var req = new Ajax.Request(url, { method: 'get', contentType: 'application/xml', onComplete: (function(transport) { var res = transport.responseXML; var cap_nodes = res.getElementsByTagName('group'); for(i=0; i cap_nodes.length; i++){ this.cap_questions.push(cap_nodes[i].childNodes [0].nodeValue); }).bind(this) } }); * * * * ...but that's pretty awkward to read. (The parens may or may not be necessary; I'd include them for clarity if nothing else.) Alternately, you can make the handler a function you define elsewhere and just use in the request: * * * * // Somewhere in your class definition handler: function(transport) { var res = transport.responseXML; var cap_nodes = res.getElementsByTagName('group'); for(i=0; i cap_nodes.length; i++){ this.cap_questions.push(cap_nodes[i].childNodes [0].nodeValue); } }, // Where you want to use it var url = path-to-php-script-sid=+Math.random(); var req = new Ajax.Request(url, { method: 'get', contentType: 'application/xml', onComplete: this.handler.bind(this) } }); * * * * But if you really want to define it inline, you can just make use of the fact that it's already a closure and you don't need Function#bind at all -- just declare a variable and set its value to 'this', and then use that variable within the closure: * * * * var self = this; // For use within the closure below var url = path-to-php-script-sid=+Math.random(); var req = new Ajax.Request(url, { method: 'get', contentType: 'application/xml', onComplete: function(transport) { var res = transport.responseXML; var cap_nodes = res.getElementsByTagName('group'); for(i=0; i cap_nodes.length; i++){ self.cap_questions.push(cap_nodes[i].childNodes [0].nodeValue); } } }); * * * * If you're not sure what I mean by closure and how that works, Flanagan[1][2] covers it a bit and I've written a bit about it[6][7]. (BTW: In my examples above, I've declared 'res' and 'cap_nodes' as vars within the function. Your example didn't do that, and so they become globals[8], which will almost certainly give you trouble at some point.) [1] http://www.oreilly.com/catalog/jscript5/ [2] http://www.amazon.com/dp/0596101996 [3] http://blog.niftysnippets.org/2008/03/mythical-methods.html [4] http://blog.niftysnippets.org/2008/04/you-must-remember-this.html [5] http://prototypejs.org/api/function/bind [6] http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html [7] http://blog.niftysnippets.org/2008/03/closures-by-example.html [8] http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html HTH, -- T.J. Crowder tj / crowder software / com Independent Software Engineer, consulting services available On Apr 27, 5:28 pm, IMBI-Indie-Portal imbil...@tpg.com.au wrote: Thanks T.J. I probably should have been more specific. I'm actually building a Q and A Captcha, not a Logger. I used that as an example. The issue is, I am using proto's Ajax.Request and I'm running that code within the 'onComplete: function(transport){ callback }' and this is executing within a method which get an array of questions from a database. Another method then creates a select list and renders it to the page. I have found that if I declare a var using the 'this.arrayName' before running the Ajax.Request I can load the array OK. What is strange, is that I can then do 'this.ArrayName = var;' and populate the objects array whilst I'm still in the 'onComplete callback'. Why is it that I cant load the this,arrayName as shown, but it lets be 're-value it'?? Here is a sample of the code: some var declarations are Not show for simplicity... var qArr = this.cap_questions; // I CREATE THE USABLE VAR WORKAROUND HERE var url = path-to-php-script-sid=+Math.random(); var req = new Ajax.Request( url, { // I USE THE var = req TO MAKE JSLINT HAPPY ?? method: 'get', contentType: 'application/xml', onComplete: function (transport) { res = transport.responseXML; cap_nodes = res.getElementsByTagName ('group'); for(i=0; i cap_nodes.length; i++){ qArr.push(cap_nodes[i].childNodes[0].nodeValue);
[Proto-Scripty] Re: Using this.arrayname to add data to an array not working
Hi! Thanks T.J and Colin. So Far So Good! I stayed with the 'inline method', to save code. I could Not get the bind() to work within the Ajax.Request though?? I tried it as T.J showed, and several other ways. Firebug reported different errors. Suggested method for inline returned (' missing } from property statement') with parenthes ')' and syntax errors without them. Trying in other positions had similar errors.. One odd bit of behaviour noted though. After populating the arrays and after exiting the Ajax.functions, when I did 'alert(this.cap_questions) before the method finished only got a blank result, not undefined, just blank. I figured that self = this is like using the PHP operator which binds the new var to the original? I even tried to alert(self.cap_questions) and got the same blank result. Yet, the arrays where populated as expected?? I guess part of the game is having faith in what your doing! I used the 'var self = this;' Worked like a dream - thanks. I did use the bind() in a few other places, like inside some setTimeout's - where I wrap in a function() as per LINT methods.. I definately learnt a few new things tonight. Much appretiated. I relate a lot to my PHP Classes and basic JS knowledge, but I'll have to do some homework on Prototype Classes and Js Classes and Objects. My Js function days are over. Classes from now on.. The second issue about calling one method from within another resolved itself using the bind(). I also did a quick test, regarding what you said about 'global vars'. I set a var in one method and tested for in in the next one that runs, but it returned 'undefined'.. I did tidy up the vars as you suggested though! I'll study the links that you gave me to see if I can undeestand how globals (declared vars) run their scope in Js classes. I think thats the key issue with all od this, scope.. I know that globals can be a bad thing as per ADSafe specs.. I'm going to be re-writing most of my JS into classes now, so you may hear from me again on classes if I get stuck.. I have another problem with prototype that I want to ask about, but as its not related so I'll start a new thread tommorow. Its bedtime now here in Oz.. Thanks again for your prompt help. This is a great group. Signing Off - Gilbert R --~--~-~--~~~---~--~~ 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 prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Using this.arrayname to add data to an array not working
Hi, Your Logger class, as given, will work fine: var l = new Logger(); l.write(Testing); l.write(One); l.write(Two); l.write(Three); The result of the above would be that the 'log' array would be: [Testing, One, Two, Three] I have had to use the following in my method that updates the array. That workaround is not necessary. If this code works: var qArr = this.cap_questions;// create a var as the array // for(blah blah){ var q = // set-up the value // qArr.push(q); } this.cap_questions = qArr; // restore the classes array value with ...then this code works: for(blah blah){ var q = // set-up the value // this.cap_questions.push(q); } I suspect if you give us a more complete example -- including direct quotes of where you're using your class (the above are clearly edited examples) -- we'll be able to tell you what you're doing wrong. My guess would be that it relates to how you're calling your class's instance methods. HTH, -- T.J. Crowder tj / crowder software / com Independent Software Engineer, consulting services available On Apr 27, 2:05 pm, Imbi Rehling imbil...@tpg.com.au wrote: Hello to all, my first post to this group! I am new to OOP in JavaScript and have written my first Js Class using prototype.js.. On the 'Learn pages' at prototypejs.org the example for 'Classes-Inheritance' shows the following.. var Logger = Class.create({ initialize: function() { // this is the right way to do it: this.log = []; }, write: function(message) { this.log.push(message); } }); For some reason I can't seem to add to the array using 'this.arrayName'. I have tried also this.arrayName[i] = value; I initialize the array using the method shown above I have had to use the following in my method that updates the array. I have several methods that will update arrays, and will probably have to use the same in those. It will mean two lines of extra code for each method!! . var qArr = this.cap_questions; // create a var as the array // for(blah blah){ var q = // set-up the value // qArr.push(q); } this.cap_questions = qArr; // restore the classes array value with updated var // Does anyone have an explanation for this, or is it a bug?? If its a bug, should it be reported at the site?? Thanks in advance.. Gilbert --~--~-~--~~~---~--~~ 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 prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Using this.arrayname to add data to an array not working
Thanks T.J. I probably should have been more specific. I'm actually building a Q and A Captcha, not a Logger. I used that as an example. The issue is, I am using proto's Ajax.Request and I'm running that code within the 'onComplete: function(transport){ callback }' and this is executing within a method which get an array of questions from a database. Another method then creates a select list and renders it to the page. I have found that if I declare a var using the 'this.arrayName' before running the Ajax.Request I can load the array OK. What is strange, is that I can then do 'this.ArrayName = var;' and populate the objects array whilst I'm still in the 'onComplete callback'. Why is it that I cant load the this,arrayName as shown, but it lets be 're-value it'?? Here is a sample of the code: some var declarations are Not show for simplicity... var qArr = this.cap_questions; // I CREATE THE USABLE VAR WORKAROUND HERE var url = path-to-php-script-sid=+Math.random(); var req = new Ajax.Request( url, { // I USE THE var = req TO MAKE JSLINT HAPPY ?? method: 'get', contentType: 'application/xml', onComplete: function (transport) { res = transport.responseXML; cap_nodes = res.getElementsByTagName ('group'); for(i=0; i cap_nodes.length; i++){ qArr.push(cap_nodes[i].childNodes[0].nodeValue); } this.cap_questions = qArr; // HERE IT LETS ME RE-DECLARE THIS OBJECTS VALUE? } }); If I try to declare the VAR within the callback it won't work either, Has to be before the new Ajax.Request. I checked with 'typeof' and it returns 'undefined' I have another problem as well. How can I call a method within another method, like in PHP. Using 'this.methodName() does not seem to work. After completion of one methods db retrieval, I do a check for state, and would like to call a method within the working method. The idea worked (as functions) before I re-wrote the whole idea into a single class. I want the class to be as dynamic as possible, and dont want to have to add more intelect to the pages code. This will be a publicly available App, so I'm trying to make it as simple as possible to setup. Thanks again for the Quick HELP. Its much appreciated! Cheers, Gilbert R.. --~--~-~--~~~---~--~~ 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 prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---