473,320 Members | 2,071 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Event listeners/broadcasting solution

Hello,

I wanted to propose a small class that would help to overcome the
feature that's missing in MSIE. I'd like to get some feedback from
people and, perhaps, improvements in code/other ideas:

/************************************************** *****************************************
DCListener class
Description: provides basic event listener functionality
Interface :
contructor DCListener(obj, evt)
public void dispatch(evt)
public int addSubscriber(fnSubscriber)
public bool removeSubscriber(id)
public void unregister()
public static int id
public static {DCListener} index
************************************************** *****************************************/

function DCListener(obj, evt) {
var id = DCListener.id++;
this.id = id;
this.obj = obj;
this.evt = evt;
this.subscribers = {};
this.subId = 0;
this.save = obj.evt;

var listenerId = this.id;
obj[evt] = function() {
DCListener.index[listenerId].dispatch();
}

DCListener.index[id] = this;
}
DCListener.prototype.dispatch = function(evt) {
var subscribers = DCListener.index[this.id].subscribers;
for (var sub in subscribers) subscribers[sub](evt);
}
DCListener.prototype.addSubscriber = function(fnSubscriber) {
var id = this.subId++;
this.subscribers[id] = fnSubscriber;
return id;
}
DCListener.prototype.removeSubscriber = function(id) {
if (id in this.subscribers) {
delete this.subscribers[id];
return true;
} else {
return false;
}
}
DCListener.prototype.unregister = function() {
delete DCListener.index[this.id];
this.obj[this.evt] = this.save;
delete this.id;
delete this.obj;
delete this.evt;
delete this.subscribers;
delete this.subId;
delete this.save;
}
DCListener.id = 0;
DCListener.index = {};

********** end of code **********

Usage:

var lstDocumenOnClick = new DCListener(document, "onclick");
var idA = lstDocumenOnClick.addSubscriber(function() {
alert("[A] received document.onclick");
});
var idB = lstDocumenOnClick.addSubscriber(function() {
alert("[b] received document.onclick");
});
// Later, to remove the first subscriber:
lstDocumenOnClick.removeSubscriber(idA);

****************************************

This is just starting draft, and I know it needs some things to be
done about:
1) Passing the event object to every subscriber
2) Perhaps syncing the method naming with Mozilla event
listener/subscriber model.
3) Testing for memory leaks

Please, I am open to ideas, and I hope this thingy might be useful for
JS community.

Regards,

Pavils
Jul 23 '05 #1
2 1775
Pavils Jurjans wrote:

Hello,
I wanted to propose a small class that would help to overcome the
feature that's missing in MSIE.
Ah but it's not missing in IE, IE simply doesn't follow the W3C Events
model but its own model (which is inferior to the W3C's one IMHO) - the
methods you want to look at are attachEvent and detachEvent.
this.save = obj.evt;
You probably meant
this.save=obj[evt];

I note that you don't trigger the existing listener if there's one, this
might be a problem if your module is to interact with scripts setting
handlers the 'old' way.
DCListener.index[listenerId].dispatch();
You need to pass the evt object here, as you've noted in your "todos".
for (var sub in subscribers) subscribers[sub](evt);
Dispatching the handlers like this isn't enough, you should use "call"
to set the correct "this" value in the listener:

for (var sub in subscribers)
subscribers[sub].call(this.obj, evt);

This way, the "this" keyword will refer to the target element, like in a
element.onevent or element.addEventListener(...) (but not with
attachEvent, which unfortunately doesn't make the assignment).
Please, I am open to ideas, and I hope this thingy might be useful for
JS community.


I'm sure it will, the code's promising and your conception is strong
(I'd make the "dispatch", static members and DCListener private, though,
not public - a minor detail).

You might also want to look at a similar module written by Lasse
Reichstein Nielsen, less object-oriented than yours, but tackling all
relevant issues:

<URL:http://www.infimum.dk/privat/eventListener.js>
Regards,
Yep.
Jul 23 '05 #2
Thanks, Yann-Erwan for your suggestions, you really have an eagle's
eye

So, here comes an update code:
************************************************** *********
/************************************************** *****************************************
DCListener class
Description: provides basic event listener functionality
Interface :
private int id;
private object obj;
private string evtType;
private {Function} subscribers;
private int subId;
private int originalHandler;
contructor DCListener(obj, evt)
public void dispatch(evt)
public int addSubscriber(fnSubscriber)
public bool removeSubscriber(id)
public void unregister()
private static int id
private static {DCListener} index
************************************************** *****************************************/

function DCListener(obj, evtType) {
var id = DCListener.id++;
DCListener.index[id] = this;
this.id = id;
this.obj = obj;
this.evtType = evtType;
this.subscribers = {};
this.subId = 1;
this.originalHandler = obj[evtType] ?
this.addSubscriber(obj[evtType]): 0;
obj[evtType] = function(evt) {
evt = evt||window.event;
DCListener.index[id].dispatch(evt);
}
}
DCListener.prototype.dispatch = function(evt) {
var subscribers = DCListener.index[this.id].subscribers;
for (var subId in subscribers) subscribers[subId].call(this.obj,
evt);
}
DCListener.prototype.addSubscriber = function(fnSubscriber) {
var subId = this.subId++;
this.subscribers[subId] = fnSubscriber;
return subId;
}
DCListener.prototype.removeSubscriber = function(subId) {
if (subId in this.subscribers) {
delete this.subscribers[subId];
return true;
} else {
return false;
}
}
DCListener.prototype.unregister = function() {
delete DCListener.index[this.id];
if (this.originalHandler) this.obj[this.evtType] =
this.subscribers[this.originalHandler];
delete this.id;
delete this.obj;
delete this.evtType;
delete this.subscribers;
delete this.subId;
delete this.save;
}
DCListener.id = 0;
DCListener.index = {};

************************************************** *********

Some notes on your comments:
Ah but it's not missing in IE, IE simply doesn't follow the W3C Events
model but its own model (which is inferior to the W3C's one IMHO) - the
methods you want to look at are attachEvent and detachEvent.
Yes, I really missed that. But, this approach is quite poor, if
comparing with the one offered by W3C. It's a sad fact, that they
still prefer to stay away from standards.
I note that you don't trigger the existing listener if there's one, this
might be a problem if your module is to interact with scripts setting
handlers the 'old' way.
It's fixed now. The original handler becomes the first subscriber.
You need to pass the evt object here, as you've noted in your "todos".
Implemented.
Dispatching the handlers like this isn't enough, you should use "call"
to set the correct "this" value in the listener:

for (var sub in subscribers)
subscribers[sub].call(this.obj, evt);

This way, the "this" keyword will refer to the target element, like in a
element.onevent or element.addEventListener(...) (but not with
attachEvent, which unfortunately doesn't make the assignment).
That's right, I foregone the scope issue. It's fixed now.
I'm sure it will, the code's promising and your conception is strong
(I'd make the "dispatch", static members and DCListener private, though,
not public - a minor detail).
Of course, all the talk about private/public is pretty irrelevant,
since there are no private methods in JS. Well, they can be mastered
via closures tho. But, I prefer to use this notation in the interface
description, so that developer would honor it.

I think you mistyped, saying you'd like to see "DCListener" private,
as it's the class name ;) Regarding the dispatch method, I think it's
cool to let it be public, because it allows to 1)provoke the event
triggering from code; and 2) Create your own custom objects that can
issue events and can have subscribers attached:

var lstDocumentOnPress = new DCListener(document, "onkeydown");

var subA = lstDocumentOnPress.addSubscriber(function(evt) {
var charCode = event.keyCode ? event.keyCode : e.which;
document.f.traceA.value = "A has received the event: " + charCode;
});
var subB = lstDocumentOnPress.addSubscriber(function(evt) {
var charCode = event.keyCode ? event.keyCode : e.which;
document.f.traceB.value = "B has received the event: " + charCode;
if (charCode == 32) lstCustomObjectEvt.dispatch();
});

var myCustomObject = {};
var lstCustomObjectEvt = new DCListener(myCustomObject, "evt");
lstCustomObjectEvt.addSubscriber(function() {
alert("Hey, I've got custom event!");
});

<body>
<form name="f">
<input type="text" name="traceA" size="50"/><br/>
<input type="text" name="traceB" size="50"/>
</form>
</body>
You might also want to look at a similar module written by Lasse
Reichstein Nielsen, less object-oriented than yours, but tackling all
relevant issues:
<URL:http://www.infimum.dk/privat/eventListener.js>


I will surely have some study of his work. It's quite hard to read it,
as it has no much comments :),

Rgds,

Pavils
Jul 23 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Amir Hardon | last post by:
I am dynamically adding rows to a table, and each row have a button which removes it. I have successfully implemented this for mozilla but I'm having troubles with IE, here is how I did it: ...
2
by: kj | last post by:
How does one trigger an event programmatically? I'm interested in how to do this in both the "Level 0" event model as well as in the DOM Level 2 event model. Thanks! kj -- NOTE: In my...
17
by: abs | last post by:
My element: <span onclick="alert('test')" id="mySpan">test</span> Let's say that I don't know what is in this span's onclick event. Is it possible to add another action to this element's onclick...
0
by: Kamilche | last post by:
''' event.py An event manager using publish/subscribe, and weakrefs. Any function can publish any event without registering it first, and any object can register interest in any event, even...
1
by: Marek Murin | last post by:
Hi all, I have created vb.net user control that has to be used by vb6 form. Everything goes well with putting the vb.net user control on the VB6 form until I want to receive any event from my...
0
by: Eniac | last post by:
Hello, I've started using Enterprise Library 2.0 recently and I've encountered a problem that seems to be ... well... undocumented :) Basically, when I set a Trace Listener (formatted event...
2
by: meyousikmann | last post by:
This will be difficult to explain so bear with me. If anyone is familiar with Tibco Rendezvous and/or Microsoft Messaging, this may make more sense. I've created a hierarchy of objects that...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.