Passing arguments to callback function in addEventListener

J

Janus

Hi,

Is there a way to pass arguments to the callback function used inside
an addEventListener?

I see that I can only list the name of the callback function.

For eg, I use this:

var boldLink=document.getElementById('cmtbold');
boldLink.addEventListener("click", rBold, true);

I need the id of boldLink to be accessible from inside the function
rBold()


Thanks in advance.

Deepak
 
V

VK

Janus said:
Is there a way to pass arguments to the callback function used inside
an addEventListener?
I see that I can only list the name of the callback function.

For eg, I use this:

var boldLink=document.getElementById('cmtbold');
boldLink.addEventListener("click", rBold, true);

I need the id of boldLink to be accessible from inside the function
rBold()

So where is the problem? Inside the event handler [this] points to the
element this handler is attached to:

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function rBold() {
window.alert(this.id);
}
function init() {
var boldLink=document.getElementById('cmtbold');
boldLink.addEventListener("click", rBold, true);
}
window.onload = init;
</script>
</head>
<body>
<p><a href="/" id="cmtbold">Click me</a></p>
</body>
</html>

Please note that IE doesn't support addEventListener and traditionally
used attachEvent method is made for all other purposes so rather
troublesome as a substitution for addEventListener.

addEventListener should be used only if you are planning to have one
event listened by several objects at once. Otherwise use the
conventional intrinsic event handler:

boldLink.onclick = rBold;
 
J

Janus

Thanks VK.
I cannot do without addEventListener because I am creating a
Greasemonkey user script.
The intrinsic event handler won't work with GM.

One more question:
Is there a way to pass other types of parameters? Like an integer?


Regards,
Deepak
Janus said:
Is there a way to pass arguments to the callback function used inside
an addEventListener?
I see that I can only list the name of the callback function.

For eg, I use this:

var boldLink=document.getElementById('cmtbold');
boldLink.addEventListener("click", rBold, true);

I need the id of boldLink to be accessible from inside the function
rBold()

So where is the problem? Inside the event handler [this] points to the
element this handler is attached to:

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function rBold() {
window.alert(this.id);
}
function init() {
var boldLink=document.getElementById('cmtbold');
boldLink.addEventListener("click", rBold, true);
}
window.onload = init;
</script>
</head>
<body>
<p><a href="/" id="cmtbold">Click me</a></p>
</body>
</html>

Please note that IE doesn't support addEventListener and traditionally
used attachEvent method is made for all other purposes so rather
troublesome as a substitution for addEventListener.

addEventListener should be used only if you are planning to have one
event listened by several objects at once. Otherwise use the
conventional intrinsic event handler:

boldLink.onclick = rBold;
 
E

Elegie

Janus wrote:

Hello,
Is there a way to pass arguments to the callback function used inside
an addEventListener?

Yes, but not directly. Instead of 'passing' the arguments, you should
rather think about making them accessible to the handler. Many patterns
are available.

[1] Make your variable available in the handler function scope chain, so
that it can reach it and use it. For instance, you could use some global
variable.

Ex:

---
var foo="Hello, World!";
obj.addEventListener(
"click",
function handler(evt){
alert(foo);
},
false
);
---

[2] Following the same idea, but being more precise, enclose your
handler into some local function expression, which will know the value
of the variable (or a way to retrieve it). You avoid namespace
pollution, at a cost of a function expression.

Ex:

---
obj.addEventListener(
"click",
(function(foo){
return function (evt){
alert(foo);
}
})("Hello, World!"),
false
);
---

[3] Add the property directly on the event target (as an expando
property), then you'll be able to retrieve it through the 'this' value
in your event handler.

Ex:
---
obj.foo="Hello, World!";
obj.addEventListener(
"click",
function handler(evt){
alert(this.foo);
},
false
);
---

[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface. The 'this' value will now
point to this object and not to the EventTarget anymore. You can then
define your expando properties on this object, like in [3]. Note that
the 'this' value resolution is not documented, so it may not be working
on some browsers (it's okay in Firefox and Opera 9, though).

Ex:

---
obj.addEventListener(
"click",
{foo:"Hello, World!", handleEvent:function(evt){alert(this.foo)}},
false
);
 
J

Janus

Thanks a lot, Elegie.

Janus wrote:

Hello,
Is there a way to pass arguments to the callback function used inside
an addEventListener?

Yes, but not directly. Instead of 'passing' the arguments, you should
rather think about making them accessible to the handler. Many patterns
are available.

[1] Make your variable available in the handler function scope chain, so
that it can reach it and use it. For instance, you could use some global
variable.

Ex:

---
var foo="Hello, World!";
obj.addEventListener(
"click",
function handler(evt){
alert(foo);
},
false
);
---

[2] Following the same idea, but being more precise, enclose your
handler into some local function expression, which will know the value
of the variable (or a way to retrieve it). You avoid namespace
pollution, at a cost of a function expression.

Ex:

---
obj.addEventListener(
"click",
(function(foo){
return function (evt){
alert(foo);
}
})("Hello, World!"),
false
);
---

[3] Add the property directly on the event target (as an expando
property), then you'll be able to retrieve it through the 'this' value
in your event handler.

Ex:
---
obj.foo="Hello, World!";
obj.addEventListener(
"click",
function handler(evt){
alert(this.foo);
},
false
);
---

[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface. The 'this' value will now
point to this object and not to the EventTarget anymore. You can then
define your expando properties on this object, like in [3]. Note that
the 'this' value resolution is not documented, so it may not be working
on some browsers (it's okay in Firefox and Opera 9, though).

Ex:

---
obj.addEventListener(
"click",
{foo:"Hello, World!", handleEvent:function(evt){alert(this.foo)}},
false
);
---


HTH,
Elegie.
 
R

Richard Cornford

Elegie wrote:
[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface.

That is very risky in javascript. The W3C ECMAScript bindings for the
EventListener interface effectively say that any _function_ is an
EventListener. The fact that some browsers also allow an object that
resembles a Java EventListener to be used (and object with specific
methods) is a non-specified extension.
The 'this' value will now
point to this object and not to the EventTarget anymore. You can then
define your expando properties on this object, like in [3]. Note that
the 'this' value resolution is not documented, so it may not be working
on some browsers (it's okay in Firefox and Opera 9, though).
<snip>

There should be no expectation of this working anywhere, so finding two
browsers where it does might be the full extent of support.

Richard.
 
E

Elegie

Richard said:
[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface.

That is very risky in javascript. The W3C ECMAScript bindings for the
EventListener interface effectively say that any _function_ is an
EventListener. The fact that some browsers also allow an object that
resembles a Java EventListener to be used (and object with specific
methods) is a non-specified extension.

Richard, the specification would then be poorly worded. The bindings
page states the existence of one "EventListener Function", how could you
tell it does not refer to the handleEvent function? All the more that
the bindings page mentions, in the EventTarget description, "objects
that implements the EventListener interface", and not "EventListener
Functions".

<URL:http://www.w3.org/TR/2006/WD-DOM-Level-3-Events-20060413/ecma-script-binding.html>

To me it would seem as if the direct use of the function would _not_ be
standard, but rather some implicitly accepted exception due to
historical reasons (for instance as the consequence of assigning
functions to regular HTML event attributes).

Of course, I would not be encouraging the use of the EventListener
interface in ECMAScript programs for that very reason, all the more that
the risk of it being broken in further versions of the environment would
probably not be the worth of using the construct. However, the OP
working in some identified environment (a GreaseMonkey script), I felt
that it would be relevant and interesting to mention the possibility
(especially for the particular 'this' value handling).
There should be no expectation of this working anywhere, so finding two
browsers where it does might be the full extent of support.

When I first read the specification, I had the expectation of it working
_anywhere_ in compliant user agents! Could the use of all other
interfaces be derived from the specification, except for the
EventListener interface?

By the way I do not have lots of browsers on this station, if you would
happen to know about some browsers supporting the DOM Event Model and
not allowing the use of EventListener as described, please let me know.


Regards,
Elegie.
 
R

Richard Cornford

Elegie said:
Richard said:
[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface.

That is very risky in javascript. The W3C ECMAScript bindings
for the EventListener interface effectively say that any
_function_ is an EventListener. The fact that some browsers also
allow an object that resembles a Java EventListener to be used
(and object with specific methods) is a non-specified extension.

Richard, the specification would then be poorly worded.

That may be true, though maybe only to the extent that trying to
misinterpret it remains too practical.

Previous versions were certainly less misleadingly worded, for example
the ECMAScript Binding for the November 2000 version of DOM Level 2
events describes EventListener as:-

| Object EventListener
| This is an ECMAScript function reference. This method has no
| return value. The parameter is a Event object.

and - EventTarget - as:-

| Object EventTarget
| The EventTarget object has the following methods:
| addEventListener(type, listener, useCapture)
| This method has no return value.
| The type parameter is of type String.
| The listener parameter is a EventListener object.
| The useCapture parameter is of type Boolean.
| removeEventListener(type, listener, useCapture)
| This method has no return value.
| The type parameter is of type String.
| The listener parameter is a EventListener object.
| The useCapture parameter is of type Boolean.
| dispatchEvent(evt)
| This method returns a Boolean.
| The evt parameter is a Event object.
| This method can raise a EventException object.

The version you cite has changed the wording of the bindings document,
but does not appear to have changed its intended meaning.
The bindings page states the existence of one
"EventListener Function",

And that is the _only_ definition of what an EventListener is in an
ECMAScript implementation: it is a function (that accepts an event
object as an argument and has no (explicit) return value).
how could you tell it does not refer to the handleEvent
function?

Compare the definition of EventListener with the definitions of
interfaces that include methods and properties. If EventListener was
intended to be anything but a function object then the bindings could
easily have expressed that.
All the more that the bindings page mentions, in the EventTarget
description, "objects that implements the EventListener interface",
and not "EventListener Functions".

Maybe not the best of expressions, but a function is an object and
implementing the " EventListener interface" involves being a function
(that accepts an event object as an argument and has no (explicit)
return value).
<URL:http://www.w3.org/TR/2006/WD-DOM-Level-3-Events-20060413/ecma-scrip
t-binding.html>

To me it would seem as if the direct use of the function would
_not_ be standard, but rather some implicitly accepted exception
due to historical reasons (for instance as the consequence of
assigning functions to regular HTML event attributes).

If that were the case I would expect to see the definition of
EventListener resemble EventTarget or Event, and explicitly state that
the interface has a method and the arguments and return values for that
method.
Of course, I would not be encouraging the use of the
EventListener interface in ECMAScript programs

If the EventListener interface is just a function object they why not?

By the way I do not have lots of browsers on this station,
if you would happen to know about some browsers supporting
the DOM Event Model and not allowing the use of EventListener
as described, please let me know.

The last time we discussed this subject here only Mozilla/Gecko browser
supported a Java-style version of EventListener. It looks like Opera
have seen it as expedient to add such support, but I don't know whether
Konqueror, Safari, NetFront, IceBrowser, etc. will have done so.

Richard.
 
E

Elegie

Richard Cornford wrote:

Previous versions were certainly less misleadingly worded, for example
the ECMAScript Binding for the November 2000 version of DOM Level 2
events describes EventListener as:-

<snip>

Granted, that description was much clearer, say, accurate.
The version you cite has changed the wording of the bindings document,
but does not appear to have changed its intended meaning.

Well, I am not familiar with W3C DOM orientations so wouldn't be able to
discuss it (and that would be off-topic), however I have to say that,
should I consider all versions of the specification, it would certainly
appear that its intended meaning may have changed as well!

Unfortunately, the change of wording has happened in Feb. 2002, and the
changes notes simply state: "This page needs update".

<URL:http://www.w3.org/TR/2002/WD-DOM-Level-3-Events-20020208/changes.html>

I have however found some discussions where they seem to have accepted
that EventListener could be Functions or Objects implementing the
EventListener interfaces. The following expresses their conclusion about
how the 'this' value should then be determined.

<URL:http://lists.w3.org/Archives/Public/public-webapi/2006Mar/0122.html>

Also, they have even been thinking about adding a handleEvent function
to the EventListener, stating that it would be referencing itself -
probably some kind of (awkward) compatibility bridge.

Compare the definition of EventListener with the definitions of
interfaces that include methods and properties. If EventListener was
intended to be anything but a function object then the bindings could
easily have expressed that.

Agreed, however on the other hand... would it have not been "easy" as
well to state that the EventListener *is* an ECMAScript function? They
did not do that.
If that were the case I would expect to see the definition of
EventListener resemble EventTarget or Event, and explicitly state that
the interface has a method and the arguments and return values for that
method.

Well in the actual specification the definition of EventListener is
similar to the EventTarget or Event ones, the bindings page simply fails
to properly mimic the change? Or even worse, does not do it because this
could mean some change in actual (W3C) implementations? :)

However my calling that an exception was, in the light of the link you
have provided, clearly an error : it was indeed the norm six years ago.
However I feel it is much more questionable now.
If the EventListener interface is just a function object they why not?

This specification, as of its last version (proposed six years after
than the one you cite), does not make it clear to me. I'd therefore
recommend the Function approach, however not arguing the respect of a
specification, but rather some back-compatibility aspect.
The last time we discussed this subject here only Mozilla/Gecko browser
supported a Java-style version of EventListener. It looks like Opera
have seen it as expedient to add such support, but I don't know whether
Konqueror, Safari, NetFront, IceBrowser, etc. will have done so.

Okay, thanks for the info.


Regards,
Elegie.
 
P

Paul

Richard said:
Elegie wrote:
[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface.

That is very risky in javascript. The W3C ECMAScript bindings for the
EventListener interface effectively say that any _function_ is an
EventListener. The fact that some browsers also allow an object that
resembles a Java EventListener to be used (and object with specific
methods) is a non-specified extension.
The 'this' value will now
point to this object and not to the EventTarget anymore. You can then
define your expando properties on this object, like in [3]. Note that
the 'this' value resolution is not documented, so it may not be working
on some browsers (it's okay in Firefox and Opera 9, though).
<snip>

There should be no expectation of this working anywhere, so finding two
browsers where it does might be the full extent of support.

Richard.

The OP mentioned he was developing a greasemonkey script for firefox.
 
R

Richard Cornford

Paul said:
Richard said:
Elegie wrote:
[4] Instead of passing the handler directly, pass some object
implementing the EventListener interface.

That is very risky in javascript. The W3C ECMAScript bindings for the
EventListener interface effectively say that any _function_ is an
EventListener. ...
The OP mentioned he was developing a greasemonkey script for firefox.

Being able to disregard the applicable standard because the context of
application allows more is not reason for doing so in itself.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top