Implementing events in my own object

I want to have a custom object that provides some events. For example:

var CustomObjectTextChangedEventName = 'textChanged'; var CustomObject = function () { var _this = this; var _text = ""; _this.OnTextChanged = document.createEvent("Event"); _this.OnTextChanged.initEvent(CustomObjectTextChangedEventName, true, false); _this.ChangeText = function (newText) { _text = newText; fireTextChanged(); }; function fireTextChanged() { _this.dispatchEvent(_this.OnTextChanged); } } 

The code for using the event will look like this:

 myCustomObject = new CustomObject(); myCustomObject.addEventListener(CustomObjectTextChangedEventName, handleTextChanged, false); 

As you can see ... the default way to use events in JS. But I can't make him worry ...

Currently my problem is that my object does not implement "addEventListener" and "dispatchEvent". But these functions are normally implemented from the "element" ...

Can I make them available somehow or should I implement them myself? How should I implement them? Should I do my own event handling? (with an internal list of handlers, the "add" and "delete" -handler function and fire with each handler when I want to fire an event)

Hello!

+9
javascript javascript-events
Jun 11 '12 at 10:22
source share
3 answers

The addEventListener function is a method of the Element class. One way is to make CustomObject inherit from Element as follows:

 CustomObject.prototype = Element.prototype; 

The problem is that the Element class may have different implementations among different browsers. So, for example, dismissal can be difficult (see this post ).

Therefore, I advise you to do it yourself. It is not difficult, try something like this:

 var CustomObject = function () { var _this = this; _this.events = {}; _this.addEventListener = function(name, handler) { if (_this.events.hasOwnProperty(name)) _this.events[name].push(handler); else _this.events[name] = [handler]; }; _this.removeEventListener = function(name, handler) { /* This is a bit tricky, because how would you identify functions? This simple solution should work if you pass THE SAME handler. */ if (!_this.events.hasOwnProperty(name)) return; var index = _this.events[name].indexOf(handler); if (index != -1) _this.events[name].splice(index, 1); }; _this.fireEvent = function(name, args) { if (!_this.events.hasOwnProperty(name)) return; if (!args || !args.length) args = []; var evs = _this.events[name], l = evs.length; for (var i = 0; i < l; i++) { evs[i].apply(null, args); } }; } 

Now using it is as simple as:

 var co = new CustomObject(); co.addEventListener('textChange', function(name) { console.log(name); }); co.fireEvent('textChange', ['test']); 

This is a basic solution. You can change it, but I think you should understand this idea.

+15
Jun 11 '12 at 11:17
source share

I am not 100% sure, but the following is the result of my old research on this issue:

  • You cannot do it somehow.
  • You can simply implement your own logic. For this, you can use the code that exists in the MDN element.removeEventListener with a few changes. Below it copies \ past code from MDN link:



 // code source: MDN: https://developer.mozilla.org/en/DOM/element.removeEventListener // without changes if (!Element.prototype.addEventListener) { var oListeners = {}; function runListeners(oEvent) { if (!oEvent) { oEvent = window.event; } for (var iLstId = 0, iElId = 0, oEvtListeners = oListeners[oEvent.type]; iElId < oEvtListeners.aEls.length; iElId++) { if (oEvtListeners.aEls[iElId] === this) { for (iLstId; iLstId < oEvtListeners.aEvts[iElId].length; iLstId++) { oEvtListeners.aEvts[iElId][iLstId].call(this, oEvent); } break; } } } Element.prototype.addEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) { if (oListeners.hasOwnProperty(sEventType)) { var oEvtListeners = oListeners[sEventType]; for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) { if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; } } if (nElIdx === -1) { oEvtListeners.aEls.push(this); oEvtListeners.aEvts.push([fListener]); this["on" + sEventType] = runListeners; } else { var aElListeners = oEvtListeners.aEvts[nElIdx]; if (this["on" + sEventType] !== runListeners) { aElListeners.splice(0); this["on" + sEventType] = runListeners; } for (var iLstId = 0; iLstId < aElListeners.length; iLstId++) { if (aElListeners[iLstId] === fListener) { return; } } aElListeners.push(fListener); } } else { oListeners[sEventType] = { aEls: [this], aEvts: [ [fListener] ] }; this["on" + sEventType] = runListeners; } }; Element.prototype.removeEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) { if (!oListeners.hasOwnProperty(sEventType)) { return; } var oEvtListeners = oListeners[sEventType]; for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) { if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; } } if (nElIdx === -1) { return; } for (var iLstId = 0, aElListeners = oEvtListeners.aEvts[nElIdx]; iLstId < aElListeners.length; iLstId++) { if (aElListeners[iLstId] === fListener) { aElListeners.splice(iLstId, 1); } } }; } 
  • I think all you need to change is to replace Element.prototype with CustomObject.prototype . And to support dispathEvent you must add a line of code CustomObject.prototype.dispatchEvent = runListener; . It might also be better to enclose this code in a closure function;

I have not tested this in my applications, but maybe this can help you.

UPDATE: The following link points to a code source that contains an XObject() class that supports events adding / removing events and sending events. Sample test included. All code is based on the answer above. http://jsfiddle.net/8jZrR/

+1
Jun 11 '12 at 11:33
source share

I improved my sample with code from fancy. I will still extract the event processing part into the "base class" ... maybe when there is still time =)

There is also a sample for using jQuery!

 <!doctype html> <html lang="en"> <head> <title>Custom Events Test</title> <meta charset="utf-8"> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> <script> /* jQuery var CustomObjectTextChangedEventName = 'textChanged'; var CustomObject = function () { var _this = this; var _text = ""; _this.ChangeText = function (newText) { _text = newText; fireTextChanged(); }; function fireTextChanged() { $(_this).trigger(CustomObjectTextChangedEventName, _text); } } var myCustomObject; $(document).ready(function () { myCustomObject = new CustomObject(); $(myCustomObject).bind(CustomObjectTextChangedEventName, handleTextChanged); }) function handleTextChanged(event, msg) { window.alert(msg); } function buttonClick() { var newText = document.getElementById('tbText').value; myCustomObject.ChangeText(newText); } */ var CustomObjectTextChangedEventName = 'textChanged'; var CustomObject = function (alias) { var _this = this; var _events = {}; var _text = ""; _this.Alias = alias; _this.OnTextChanged = document.createEvent("Event"); _this.OnTextChanged.initEvent(CustomObjectTextChangedEventName, true, false); _this.ChangeText = function (newText) { var args = new TextChangedEventArgs(); args.OldText = _text; args.NewText = newText; _text = newText; fireEvent(CustomObjectTextChangedEventName, args); }; _this.addEventListener = function (name, handler) { if (_events.hasOwnProperty(name)) _events[name].push(handler); else _events[name] = [handler]; }; _this.removeEventListener = function (name, handler) { /* This is a bit tricky, because how would you identify functions? This simple solution should work if you pass THE SAME handler. */ if (!_events.hasOwnProperty(name)) return; var index = _events[name].indexOf(handler); if (index != -1) _events[name].splice(index, 1); }; function fireEvent(name, args) { if (!_events.hasOwnProperty(name)) return; var evs = _events[name], l = evs.length; for (var i = 0; i < l; i++) { evs[i](_this, args); } } } var TextChangedEventArgs = function () { var _this = this; _this.OldText = null; _this.NewText = null; } var myCustomObject; var myCustomObject2; window.onload = function () { myCustomObject = new CustomObject("myCustomObject"); myCustomObject.addEventListener(CustomObjectTextChangedEventName, handleTextChanged); myCustomObject2 = new CustomObject("myCustomObject2"); myCustomObject2.addEventListener(CustomObjectTextChangedEventName, handleTextChanged); }; function handleTextChanged(sender, args) { window.alert('At ' + sender.Alias + ' from [' + args.OldText + '] to [' + args.NewText + ']'); } function buttonClick() { var newText = document.getElementById('tbText').value; myCustomObject.ChangeText(newText); } function buttonClick2() { var newText = document.getElementById('tbText2').value; myCustomObject2.ChangeText(newText); } </script> </head> <body> <input type="text" id="tbText" /> <input type="button" value="Change" onclick="buttonClick();" /> <input type="text" id="tbText2" /> <input type="button" value="Change" onclick="buttonClick2();" /> </body> 

+1
Jun 11 2018-12-12T00:
source share



All Articles