Jeremy wrote:
I want each instance of an object to be able to listen for input events.
When the event occurs, a method of the object should be called, such
that "this" is in scope and refers to the object instance.
All function objects have a this value that is established when the
function is called, not when you declare it. You can modify the object
used for the this value using the function's apply() or call() methods.
The usual method is to use the this keyword to create a reference back
to the object when you attach the event, not try to get a reference to
the object at some later time. You might also consider simply adding
the property to a prototype object at an appropriate point in the scope
chain and avoid munging the this keyword altogether.
Is this possible?
Example:
function MyConstructor(e lement)
{
//element is some HTML element
this.addListene rs(element);
this.foo = "Bar";
return this;
}
MyConstructor.p rototype.addLis teners = function(elemen t)
{
element.addEven tListener("keyp ress", this.doSomethin g, true);
Is this only for W3C browers? You seem to be ignoring IE's attachEvent.
}
MyConstructor.p rototype.doSome thing = function(e)
{
alert(this.foo. length); //Error: this.foo has no properties
Because the foo property belongs to the (possibly anonymous) object
that was used to attach the event, which is not what the this keyword
will refer to when the event calls the function.
In Gecko browsers, the this keyword will refer to the HTML element that
the event is attached to. In IE, it will refer to the window/global
object.
alert(this);
//shows the HTML element that triggered the event
Or the window object in IE. Try replacing the body of the addListeners
function with:
var obj = this;
element.onkeypr ess = function(){
obj.doSomething .apply(obj);
}
But the closure will likely cause a memory leak in IE. If you really
want to use attachEvent, try:
var obj = this;
if (element.addEve ntListener){
element.addEven tListener(
'keyup',
function() {obj.doSomethin g.apply(obj)},
true
);
} else if (element.attach Event){
element.attachE vent(
'onkeyup',
function() {obj.doSomethin g.apply(obj)}
);
}
Again you have a closure/memory leak issue in IE.
}
Is there any way to get "this" to refer to the object in the event listener?
Another strategy is to add a property to the element that points back
to the object and use the event to find the target/source element and
hence get the foo property:
MyConstructor.p rototype.addLis teners = function(elemen t)
{
element.srcObj = this;
if (element.addEve ntListener){
element.addEven tListener('keyu p', this.doSomethin g, true);
} else if (element.attach Event){
element.attachE vent('onkeyup', this.doSomethin g);
}
}
MyConstructor.p rototype.doSome thing = function(e)
{
var e = e || window.event;
var tgt = e.target || e.srcElement;
alert(tgt.srcOb j.foo);
}
--
Rob