Languages
[Edit]
EN

JavaScript - how to write own / custom event listener collection class

2 points
Created by:
JustMike
26150

In this article, we're going to have a look at how to write own event listener class. Presented solutions are splitted into two separated examples:

  • simple event lsitener - this collection allows to keep many callback functions togather and call them togather,
  • complex event listener -¬†this collection is similar to first one with major difference, the collection groups callback¬†functions into separated events by given¬†event name.

1. Simple event listener class example

Presented collection in this section allows to add, remove, fire and clean events. add method returns function reference that allows to remove added event (just by calling it without any arguments).

// ONLINE-RUNNER:browser;

function SimpleListener() {
	var self = this;
	var listeners = [ ];

	self.getSize = function() {
		return listeners.length;
	};
	self.add = function(action) {
		if (action instanceof Function) {
			listeners.push(action);
            var removed = true;
			var remove = function() {
				if (removed) {
                  	return false;
                }
                removed = true;
                return self.remove(action);
			};
			return remove;
		}
		throw new Error( 'Indicated listener action is not function type.' );
	};
	self.remove = function(action) {
		var index = listeners.indexOf(action);
		if (index == -1) {
			return false;
        }
		listeners.splice(index, 1);
		return true;
	};
	self.fire = function(parameters) {
		for (var i = 0; i < listeners.length; ++i) {
			var listener = listeners[i];
			listener.apply(listener, parameters);
		}
	};
  	self.clean = function() {
    	listener = [ ];
    };
}

// Usage example:

var myEventListener = new SimpleListener();

myEventListener.add(function(name, age, city) {
	console.log('Function 1: ' + name + ' ' + age + ' ' + city);
});
myEventListener.add(function(name, age, city) {
	console.log('Function 2: ' + name + ' ' + age + ' ' + city);
});
myEventListener.add(function(name, age, city) {
	console.log('Function 3: ' + name + ' ' + age + ' ' + city);
});

myEventListener.fire(['John', 25, 'London']);

2. Complex event listener class example

Presented collection in this section provides same operations like in first example: add, remove, fire and clean. Main difference is events grouping - the methods takes as first argument name of event. Check below example to know how it works:

// ONLINE-RUNNER:browser;

// this class is coppied from first example
function SimpleListener() {
	var self = this;
	var listeners = [ ];

	self.getSize = function() {
		return listeners.length;
	};
	self.add = function(action) {
		if (action instanceof Function) {
			listeners.push(action);
            var removed = true;
			var remove = function() {
				if (removed) {
                  	return false;
                }
                removed = true;
                return self.remove(action);
			};
			return remove;
		}
		throw new Error( 'Indicated listener action is not function type.' );
	};
	self.remove = function(action) {
		var index = listeners.indexOf(action);
		if (index == -1) {
			return false;
        }
		listeners.splice(index, 1);
		return true;
	};
	self.fire = function(parameters) {
		for (var i = 0; i < listeners.length; ++i) {
			var listener = listeners[i];
			listener.apply(listener, parameters);
		}
	};
  	self.clean = function() {
    	listener = [ ];
    };
}

function ComposedListener() {
	var self = this;
	var count = 0;
	var listeners = { };

	self.getSize = function(event) {
		if (event) {
			var entity = listeners[event];
			if (entity) {
				return entity.getSize();
            }
			return 0;
		}
		return count;
	};
	self.add = function(event, action) {
        var entity = listeners[event];
        if (entity == null) {
            var entity = new SimpleListener();
            var remove = entity.add(action); // add method throws exception breaking logic
            listeners[event] = entity
        } else {
          	var remove = entity.add(action)
        }
        count += 1;
      	var proxy = function() {
            if (remove()) {
                count -= 1;
                if (!entity.getSize()) {
                  	delete listeners[event];
                }
                return true;
            }
          	return false;
        };
        return proxy;
	};
	self.remove = function(event, action) {
      	var entity = listeners[event];
        if (entity == null) {
          	return false;
        }
      	if (action) {
            if (entity.remove(action)) {
                count -= 1;
                if (!entity.getSize()) {
                    delete listeners[event];
                }
              	return true;
            }
          	return false;
        } else {
        	count -= entity.getSize();
          	delete listeners[event];
          	entity.clean(); // cleaning because of add method result
          	return true;
        }
	};
	self.fire = function(event, parameters) {
		var entity = listeners[event];
		if (entity) {
			entity.fire(parameters);
        }
	};
  	self.clean = function() {
      	if (count > 0) {
            for (var key in listeners) {
                if (listeners.hasOwnProperty(key)) {
                    var listener = listeners[key];
                    listener.clean(); // cleaning because of add method result
                }
            }
            count = 0;
            listeners = { };
        }
    };
}

// Usage example:

var myEventListener = new ComposedListener();

myEventListener.add('eventname1', function(name, age, city) {
	console.log('eventname1 -> Function 1: ' 
        + name + ' ' + age + ' ' + city);
});
myEventListener.add('eventname1', function(name, age, city) {
	console.log('eventname1 -> Function 2: ' 
        + name + ' ' + age + ' ' + city);
});
myEventListener.add('eventname2', function(name, age, city) {
	console.log('eventname2 -> Function 3: ' 
        + name + ' ' + age + ' ' + city);
});

myEventListener.fire('eventname1', ['John', 25, 'London']);
myEventListener.fire('eventname2', ['Kate', 21, 'Massachusetts']);

 

Native Advertising
50 000 ad impressions - 449$
ūüöÄ
Get your tech brand or product in front of software developers.
For more information contact us:
Red dot
Dirask - friendly IT community for everyone.

‚̧ԳŹūüíĽ ūüôā

Join