[Proto-Scripty] Re: Binding class method problem with this
Back to happy. All is working. Thanks again TJ, and I love when things work as expected! I have been pulling my hair out all weekend! Karl.. On Sep 19, 11:25 pm, kstubs kst...@gmail.com wrote: Oh my gosh! OK, I never considered that bind() returns a function. Wow... that changes everything. Thanks for the links, and the concise response T.J. Looking at these items now, and obviously my standalone code post is moot. Karl.. On Sep 19, 9:52 pm, T.J. Crowder t...@crowdersoftware.com wrote: Hi, ...I am still confused on the behavior of the test javascript code. Your first call, `_test.show('outer', 0);`, is processed like this: 1. Log the call via console.log 2. Since itt == 0, go into the first if block 3. Do a `bind` that's completely ignored because it's never called or stored anywhere 4. Do a call to `test#show`, which is 4.a. Logged via console.log 4.b. itt != 0 so first if block skipped 4.c. itt == 1 so enter second block 4.d. Do a `bind` that's completely ignored because it's never called or stored anywhere 5. Do a call to `test#hide`, which just logs it The wait to show event is coded like this: this.show.bind(this).delay(2); There, your bound function for `test#show` *is* used -- you're setting up a delayed call to it. A method hide on the same object occurs on document mouseover. One thing it does is to set this.active = false; This document mouseover could occur in the 2 second delay. I am expecting that setting this.active = false will cancel expanding the banner. It should, from what you've described. You've talked about mouseover and mouseout. For something like this, I'd use mouseenter and mouseleave instead. Prototype 1.6.1 and up emulate these on browsers that don't provide them (which is many of them; they were originally in IE only). mouseenter and mouseleave don't bubble, which in some situations is very useful. Here's an example using those events and an active flag with a delayed function call as you've described:http://jsbin.com/asefu4 Using an active flag like that has an issue: If the user mouses over the banner, mouses out, and then returns within the two seconds, the banner will expand almost immediately (as a result of the original two- second delay). Here's an example that uses the handle returned by Function#delay instead:http://jsbin.com/asefu4/2 HTH, -- T.J. Crowder Independent Software Engineer tj / crowder software / com www / crowder software / com On Sep 20, 2:12 am, kstubs kst...@gmail.com wrote: Does it mean: if I am using a member variable (ie., this.active = false;) who's value is true when I'm over the banner and if true then show the banner after specific wait time but if I cancel the variable because of another event, like mouseover the document, the method bound to the show() event is a copy, so this.active is true?? The wait to show event is coded like this: this.show.bind(this).delay(2); The show event has something like this: if(this.active) this.banner.addClassName('expanded'); A method hide on the same object occurs on document mouseover. One thing it does is to set this.active = false; This document mouseover could occur in the 2 second delay. I am expecting that setting this.active = false will cancel expanding the banner. Does this clear things up? Karl.. On Sep 19, 4:33 pm, kstubs kst...@gmail.com wrote: My Challenge: I have a banner on my website,www.meetscoresonline.com When you rollover the banner, the action to expand the banner will pause, expecting the user to remain on the banner to ensure he wishes the banner to expand. The banner should remain expanded until I leave the banner. Not sure why I am having so much trouble with this, but things like mouseout event is firing when I rollover objects contained by the banner at which time I should NOT collapse the banner. The banner should only collapse when the user mouses away from the banner. In my efforts to code this, I wrote up the test javascript and was trying to understand the behavior of binding the objects. Your explanation helps, but honestly I am still confused on the behavior of the test javascript code. Karl.. On Sep 19, 2:48 am, T.J. Crowder t...@crowdersoftware.com wrote: Hi, I can't quite make out what you're trying to do, but I can tell you why what you're doing isn't working: Function#bind[1] *returns* a new bound function, it doesn't change the original function at all. Since you're not assigning the return value to anything, it's not being used. You typically use #bind when you're passing a reference to a function that needs to be called with a specific context (`this` value) into something that doesn't provide any way for you to tell it what that
[Proto-Scripty] Re: Binding class method problem with this
Does it mean: if I am using a member variable (ie., this.active = false;) who's value is true when I'm over the banner and if true then show the banner after specific wait time but if I cancel the variable because of another event, like mouseover the document, the method bound to the show() event is a copy, so this.active is true?? The wait to show event is coded like this: this.show.bind(this).delay(2); The show event has something like this: if(this.active) this.banner.addClassName('expanded'); A method hide on the same object occurs on document mouseover. One thing it does is to set this.active = false; This document mouseover could occur in the 2 second delay. I am expecting that setting this.active = false will cancel expanding the banner. Does this clear things up? Karl.. On Sep 19, 4:33 pm, kstubs kst...@gmail.com wrote: My Challenge: I have a banner on my website,www.meetscoresonline.com When you rollover the banner, the action to expand the banner will pause, expecting the user to remain on the banner to ensure he wishes the banner to expand. The banner should remain expanded until I leave the banner. Not sure why I am having so much trouble with this, but things like mouseout event is firing when I rollover objects contained by the banner at which time I should NOT collapse the banner. The banner should only collapse when the user mouses away from the banner. In my efforts to code this, I wrote up the test javascript and was trying to understand the behavior of binding the objects. Your explanation helps, but honestly I am still confused on the behavior of the test javascript code. Karl.. On Sep 19, 2:48 am, T.J. Crowder t...@crowdersoftware.com wrote: Hi, I can't quite make out what you're trying to do, but I can tell you why what you're doing isn't working: Function#bind[1] *returns* a new bound function, it doesn't change the original function at all. Since you're not assigning the return value to anything, it's not being used. You typically use #bind when you're passing a reference to a function that needs to be called with a specific context (`this` value) into something that doesn't provide any way for you to tell it what that context should be (like an event handler). What #bind does is create a new function that doesn't care what `this` value it's called with. The new function, when called, turns around and calls the original function with the `this` value you told it to use (as well as any curried arguments and then the actual arguments it was called with). Here's a classic event handler example: $('someElement').observe('click', myObj.myMethod.bind(myobj)); The above uses #bind to create a function that, when called, will turn around and call `myMethod` in the context of `myObj`. `myMethod` is not changed in any way. The return value of #bind is passed in as the handler. To make it a bit more explicit: var handler = myObj.myMethod.bind(myobj); $('someElement').observe('click', handler); [1]http://api.prototypejs.org/language/function/prototype/bind/ HTH, -- T.J. Crowder Independent Software Engineer tj / crowder software / com www / crowder software / com On Sep 18, 7:36 pm, kstubs kst...@gmail.com wrote: In my test class, I call show() method externally and then internally but the internal calls are not working when binding this. The expected console results for the following implementation: _test = new test(); _test.show('outer', 0); _test.hide('outer'); EXPECTED CONSOLE LOG: show: outer show: inner show: inner no bind hide: inner hide: outer ACTUAL CONSOLE LOG: show: outer show: inner no bind hide: outer Here is my test class. Is there something wrong with the binding method? var test = Class.create({ show: function(caller, itt) { console.log('show: ' + caller); if(itt == 0) { this.show.bind(this, 'inner', 1); this.show('inner no bind', 1); } if(itt == 1) this.hide.bind(this, 'inner', itt); }, hide: function(caller) { console.log('hide: ' + caller); } }); -- 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-scriptacul...@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: Binding class method problem with this
I am attaching a self-contained test page. This demonstrates an issue with bind(). Note test ONE fails. All other tests pass as expected. Test one is: this.out.bind(this,'ONE '); This fails. Interestingly, if I add a delay to this, as in test TWO, THREE, it works. So this works: this.out.bind(this,'TWO ').delay(1.5); Please have a look. Am I doing something wrong with bind? As for the other issues mentioned in this thread, I am going to clean up my Javascript some, as I think there is some other problem. I'm having issues with scope, setTimeouts, etc... these stand-alone tests prove that the issue is somewhere else. Thanks for looking at the bind problem. Karl... STANDALONE CODE !DOCTYPE HTML html head !-- TODO: Obviously, change this if you're using a different encoding -- meta http-equiv=Content-type content=text/ html;charset=UTF-8/meta titleTest Page/title script type='text/javascript' src='http://prototypejs.org/ assets/2009/8/31/prototype.js'/script script type='text/javascript' var four = 0; var five = 0; var Thing = Class.create({ Name:'Paul', initialize: function() { }, test: function(e){ var elm = e.element(); console.log(elm.readAttribute('id')); $('out').update(); $('out').insert('pExpecting: ONE TWO THREE FOUR FIVE (five ommitted if you rollover out region)/p'); $('out').insert('pActual: TWO THREE FOUR FIVE/p'); // ONE this.out.bind(this,'ONE '); // TWO this.out.bind(this,'TWO ').delay(1.5); // THREE var f = function() { this.out('THREE '); }.bind(this); var three = setTimeout(f, 3000); // FOUR four = setTimeout(this.testTimeout.bind(this, 'FOUR '), 4000); // FIVE five = setTimeout(this.testTimeout.bind(this, 'FIVE '), 5000); }, testTimeout: function(value) { this.out(value); }, out: function(value) { $('out').insert(value); }, cancel: function(){ if(five != null) clearTimeout(five); } }); var t = null; document.observe('dom:loaded', function() { t = new Thing(); $('btnGo').observe('click', t.test.bindAsEventListener(t)); $('out').observe('mouseover', t.cancel.bindAsEventListener(t)); }); /script /head body div input type='button' id='btnGo' value='Go'/ /div div id=out style=background-color:#ccc; padding:5px; border:#999 /div /body /html On Sep 19, 6:12 pm, kstubs kst...@gmail.com wrote: Does it mean: if I am using a member variable (ie., this.active = false;) who's value is true when I'm over the banner and if true then show the banner after specific wait time but if I cancel the variable because of another event, like mouseover the document, the method bound to the show() event is a copy, so this.active is true?? The wait to show event is coded like this: this.show.bind(this).delay(2); The show event has something like this: if(this.active) this.banner.addClassName('expanded'); A method hide on the same object occurs on document mouseover. One thing it does is to set this.active = false; This document mouseover could occur in the 2 second delay. I am expecting that setting this.active = false will cancel expanding the banner. Does this clear things up? Karl.. On Sep 19, 4:33 pm, kstubs kst...@gmail.com wrote: My Challenge: I have a banner on my website,www.meetscoresonline.com When you rollover the banner, the action to expand the banner will pause, expecting the user to remain on the banner to ensure he wishes the banner to expand. The banner should remain expanded until I leave the banner. Not sure why I am having so much trouble with this, but things like mouseout event is firing when I rollover objects contained by the banner at which time I should NOT collapse the banner. The banner should only collapse when the user mouses away from the banner. In my efforts to code this, I wrote up the test javascript and was trying to understand the behavior of binding the objects. Your explanation helps, but honestly I am still confused on the behavior of the test javascript code. Karl.. On Sep 19, 2:48 am, T.J. Crowder t...@crowdersoftware.com wrote: Hi, I can't quite make out what you're trying to do, but I can tell you why what you're doing isn't working: Function#bind[1] *returns* a new bound function, it doesn't change the original function at all. Since you're not assigning the return value to anything, it's not being used. You typically use #bind when you're passing a reference to a function that needs to be called with a specific context (`this` value) into something that doesn't provide any way for you to tell it what that context should be (like an event handler). What #bind does is create a new
[Proto-Scripty] Re: Binding class method problem with this
Hi, ...I am still confused on the behavior of the test javascript code. Your first call, `_test.show('outer', 0);`, is processed like this: 1. Log the call via console.log 2. Since itt == 0, go into the first if block 3. Do a `bind` that's completely ignored because it's never called or stored anywhere 4. Do a call to `test#show`, which is 4.a. Logged via console.log 4.b. itt != 0 so first if block skipped 4.c. itt == 1 so enter second block 4.d. Do a `bind` that's completely ignored because it's never called or stored anywhere 5. Do a call to `test#hide`, which just logs it The wait to show event is coded like this: this.show.bind(this).delay(2); There, your bound function for `test#show` *is* used -- you're setting up a delayed call to it. A method hide on the same object occurs on document mouseover. One thing it does is to set this.active = false; This document mouseover could occur in the 2 second delay. I am expecting that setting this.active = false will cancel expanding the banner. It should, from what you've described. You've talked about mouseover and mouseout. For something like this, I'd use mouseenter and mouseleave instead. Prototype 1.6.1 and up emulate these on browsers that don't provide them (which is many of them; they were originally in IE only). mouseenter and mouseleave don't bubble, which in some situations is very useful. Here's an example using those events and an active flag with a delayed function call as you've described: http://jsbin.com/asefu4 Using an active flag like that has an issue: If the user mouses over the banner, mouses out, and then returns within the two seconds, the banner will expand almost immediately (as a result of the original two- second delay). Here's an example that uses the handle returned by Function#delay instead: http://jsbin.com/asefu4/2 HTH, -- T.J. Crowder Independent Software Engineer tj / crowder software / com www / crowder software / com On Sep 20, 2:12 am, kstubs kst...@gmail.com wrote: Does it mean: if I am using a member variable (ie., this.active = false;) who's value is true when I'm over the banner and if true then show the banner after specific wait time but if I cancel the variable because of another event, like mouseover the document, the method bound to the show() event is a copy, so this.active is true?? The wait to show event is coded like this: this.show.bind(this).delay(2); The show event has something like this: if(this.active) this.banner.addClassName('expanded'); A method hide on the same object occurs on document mouseover. One thing it does is to set this.active = false; This document mouseover could occur in the 2 second delay. I am expecting that setting this.active = false will cancel expanding the banner. Does this clear things up? Karl.. On Sep 19, 4:33 pm, kstubs kst...@gmail.com wrote: My Challenge: I have a banner on my website,www.meetscoresonline.com When you rollover the banner, the action to expand the banner will pause, expecting the user to remain on the banner to ensure he wishes the banner to expand. The banner should remain expanded until I leave the banner. Not sure why I am having so much trouble with this, but things like mouseout event is firing when I rollover objects contained by the banner at which time I should NOT collapse the banner. The banner should only collapse when the user mouses away from the banner. In my efforts to code this, I wrote up the test javascript and was trying to understand the behavior of binding the objects. Your explanation helps, but honestly I am still confused on the behavior of the test javascript code. Karl.. On Sep 19, 2:48 am, T.J. Crowder t...@crowdersoftware.com wrote: Hi, I can't quite make out what you're trying to do, but I can tell you why what you're doing isn't working: Function#bind[1] *returns* a new bound function, it doesn't change the original function at all. Since you're not assigning the return value to anything, it's not being used. You typically use #bind when you're passing a reference to a function that needs to be called with a specific context (`this` value) into something that doesn't provide any way for you to tell it what that context should be (like an event handler). What #bind does is create a new function that doesn't care what `this` value it's called with. The new function, when called, turns around and calls the original function with the `this` value you told it to use (as well as any curried arguments and then the actual arguments it was called with). Here's a classic event handler example: $('someElement').observe('click', myObj.myMethod.bind(myobj)); The above uses #bind to create a function that, when called, will turn around and call `myMethod` in the context of `myObj`. `myMethod` is not changed in any way. The return value of #bind is passed in as the