dyndan
28 Aug 2008, 4:43 AM
Hi people,
in some cases loopy code or extensive use of event firing can lead to unwanted multiple attachments of a listener.
To avoid this, I added the option "addOnce" to the addListener function options (like single, delay, buffer, see http://extjs.com/deploy/dev/docs/?class=Ext.util.Observable).
This allows you to do the following:
this.myMultipleTimesCalledFunction = function(outerArgs) {
//Note that listener function should not deal with outerArgs in case of "addOnce=true".
this.on("test", function(args) {
alert("test listener handled args="+args);
}, this, {
single : true,
addOnce : true
});
}
"addOnce = true" manages addListener in a way that prevents the same listener function for the same scope is added more than once.
Code:
Ext.util.Event.prototype.orgAddListener = Ext.util.Event.prototype.addListener;
Ext.util.Event.prototype.addListener = function(fn, scope, options) {
function hashCode(str) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = (31 * hash + str.charCodeAt(i)) % 99999999;
}
return hash;
}
var add = true;
if (options.addOnce) {
var fnHash = hashCode(fn.toString());
for (var i = 0, len = this.listeners.length; i < len; i++) {
if (this.listeners[i].scope == scope) {
if (!this.listeners[i].fnHash)
this.listeners[i].fnHash = hashCode(this.listeners[i].fn
.toString());
if (this.listeners[i].fnHash == fnHash) {
add = false;
break;
}
}
}
}
if (add)
this.orgAddListener(fn, scope, options);
}
By the way:
I checked event handling in Ext.util.Observable and I came to the conclusion that event firing through fireEvent does not support custom arguments as explained here (method addListener):
el.on('click', this.onClick, this, {
single: true,
delay: 100,
forumId: 4 //This is not supported
});
(Please correct me if I am wrong.)
I do not miss this feature cause the following does it just fine:
this.fooFunction = function(fooArgs) {
this.on("test", function() {
firstTestFunction(fooArgs);
}, this);
this.on("test", function(invokingArgs) {
secondTestFunction(invokingArgs);
}, this, {
addOnce : true
});
}
this.myInvokingFunction = function(invokingArgs) {
this.fireEvent("test",invokingArgs);
}
MyObject.fooFunction("Args of first call");
MyObject.fooFunction("Args of second call");
MyObject.myInvokingFunction("Something else");
In this example "firstTestFunction" gets called twice. The first call gets passed in "Args of first call" and the second call gets passed in "Args of second call", "secondTestFunction" gets called once with passed in "Something else".
dyndan
in some cases loopy code or extensive use of event firing can lead to unwanted multiple attachments of a listener.
To avoid this, I added the option "addOnce" to the addListener function options (like single, delay, buffer, see http://extjs.com/deploy/dev/docs/?class=Ext.util.Observable).
This allows you to do the following:
this.myMultipleTimesCalledFunction = function(outerArgs) {
//Note that listener function should not deal with outerArgs in case of "addOnce=true".
this.on("test", function(args) {
alert("test listener handled args="+args);
}, this, {
single : true,
addOnce : true
});
}
"addOnce = true" manages addListener in a way that prevents the same listener function for the same scope is added more than once.
Code:
Ext.util.Event.prototype.orgAddListener = Ext.util.Event.prototype.addListener;
Ext.util.Event.prototype.addListener = function(fn, scope, options) {
function hashCode(str) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = (31 * hash + str.charCodeAt(i)) % 99999999;
}
return hash;
}
var add = true;
if (options.addOnce) {
var fnHash = hashCode(fn.toString());
for (var i = 0, len = this.listeners.length; i < len; i++) {
if (this.listeners[i].scope == scope) {
if (!this.listeners[i].fnHash)
this.listeners[i].fnHash = hashCode(this.listeners[i].fn
.toString());
if (this.listeners[i].fnHash == fnHash) {
add = false;
break;
}
}
}
}
if (add)
this.orgAddListener(fn, scope, options);
}
By the way:
I checked event handling in Ext.util.Observable and I came to the conclusion that event firing through fireEvent does not support custom arguments as explained here (method addListener):
el.on('click', this.onClick, this, {
single: true,
delay: 100,
forumId: 4 //This is not supported
});
(Please correct me if I am wrong.)
I do not miss this feature cause the following does it just fine:
this.fooFunction = function(fooArgs) {
this.on("test", function() {
firstTestFunction(fooArgs);
}, this);
this.on("test", function(invokingArgs) {
secondTestFunction(invokingArgs);
}, this, {
addOnce : true
});
}
this.myInvokingFunction = function(invokingArgs) {
this.fireEvent("test",invokingArgs);
}
MyObject.fooFunction("Args of first call");
MyObject.fooFunction("Args of second call");
MyObject.myInvokingFunction("Something else");
In this example "firstTestFunction" gets called twice. The first call gets passed in "Args of first call" and the second call gets passed in "Args of second call", "secondTestFunction" gets called once with passed in "Something else".
dyndan