Last active
December 17, 2015 14:19
-
-
Save sukima/5623141 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Damn Simple Event Dispatcher | |
// ============================ | |
// | |
// Used to extend your own objects to handle events outside of the global event | |
// model introduced in Titanium. This is a implementation copy of | |
// Titanium.Proxy. Because Titanium objects are not JavaScript objects it's | |
// functionality is recreated here for our own app use. | |
// | |
// Requires [undersore](http://underscorejs.org/). | |
// | |
// Usage / Examples | |
// ---------------- | |
// | |
// There are two ways to use this. Stand alone and inherited. | |
// | |
// Stand Alone Event Dispatching is not as useful in practise but can be used | |
// in fun ways: | |
// | |
// var e = new EventEmitter(); | |
// var callback = function(data) { console.log(data); }; | |
// e.addEventListener("custom_event", callback); | |
// e.fireEvent("custom_event", "custom_event_data"); | |
// e.removeEventListener("custom_event", callback); | |
// | |
// Inherited Pattern is more useful especially to make your own objects an | |
// event dispatcher: | |
// | |
// function MyObject() { | |
// EventEmitter.call(this); // Required | |
// this.data = "custom_event_data"; | |
// } | |
// MyObject.prototype = new EventEmitter(); // Required | |
// MyObject.prototype.fire = function() { | |
// this.fireEvent("custom_event", this.data); | |
// }; | |
// | |
// var myobj = new MyObject(); | |
// var callback = function(data) { console.log(data); }; | |
// myobj.addEventListener("custom_event", callback); | |
// myobj.fire(); | |
// myobj.removeEventListener("custom_event", callback); | |
// | |
(function(exports) { | |
exports.EventEmitter = (function() { | |
function EventEmitter() { | |
this.event_handlers = {}; | |
} | |
var fn = EventEmitter.prototype; | |
fn.addEventListener = function(name, func) { | |
this.event_handlers[name] = _.chain(this.event_handlers[name]) | |
.union(func).filter(_.isFunction).value(); | |
return this; | |
}; | |
fn.removeEventListener = function(name, func) { | |
if (!_.isEmpty(this.event_handlers[name])) { | |
this.event_handlers[name] = _.without(this.event_handlers[name], func); | |
} | |
return this; | |
}; | |
fn.fireEvent = function(name, data, context) { | |
if (context == null) { context = this; } | |
_.each(this.event_handlers[name], function(func) { func.call(context, data); }); | |
}; | |
return EventEmitter; | |
})(); | |
})(this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe "EventEmitter", -> | |
beforeEach -> | |
@callback = createSpy("event callback") | |
@eventEmitter = new EventEmitter(); | |
describe "#addEventListener", -> | |
it "should create an event when one does not exist", -> | |
@eventEmitter.addEventListener("test_event_not_exist_yet", @callback) | |
expect( @eventEmitter.event_handlers["test_event_not_exist_yet"] ).toBeDefined() | |
it "should handle array of functions", -> | |
expect( => @eventEmitter.addEventListener("test_event", [@callback]) ).not.toThrow() | |
it "should handle single functions", -> | |
expect( => @eventEmitter.addEventListener("test_event", @callback) ).not.toThrow() | |
it "should ignore non functions", -> | |
expect( => @eventEmitter.addEventListener("test_event", null) ).not.toThrow() | |
expect( => @eventEmitter.addEventListener("test_event", undefined) ).not.toThrow() | |
expect( => @eventEmitter.addEventListener("test_event", 1) ).not.toThrow() | |
expect( => @eventEmitter.addEventListener("test_event", "x") ).not.toThrow() | |
expect( @eventEmitter.event_handlers["test_event"].length ).toBe 0 | |
it "should be chainable", -> | |
expect( @eventEmitter.addEventListener() ).toEqual @eventEmitter | |
describe "#removeEventListener", -> | |
it "should remove registered events", -> | |
@eventEmitter.addEventListener("test_event", @callback) | |
@eventEmitter.removeEventListener("test_event", @callback) | |
expect( @eventEmitter.event_handlers["test_event"].length ).toBe 0 | |
it "should ignore unknown events", -> | |
expect( => @eventEmitter.removeEventListener("test_event_not_exist_yet", @callback) ) | |
.not.toThrow() | |
it "should ignore non functions", -> | |
@eventEmitter.addEventListener("test_event", @callback) | |
expect( => @eventEmitter.removeEventListener("test_event", 1234) ) | |
.not.toThrow() | |
it "should be chainable", -> | |
expect( @eventEmitter.removeEventListener() ).toEqual @eventEmitter | |
describe "#fireEvent", -> | |
it "should call callback functions", -> | |
@eventEmitter.addEventListener("test_event", @callback) | |
@eventEmitter.fireEvent("test_event", 1) | |
expect( @callback ).toHaveBeenCalledWith(1) | |
it "should be chainable", -> | |
expect( @eventEmitter.fireEvent() ).toEqual @eventEmitter | |
describe "Inheritance Pattern", -> | |
beforeEach -> | |
# Use clasical javascript inheritance. Not coffeescript's. | |
`this.TestEmitter = function() { EventEmitter.call(this); }` | |
`this.TestEmitter.prototype = new EventEmitter()` | |
@instance = new @TestEmitter() | |
it "should add methods to original object", -> | |
expect( @instance.addEventListener ).toBeDefined() | |
expect( @instance.removeEventListener).toBeDefined() | |
expect( @instance.fireEvent ).toBeDefined() | |
it "should be an instance of EventEmitter", -> | |
expect( @instance instanceof EventEmitter ).toBeTruthy() | |
it "should be an instance of the original object", -> | |
expect( @instance instanceof @TestEmitter ).toBeTruthy() | |
it "should isolate instances", -> | |
other = new @TestEmitter() | |
expect( @instance.event_handlers ).not.toBe other.event_handlers |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment