Monday, March 26, 2012

Wish: ClientSide EventHandling By Reference

Hello to all!

I have discovered that event handling in the client side is done by copying the function into the event handler list array and not by referencing it. That is very bad I think. I wish for the next release of the MS Ajax Library an event handling by reference. Below is some code to make clear, what I am meaning.

1 Type.registerNamespace('Demo');23 Demo.Class1 = function () {4this.className ='this is class one';5 _evtHandler =new Sys.EventHandlerList();6 }7 Demo.Class1.prototype = {8 addDoSomethingEventHandler: function (handler) {9 _evtHandler.addHandler('onDoSomething', handler);10 },11 removeDoSomethingEventHandler: function (handler) {12 _evtHandler.removeHandler('onDoSomething', handler);13 },14 doSomething: function () {15 alert('I am doing something.');16 var f = _evtHandler.getHandler('onDoSomething');17if(f) {18 f();19 }20 },21 dispose: function() {22 alert('I am disposing now (' +this.className +')');23 }24 }25 Demo.Class1.registerClass('Demo.Class1',null, Sys.IDisposable);2627 Demo.Class2 = function (id) {28this.className ='this is class two.';29this._id = id30 }31 Demo.Class2.prototype = {32 methodOne: function () {33 alert('ID: ' +this._id +'\nMethod One knows that something is done.');34 },35 methodTwo: function () {36 alert('ID: ' +this._id +'\nMethod Two knows that something is done.');37 },38 methodThree: function () {39 alert('ID: ' +this._id +'\nMethod Three knows that something is done.');40 },41 dispose: function () {42 alert('I am disposing now (' +this.className +')');43 }44 }45 Demo.Class2.registerClass('Demo.Class2',null, Sys.IDisposable);4647 var obj1 =new Demo.Class1();48 var obj2 =new Demo.Class2('obj2');49 var obj3 =new Demo.Class2('obj3');5051 obj1.addDoSomethingEventHandler(obj2.methodOne);52 obj1.addDoSomethingEventHandler(obj2.methodTwo);53 obj1.addDoSomethingEventHandler(obj3.methodOne);54 obj1.doSomething();55 obj2.methodOne = function () {56 alert('Someone has overwritten me.');57 };58 obj1.removeDoSomethingEventHandler(obj2.methodOne);59 obj1.doSomething();60 obj2.methodOne();61 obj3.methodThree();

First observaion is that becauseobj2.methodOne() has been over written id couldn't removed from the event handler list. The second one is that the variablesthis._id are undefined when calling the functions by raising the event. Calling the methods directly from an instance does work, see line 61.

I need some workaround to save an instance, too, not only a copy of its methods in order their instance variables are not undefined. Any Ideas are welcome.

Yavuz

First of all your code seems to be buggy.

obj1.addDoSomethingEventHandler(obj2.methodOne);

When the methodOne is invoked the this pointer will not be obj2.

Here is the fix.

var fn = Function.createDelegate(obj2, obj2.methodOne);

obj1.addDoSomethingEventHandler(fn);

Now you can remove the handler using

obj1.removeDoSomethingEventHandler(fn);

This is unaffected whether or not you set obj2.methodOne to something else.


Hello Rama!

That was not a bug. It was a question how to solve this problemSmile Thank you for your answer.

Now the function is copied into the delegate. Ifobj2.methodOne() is changed, the changed method isn't invoked. But thats another story I think. It's a situation which occurs rarely i think where you have to change a method at run-time.

I could not find a documentation about theFunction.createDelegate() method. Have I to go through the debug.js-files?

Yavuz


Looks like it has been not documented yet. The doc writers missed it. There are two function Function.createCallback and Function.createDelegate, they are widely used in ASP.NET AJAX. You can look at the source as it is easy to understand utility.

I will do it. Thank you.

No comments:

Post a Comment