[Proto-Scripty] Re: Binding class method problem with this

2010-09-20 Thread kstubs
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

2010-09-19 Thread kstubs
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

2010-09-19 Thread kstubs
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

2010-09-19 Thread T.J. Crowder
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