Binding Javascript Class Method with Element Event

S

sjkothenbeutel

I've been reading through quite a bit regarding this topic but am
finding myself confused.

Here is the scenario:

I have a javascript class defined with methods whereas each has
references to "this." As everyone is aware of, when you attach and
event from an element to a class method and the class method
references "this", the scope of "this" refers not to the class but
rather to the element firing the event.

So, lets consider the following code:

function objclass {
this.parentDiv = document.getElementById("parentdiv");
this.x = 0;
this.y = 0;

this.elementScrolled = elementScrolled;
this.createElement= createElement;
}

function elementScrolled() {
this.x = this.parentDiv.scrollLeft;
this.y = this.parentDiv.scrollTop;
alert(this.x + "x" + this.y);
}

function createElement() {
var element = document.createElement("div");
element.id = "parentdiv";
element.onscroll = this.elementScrolled();
this.parentDiv.appendChild(element);
}

If I run this code, the references to this.x and this.y return
nothing... or "undefined."

How do I solve this problem? I want to be able to access the "this"
reference within my event handler. Any quick fix suggestions?

Thank you!
 
B

Bjoern Hoehrmann

* (e-mail address removed) wrote in comp.lang.javascript:
I have a javascript class defined with methods whereas each has
references to "this." As everyone is aware of, when you attach and
event from an element to a class method and the class method
references "this", the scope of "this" refers not to the class but
rather to the element firing the event.

You can give your "class" a "method" 'handleEvent' inside of which
`this` will be bound to the object you registered, for example,

var T = { handleEvent: function(evt) { ... } };
document.addEventListener('click', T, false);

Other than that you'll have to store a reference to the desired
object in the function you are registering, for example, you could
just use something like function(evt) { obj.meth(evt); }.
 
S

sjkothenbeutel

* (e-mail address removed) wrote in comp.lang.javascript:


You can give your "class" a "method" 'handleEvent' inside of which
`this` will be bound to the object you registered, for example,

  var T = { handleEvent: function(evt) { ... } };
  document.addEventListener('click', T, false);

Other than that you'll have to store a reference to the desired
object in the function you are registering, for example, you could
just use something like function(evt) { obj.meth(evt); }.

mmmm... any chance you can show me how by altering my code? I'm still
confused. Also, I'm using IE.

thanks!
 
W

whitelined

mmmm... any chance you can show me how by altering my code? I'm still
confused. Also, I'm using IE.

thanks!

An alternative is a function that returns a function that uses apply to
bind this to the called function:

/*
* o = object
* f = function name
*/
function EventObjectBind(o, f)
{
return function(){o[f].apply(o, arguments)}
}


You use it like this:

element.onscroll = EventObjectBind(this, 'elementScrolled');
 
T

Thomas 'PointedEars' Lahn

Here is the scenario:

I have a javascript class

There is no such thing so far, the target implementations are
prototype-based object-oriented programming languages.

You have a _constructor_ for an object.
defined with methods whereas each has
references to "this." As everyone is aware of, when you attach and
event from an element to a class method and the class method
references "this", the scope of "this" refers not to the class but
rather to the element firing the event.

So much for "everyone" aware of something that does not even exist.
So, lets consider the following code:

function objclass {
this.parentDiv = document.getElementById("parentdiv");
this.x = 0;
this.y = 0;

this.elementScrolled = elementScrolled;
this.createElement= createElement;
}

function elementScrolled() {
this.x = this.parentDiv.scrollLeft;
this.y = this.parentDiv.scrollTop;
alert(this.x + "x" + this.y);
}

function createElement() {
var element = document.createElement("div");
element.id = "parentdiv";
element.onscroll = this.elementScrolled();

There isn't really a need for this method, your constructor can do all that.

You are assigning the return value of the method here instead of a reference
to it. But even if you omitted the `()', it will not work as desired
because the right-hand side would be just a reference to a Function object
that does not "know" of an owning object.

Therefore, you are looking for

var me = this;
element.onscroll = function() {
me.elementScrolled();
};

Besides, `onscroll' is a proprietary property that should be feature-tested
for before being used.

And for recent implementations it is unnecessary to declare the method globally:

objclass.prototype.elementScrolled = function(...) {
this.x = ...
...
};

Or, if you need a closure over the constructor's execution context:

function objclass(...)
{
...

this.elementScrolled = function(...) {
this.x = ...
...
};

...
}

By convention, your constructor identifier should begin with a capital
letter (here: at least Objclass, or probably something more descriptive);
other identifiers, except those for constants, should not.
this.parentDiv.appendChild(element);
}

If I run this code, the references to this.x and this.y return
nothing... or "undefined."

In fact, with your current code the event listener would never be called
because the premature method call returns `undefined' (as there is no
`return' statement in it that says otherwise) and so `undefined' is assigned
to the `onscroll' property.
How do I solve this problem? I want to be able to access the "this"
reference within my event handler. Any quick fix suggestions?

HTH

PointedEars
 

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

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top