[Proto-Scripty] Re: Anchor button triggers window.onbeforeunload in IE

2010-10-25 Thread T.J. Crowder
@JoJo:

I start this off responding to Eric, but there's some info (useful, I
hope) for you below as well.

@Eric:

> T.J.'s blog has many very well written articles that will explain you
> why...

You're very kind!! :-)

> Also note that I am 80% sure (please somebody confirm) that since your
> parameter is a local variable, javascript will implicitly create a
> closure for you.

Not *implicitly*, no, but your rewrite has an explicit closure and
should absolutely work.

You probably know this, but JoJo's mechanism (or, as you point out,
Function#curry) is necessary in situations where you're going to
change `localVariable` later, for instance loops:

var index, localVariable;
for (index = 0; index < 10; ++index) {
localVariable = "Hi, I'm index " + index;
dynamicAnchor = new Element(
    'a', {
        href: 'javascript:void(0)'
    }
).observe(
    'click',
    function(event) {   // <=== Problem
        window.status = localVariable;
        event.stop();
    }
);
}

The above would create a bunch of anchors *all* of which would show
the message "Hi, I'm index 9", because that's the value of
`localVariable` at the end of the loop. So instead, you need to do
something like what JoJo did, though if you do *exactly* what JoJo did
in a loop, it has to create the factory function on every loop, which
is unnecessary as it's invariant:

var index, localVariable;
for (index = 0; index < 10; ++index) {
localVariable = "I'm index " + index;
dynamicAnchor = new Element(
'a', {
href: 'javascript:void(0)'
};
).observe(
'click',
(function(parameter) { // <== This factory function gets
duplicated
return function(event) {
window.status = parameter;
Event.stop(event);
}
})(localVariable);
);
}

Since nothing keeps a reference to the factory functions, it doesn't
matter much.

@JoJo:

Like Eric, I'd probably use Function#curry. FWIW, this is how I'd
write it:

// Somewhere useful where I can reuse it, because this looks like
// something we'll need to do somewhere else, too
function showStatMsgAndStopHandler(message, event) {
window.status = message;
event.stop();
}

// Use it
dynamicAnchor = new Element(
'a', {
href: 'javascript:void(0)'
};
).observe(
'click',
showStatMsgAndStopHandler.curry(localVariable)
);

A couple of reasons I'd do it that way:

1. Reuse
2. Well-controlled closures
3. I'm a fan of named functions rather than anonymous ones[1] ;-)
4. Readability (maybe)

With the rewrite, _nothing_ closes over the local variables in the
context in which this dynamic anchor is being created. Assuming you
define `showStatMsgAndStopHandler` in a place you're defining other
generally-useful stuff, the only closures in the rewrite are generated
in the well-controlled scope of Function#curry. So we're not keeping
stuff in memory we don't need.

[1] http://blog.niftysnippets.org/2010/03/anonymouses-anonymous.html

HTH,
--
T.J. Crowder
Independent Software Engineer
tj / crowder software / com
www / crowder software / com

On Oct 25, 4:10 pm, Eric  wrote:
> Hi JoJo,
>
> It seems you're doing a closure "by hand". You may want to look at
> Function.bind() or Function.curry() in prototype documentation, since
> they do it for you.
> Your solution may become :
> dynamicAnchor = new Element(
>     'a', {
>         href: 'javascript:void(0)'
>     }
> ).observe(
>     'click',
>     (function(parameter,event) {
>         window.status = parameter;
>         event.stop();
>     }).curry(localVariable)
> );
>
> Also note that I am 80% sure (please somebody confirm) that since your
> parameter is a local variable, javascript will implicitly create a
> closure for you.
>
> In other words, this should work:
> var localVariable= 'Hi!';
> dynamicAnchor = new Element(
>     'a', {
>         href: 'javascript:void(0)'
>     }
> ).observe(
>     'click',
>     function(event) {
>         window.status = localVariable;
>         event.stop();
>     }
> );
>
> T.J.'s blog has many very well written articles that will explain you
> why (http://blog.niftysnippets.org/search/label/closures).
>
> Eric
>
> On Oct 22, 8:47 pm, JoJo  wrote:
>
>
>
>
>
>
>
> > Thanks T.J.
>
> > The solution is:
>
> > dynamicAnchor = new Element(
> >     'a', {
> >         href: 'javascript:void(0)'
> >     }
> > ).observe(
> >     'click',
> >     function(parameter) {
> >         return function(event) {
> >             window.status = parameter;
> >             Event.stop(event);
> >         }
> >     }(localVariable)
> > );
>
> > On Oct 22, 4:39 am, "T.J. Crowder"  wrote:
>
> > > Hi,
>
> > > See the documentation for `Event.observe`[1] (which is what you're
> > > calling indirectly from the `Element#observe` function), specifically
> > > the "Preventing the Default Event Action and Bubbling" part, and the
> > > `Event` object[2]: You don't return fa

[Proto-Scripty] Re: Anchor button triggers window.onbeforeunload in IE

2010-10-25 Thread T.J. Crowder
Hi,

On Oct 22, 7:47 pm, JoJo  wrote:
> Thanks T.J.
>
> The solution is:
> ...

FWIW, it's a bit off-topic, but regarding your code where you're
defining and then calling a function:

function(parameter) {
// ...
}(localVariable)

To ensure that that works reliably across implementations, you'll want
to wrap the function expression in parentheses:

(function(parameter) {
// ...
})(localVariable)

I don't remember my source for the information, but I remember that I
trusted the source. It seems to me your version _should_ work
according to the spec, and I know it does for other things, but I
think some significant implementation has an issue with generating the
call without clarifying it as with the parens above.

Happy coding,
--
T.J. Crowder
Independent Software Engineer
tj / crowder software / com
www / crowder software / com

On Oct 22, 7:47 pm, JoJo  wrote:
> Thanks T.J.
>
> The solution is:
>
> dynamicAnchor = new Element(
>     'a', {
>         href: 'javascript:void(0)'
>     }
> ).observe(
>     'click',
>     function(parameter) {
>         return function(event) {
>             window.status = parameter;
>             Event.stop(event);
>         }
>     }(localVariable)
> );
>
> On Oct 22, 4:39 am, "T.J. Crowder"  wrote:
>
>
>
>
>
>
>
> > Hi,
>
> > See the documentation for `Event.observe`[1] (which is what you're
> > calling indirectly from the `Element#observe` function), specifically
> > the "Preventing the Default Event Action and Bubbling" part, and the
> > `Event` object[2]: You don't return false to cancel the `click` event,
> > you use the `Event#preventDefault` function (which is a standard DOM
> > function[3] that Prototype ensures is present even on implementations
> > that lack it) or, more likely, `Event#stop`[4] which both prevents the
> > default action and stops the event bubbling.
>
> > [1]http://api.prototypejs.org/dom/event/observe/
> > [2]http://api.prototypejs.org/dom/event/
> > [3]http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-prev...
> > [4]http://api.prototypejs.org/dom/event/stop/
>
> > HTH,
> > --
> > T.J. Crowder
> > Independent Software Engineer
> > tj / crowder software / com
> > www / crowder software / com
>
> > On Oct 22, 2:41 am, JoJo  wrote:
>
> > > I use anchors to call javascript functions. Usually, I do this:
>
> > > 
> > >    call the function
> > > 
>
> > > This works fine in all browsers. Window.onbeforeunload is never
> > > triggered because the ONCLICK returns false, and thus the HREF if not
> > > executed. When HREF is not executed, the browser does not believe that
> > > the window in unloading. Now, I'm trying to create a dynamic anchor to
> > > accomplish the same thing. It looks nearly identical to the HTML
> > > anchor, but now it's triggering window.onbeforeunload in IE8. How do I
> > > not trigger it?
>
> > > dynamicAnchor = new Element(
> > >     'a', {
> > >         href: 'javascript:void(0)',
> > >     }
> > > ).observe(
> > >     'click',
> > >     function(parameter) {
> > >         return function() {
> > >             window.status = parameter;
> > >             return false;
> > >         }
> > >     }(localVariable)
> > > );

-- 
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: Anchor button triggers window.onbeforeunload in IE

2010-10-25 Thread Eric
Hi JoJo,

It seems you're doing a closure "by hand". You may want to look at
Function.bind() or Function.curry() in prototype documentation, since
they do it for you.
Your solution may become :
dynamicAnchor = new Element(
'a', {
href: 'javascript:void(0)'
}
).observe(
'click',
(function(parameter,event) {
window.status = parameter;
event.stop();
}).curry(localVariable)
);

Also note that I am 80% sure (please somebody confirm) that since your
parameter is a local variable, javascript will implicitly create a
closure for you.

In other words, this should work:
var localVariable= 'Hi!';
dynamicAnchor = new Element(
'a', {
href: 'javascript:void(0)'
}
).observe(
'click',
function(event) {
window.status = localVariable;
event.stop();
}
);

T.J.'s blog has many very well written articles that will explain you
why (http://blog.niftysnippets.org/search/label/closures).

Eric

On Oct 22, 8:47 pm, JoJo  wrote:
> Thanks T.J.
>
> The solution is:
>
> dynamicAnchor = new Element(
>     'a', {
>         href: 'javascript:void(0)'
>     }
> ).observe(
>     'click',
>     function(parameter) {
>         return function(event) {
>             window.status = parameter;
>             Event.stop(event);
>         }
>     }(localVariable)
> );
>
> On Oct 22, 4:39 am, "T.J. Crowder"  wrote:
>
> > Hi,
>
> > See the documentation for `Event.observe`[1] (which is what you're
> > calling indirectly from the `Element#observe` function), specifically
> > the "Preventing the Default Event Action and Bubbling" part, and the
> > `Event` object[2]: You don't return false to cancel the `click` event,
> > you use the `Event#preventDefault` function (which is a standard DOM
> > function[3] that Prototype ensures is present even on implementations
> > that lack it) or, more likely, `Event#stop`[4] which both prevents the
> > default action and stops the event bubbling.
>
> > [1]http://api.prototypejs.org/dom/event/observe/
> > [2]http://api.prototypejs.org/dom/event/
> > [3]http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-prev...
> > [4]http://api.prototypejs.org/dom/event/stop/
>
> > HTH,
> > --
> > T.J. Crowder
> > Independent Software Engineer
> > tj / crowder software / com
> > www / crowder software / com
>
> > On Oct 22, 2:41 am, JoJo  wrote:
>
> > > I use anchors to call javascript functions. Usually, I do this:
>
> > > 
> > >    call the function
> > > 
>
> > > This works fine in all browsers. Window.onbeforeunload is never
> > > triggered because the ONCLICK returns false, and thus the HREF if not
> > > executed. When HREF is not executed, the browser does not believe that
> > > the window in unloading. Now, I'm trying to create a dynamic anchor to
> > > accomplish the same thing. It looks nearly identical to the HTML
> > > anchor, but now it's triggering window.onbeforeunload in IE8. How do I
> > > not trigger it?
>
> > > dynamicAnchor = new Element(
> > >     'a', {
> > >         href: 'javascript:void(0)',
> > >     }
> > > ).observe(
> > >     'click',
> > >     function(parameter) {
> > >         return function() {
> > >             window.status = parameter;
> > >             return false;
> > >         }
> > >     }(localVariable)
> > > );
>
>

-- 
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: Anchor button triggers window.onbeforeunload in IE

2010-10-22 Thread JoJo
Thanks T.J.

The solution is:

dynamicAnchor = new Element(
'a', {
href: 'javascript:void(0)'
}
).observe(
'click',
function(parameter) {
return function(event) {
window.status = parameter;
Event.stop(event);
}
}(localVariable)
);

On Oct 22, 4:39 am, "T.J. Crowder"  wrote:
> Hi,
>
> See the documentation for `Event.observe`[1] (which is what you're
> calling indirectly from the `Element#observe` function), specifically
> the "Preventing the Default Event Action and Bubbling" part, and the
> `Event` object[2]: You don't return false to cancel the `click` event,
> you use the `Event#preventDefault` function (which is a standard DOM
> function[3] that Prototype ensures is present even on implementations
> that lack it) or, more likely, `Event#stop`[4] which both prevents the
> default action and stops the event bubbling.
>
> [1]http://api.prototypejs.org/dom/event/observe/
> [2]http://api.prototypejs.org/dom/event/
> [3]http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-prev...
> [4]http://api.prototypejs.org/dom/event/stop/
>
> HTH,
> --
> T.J. Crowder
> Independent Software Engineer
> tj / crowder software / com
> www / crowder software / com
>
> On Oct 22, 2:41 am, JoJo  wrote:
>
> > I use anchors to call javascript functions. Usually, I do this:
>
> > 
> >    call the function
> > 
>
> > This works fine in all browsers. Window.onbeforeunload is never
> > triggered because the ONCLICK returns false, and thus the HREF if not
> > executed. When HREF is not executed, the browser does not believe that
> > the window in unloading. Now, I'm trying to create a dynamic anchor to
> > accomplish the same thing. It looks nearly identical to the HTML
> > anchor, but now it's triggering window.onbeforeunload in IE8. How do I
> > not trigger it?
>
> > dynamicAnchor = new Element(
> >     'a', {
> >         href: 'javascript:void(0)',
> >     }
> > ).observe(
> >     'click',
> >     function(parameter) {
> >         return function() {
> >             window.status = parameter;
> >             return false;
> >         }
> >     }(localVariable)
> > );

-- 
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: Anchor button triggers window.onbeforeunload in IE

2010-10-22 Thread T.J. Crowder
Hi,

See the documentation for `Event.observe`[1] (which is what you're
calling indirectly from the `Element#observe` function), specifically
the "Preventing the Default Event Action and Bubbling" part, and the
`Event` object[2]: You don't return false to cancel the `click` event,
you use the `Event#preventDefault` function (which is a standard DOM
function[3] that Prototype ensures is present even on implementations
that lack it) or, more likely, `Event#stop`[4] which both prevents the
default action and stops the event bubbling.

[1] http://api.prototypejs.org/dom/event/observe/
[2] http://api.prototypejs.org/dom/event/
[3] 
http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-preventDefault
[4] http://api.prototypejs.org/dom/event/stop/

HTH,
--
T.J. Crowder
Independent Software Engineer
tj / crowder software / com
www / crowder software / com

On Oct 22, 2:41 am, JoJo  wrote:
> I use anchors to call javascript functions. Usually, I do this:
>
> 
>    call the function
> 
>
> This works fine in all browsers. Window.onbeforeunload is never
> triggered because the ONCLICK returns false, and thus the HREF if not
> executed. When HREF is not executed, the browser does not believe that
> the window in unloading. Now, I'm trying to create a dynamic anchor to
> accomplish the same thing. It looks nearly identical to the HTML
> anchor, but now it's triggering window.onbeforeunload in IE8. How do I
> not trigger it?
>
> dynamicAnchor = new Element(
>     'a', {
>         href: 'javascript:void(0)',
>     }
> ).observe(
>     'click',
>     function(parameter) {
>         return function() {
>             window.status = parameter;
>             return false;
>         }
>     }(localVariable)
> );

-- 
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.