JavaScript Graphics Library (JSGL.org) Draw and move interactive vector graphics easily in Javascript!

jsgl.util.delegate

jsgl.util.delegate is a simple, yet powerful utility, which allows you to pair functions with objects on which the functions should be executed as methods.

Consider the following example:

function MyClass() {
  this.x = 10;
}
MyClass.prototype.foo = function() {
  alert(this.x);
}
 
var myInstance = new MyClass();
window.setTimeout(myInstance.foo, 1000); // will alert "undefined"

The above code will prompt undefined, because, at the time of execution, the foo function is not linked to the myInstance object – it is simply an anonymous function, which substitutes this with the global object at the time of execution. It is because the function has been passed as an argument.

In many situations, however, when passing function as an argument, you might like to execute the function as a method of some given object. This is when jsgl.util.delegate becomes useful:

window.setTimeout(jsgl.util.delegate(myInstance, myInstance.foo), 1000); // prints "10"

The above code creates a new function, which actually executes the myInstance.foo function as a method of myInstance.

Working with Event Handlers

The above shown principle is very useful also when working with event handlers (not just in JSGL, but also in DHTML in general).

Again, consider a more complicated example:

function MyCircleWrapper(panel) { // constructor
 
  this.circle = panel.createCircle();
  panel.addCircle(this.circle);
  this.circle.setRadius(30);
  with(this.circle.getStroke()) {
    setColor('blue');
    setWeight(5);
  }
  this.circle.addMouseOverListener(this.mouseOver); // wrong!
  this.circle.addMouseOverListener(this.mouseOut); // wrong!
}
 
MyCircleWrapper.prototype.mouseOver = function() { // method
  this.circle.getStroke().setColor('red');
}
 
MyCircleWrapper.prototype.mouseOut = function() { // method
  this.circle.getStroke().setColor('blue');
}
 
MyCircleWrapper.prototype.moveCircle(x,y) { // method
  this.circle.setLocationXY(x,y);
}

The above-example will throw unhandled exception whenever the circle is moved over or out of the circle with the mouse pointer. Again, it is because the functions registered as mouse listeners do not have any connection to the proper MyCircleWrapper instance.

Following the above example, you can fix the problem using jsgl.util.delegate:

...
  this.circle.addMouseOverListener(jsgl.util.delegate(this, this.mouseOver));
  this.circle.addMouseOutListener(jsgl.util.delegate(this, this.mouseOut));
...
 
delegate.txt · Last modified: 2013/03/14 03:16 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license: GNU Free Documentation License 1.3
Driven by DokuWiki Powered by PHP Valid XHTML 1.0 Valid CSS