Hi all, I''m having a problem with an Ajax.Request. I can''t figure out how I can pass an event (an onclick on a checkbox) which causes the Ajax Request, to be recognized in an onSuccess function. Here''s my simplified code: var RequiredField = Class.create(); RequiredField.prototype = { initialize: function(chkbox) { this.chkbox = chkbox; this.chkbox.onclick = this.switchRequired.bindAsEventListener(this); }, switchRequired: function(evt) { this.evt = evt; // Set the event to a property alert(this.evt); var params = $F(this.chkbox); var myAjax = new Ajax.Request(''server/checkRequired.html'', {method: ''get'', parameters: params, onSuccess: this.switchPrompt ,onFailure: this.dontCheck} }, switchPrompt: function() { alert(this.evt); // Try to pick up the this.evt var, but it comes bakc as undefined }, dontCheck: function(response) { // failure } }
A few thoughts : 1) You need to bind the object to get it to work: onSuccess: this.switchPrompt.bind(this), onFailure: this.dontCheck.bind(this) that will fake out Javascript and set up the "this" reference to work correctly for you I think. 2) On another note, I''ve noticed that it''s appropriate to use the Event.observe() method to set up onclick listeners. For instance: Event.observe(this.chkbox, ''click'',this.switchRequired.bindAsEventListener(this)); In this case it probably makes no difference, but in general it helps you around browser inconsistencies with events and listeners. 3) Do you really want to cache the whole event? I don''t know if that will cause any weirdness because of the browser trying to destroy it or something. In general I would cache the source of the event only, which is probably what you need anyway: this.cache = Event.element(evt); but maybe I''m wrong and you do want the whole event and caching it is not a problem. Hope that helps, rahul -----Original Message----- From: rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Jason Hummel Sent: Thursday, October 27, 2005 9:37 AM To: rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: [Rails-spinoffs] Problem passing event object Hi all, I''m having a problem with an Ajax.Request. I can''t figure out how I can pass an event (an onclick on a checkbox) which causes the Ajax Request, to be recognized in an onSuccess function. Here''s my simplified code: var RequiredField = Class.create(); RequiredField.prototype = { initialize: function(chkbox) { this.chkbox = chkbox; this.chkbox.onclick = this.switchRequired.bindAsEventListener(this); }, switchRequired: function(evt) { this.evt = evt; // Set the event to a property alert(this.evt); var params = $F(this.chkbox); var myAjax = new Ajax.Request(''server/checkRequired.html'', {method: ''get'', parameters: params, onSuccess: this.switchPrompt ,onFailure: this.dontCheck} }, switchPrompt: function() { alert(this.evt); // Try to pick up the this.evt var, but it comes bakc as undefined }, dontCheck: function(response) { // failure } } _______________________________________________ Rails-spinoffs mailing list Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
Thanks for the feedback, the bind(this) worked like a charm, I was beating my head against my monitor trying to come up with a solution. I''m confused, though, as to why javascript loses the reference to "this" without that bind method can somebody explain? Also why doesn''t onSuccess: this.switchPrompt.bind(this) fire automatically, because it has "()" at the end. I know I tried this.switchPrompt(evt) at one point, and instead of pointing the switchPrompt method to be fired onSuccess, it just always fired it automatically - because it had the parenthases at the end. Thanks for the other thoughts as well, I implemented both of them, just to be on the safe side. On 10/27/05, Rahul Bhargava <rahul-NLnzLvfFuBM@public.gmane.org> wrote:> A few thoughts : > > 1) You need to bind the object to get it to work: > onSuccess: this.switchPrompt.bind(this), > onFailure: this.dontCheck.bind(this) > that will fake out Javascript and set up the "this" reference to work > correctly for you I think. > > 2) On another note, I''ve noticed that it''s appropriate to use the > Event.observe() method to set up onclick listeners. For instance: > > Event.observe(this.chkbox, > ''click'',this.switchRequired.bindAsEventListener(this)); > > In this case it probably makes no difference, but in general it helps > you around browser inconsistencies with events and listeners. > > 3) Do you really want to cache the whole event? I don''t know if that > will cause any weirdness because of the browser trying to destroy it or > something. In general I would cache the source of the event only, which > is probably what you need anyway: > this.cache = Event.element(evt); > but maybe I''m wrong and you do want the whole event and caching it is > not a problem.
Ah, JS is a bit quirky, but those quirks are kind of what makes it so useful and great. This is my understanding of it... First off, functions are just another type of object in JS. So if you have a function: function foo(){ alert(''foo''); } you can run that function by doing "foo()", or you can refer to it as a variable as "foo" - notice the lack of parentheses. So now take your case, where you want to register a function as a callback for something else. The idea is that whatever you pass in for onSuccess should be a function object that will be called later, you don''t want to run that function right then. So you need to pass in the variable that is your function, not run the function itself. The tricky thing is that when you refer to the function as a variable, if it is inside some other object, it doesn''t know about the "this" object when it is called for execution later. I don''t know why that is, it just is the way of the JS world I guess. So the prototype.js library adds a "bind()" method to the function object. That method returns a function - and that''s confusing. It returns a function that remembers the "this" argument that you pass in, and when executed it will run the method you have bound against that. So in practice this is what happens: 1) onSuccess: this.switchPrompt(evt) This would just run the switchPrompt function and set onSuccess to the value it returns... not what you want. 2) onSuccess: this.switchPrompt This would register that function variable as the callback, but it probably wouldn''t work because it won''t be able to access the "this" object when it runs. Not what you want. 3) onSuccess: this.switchPrompt.bind(this) Will create a fake function for you and return that, so the callback is properly set to a function variable that can be run and will remember it''s "this" parent object. That''s what you want. Hope that is accurate / helpful. It''s certainly confusing :-) rahul -----Original Message----- From: rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Jason Hummel Sent: Thursday, October 27, 2005 12:09 PM To: rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: Re: [Rails-spinoffs] Problem passing event object Thanks for the feedback, the bind(this) worked like a charm, I was beating my head against my monitor trying to come up with a solution. I''m confused, though, as to why javascript loses the reference to "this" without that bind method can somebody explain? Also why doesn''t onSuccess: this.switchPrompt.bind(this) fire automatically, because it has "()" at the end. I know I tried this.switchPrompt(evt) at one point, and instead of pointing the switchPrompt method to be fired onSuccess, it just always fired it automatically - because it had the parenthases at the end. Thanks for the other thoughts as well, I implemented both of them, just to be on the safe side. On 10/27/05, Rahul Bhargava <rahul-NLnzLvfFuBM@public.gmane.org> wrote:> A few thoughts : > > 1) You need to bind the object to get it to work: > onSuccess: this.switchPrompt.bind(this), > onFailure: this.dontCheck.bind(this) > that will fake out Javascript and set up the "this" reference to work > correctly for you I think. > > 2) On another note, I''ve noticed that it''s appropriate to use the > Event.observe() method to set up onclick listeners. For instance: > > Event.observe(this.chkbox, > ''click'',this.switchRequired.bindAsEventListener(this)); > > In this case it probably makes no difference, but in general it helps > you around browser inconsistencies with events and listeners. > > 3) Do you really want to cache the whole event? I don''t know if that > will cause any weirdness because of the browser trying to destroy itor> something. In general I would cache the source of the event only,which> is probably what you need anyway: > this.cache = Event.element(evt); > but maybe I''m wrong and you do want the whole event and caching it is > not a problem._______________________________________________ Rails-spinoffs mailing list Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
* Jason Hummel <jhummel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> [2005-10-27 12:09]:> Thanks for the feedback, the bind(this) worked like a charm, I was > beating my head against my monitor trying to come up with a solution. > > I''m confused, though, as to why javascript loses the reference to > "this" without that bind method can somebody explain?function ThingSayFoo() { alert(''foo! '' + this + this.location); } function Thing() { this.location = ''thing''; return this; } Thing.prototype = { sayFoo: ThingSayFoo } function Amajig() { this.location = ''-a-ma-jig''; return this; } Amajig.prototype = { sayFoo: ThingSayFoo } // Called directly, this is the brwoser window, closures at work. ThingSayFoo() // Thing is this. new Thing().sayFoo(); // Amajig is this. new Amajig().sayFoo(); Didn''t see the orginal code, but a refernece to this is not lost. It is added. And it is added based on how the function is called. Bind keeps the desired target object in a closure, and calls the member function "though" the object. Assigning the method directly means it is called directly. Cheers. -- Alan Gutierrez - alan-JbsJTiZCByIAvxtiuMwx3w@public.gmane.org - http://engrm.com/blogometer/
Rahul Bhargava wrote:>The tricky thing is that when you refer to the function as a variable, >if it is inside some other object, it doesn''t know about the "this" >object when it is called for execution later. I don''t know why that is, >it just is the way of the JS world I guess. >Does this help any? (not the variable this, that is, but the link this... er, the link that... the link I''m about to give you...) http://www.quirksmode.org/js/this.html