Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change implementation to be modular #2

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -10,7 +10,7 @@ the functionality that Node's event emitter has.)
This library has three goals: This library has three goals:


1. Make it easy and intuitive to listen for and initiate events on an object. 1. Make it easy and intuitive to listen for and initiate events on an object.
2. Be really small. Right now the minified version comes in at 407 bytes (247 2. Be really small. Right now the minified version comes in at 571 bytes (345
bytes gzipped). bytes gzipped).
3. Not pollute the global namespace or the objects it modifies with a bunch of 3. Not pollute the global namespace or the objects it modifies with a bunch of
crap. I define crap as anything that is not the API. crap. I define crap as anything that is not the API.
Expand Down
18 changes: 0 additions & 18 deletions index.js

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -7,7 +7,7 @@
, "email": "benjamin@benjaminthomas.org" , "email": "benjamin@benjaminthomas.org"
} }
, "keywords": ["events", "emitter", "trigger"] , "keywords": ["events", "emitter", "trigger"]
, "main": "./index.js" , "main": "./smokesignals.min.js"
, "repository": {"type": "git", "url": "git://github.com/bentomas/smokesignals.git"} , "repository": {"type": "git", "url": "git://github.com/bentomas/smokesignals.git"}
, "scripts": { "test": "node ./test.js" } , "scripts": { "test": "node ./test.js" }
} }
150 changes: 80 additions & 70 deletions smokesignals.js
@@ -1,82 +1,92 @@
// in a few cases we've chosen optimizing script length over efficiency of code. (function (name, global, definition) {
// I think that is the right choice for this library. If you're adding and if (typeof module !== 'undefined') {
// triggering A LOT of events, you might want to use a different library. module.exports = definition();
smokesignals = { } else if (typeof define !== 'undefined' && typeof define.amd === 'object') {
convert: function(obj, handlers) { define(definition);
// we store the list of handlers as a local variable inside the scope } else {
// so that we don't have to add random properties to the object we are global[name] = definition();
// converting. (prefixing variables in the object with an underscore or }
// two is an ugly solution) })('smokesignals', this, function () {
// we declare the variable in the function definition to use two less // in a few cases we've chosen optimizing script length over efficiency of code.
// characters (as opposed to using 'var '). I consider this an inelegant // I think that is the right choice for this library. If you're adding and
// solution since smokesignals.convert.length now returns 2 when it is // triggering A LOT of events, you might want to use a different library.
// really 1, but doing this doesn't otherwise change the functionallity of return {
// this module, so we'll go with it for now convert: function(obj, handlers) {
handlers = {}; // we store the list of handlers as a local variable inside the scope
// so that we don't have to add random properties to the object we are
// converting. (prefixing variables in the object with an underscore or
// two is an ugly solution)
// we declare the variable in the function definition to use two less
// characters (as opposed to using 'var '). I consider this an inelegant
// solution since smokesignals.convert.length now returns 2 when it is
// really 1, but doing this doesn't otherwise change the functionallity of
// this module, so we'll go with it for now
handlers = {};


// add a listener // add a listener
obj.on = function(eventName, handler) { obj.on = function(eventName, handler) {
// either use the existing array or create a new one for this event // either use the existing array or create a new one for this event
// this isn't the most efficient way to do this, but is the shorter // this isn't the most efficient way to do this, but is the shorter
// than other more efficient ways, so we'll go with it for now. // than other more efficient ways, so we'll go with it for now.
(handlers[eventName] = handlers[eventName] || []) (handlers[eventName] = handlers[eventName] || [])
// add the handler to the array // add the handler to the array
.push(handler); .push(handler);


return obj; return obj;
}

// add a listener that will only be called once
obj.once = function(eventName, handler) {
// create a wrapper listener, that will remove itself after it is called
function wrappedHandler() {
// remove ourself, and then call the real handler with the args
// passed to this wrapper
handler.apply(obj.off(eventName, wrappedHandler), arguments);
} }
// in order to allow that these wrapped handlers can be removed by
// removing the original function, we save a reference to the original
// function
wrappedHandler.h = handler;


// call the regular add listener function with our new wrapper // add a listener that will only be called once
return obj.on(eventName, wrappedHandler); obj.once = function(eventName, handler) {
} // create a wrapper listener, that will remove itself after it is called
function wrappedHandler() {
// remove ourself, and then call the real handler with the args
// passed to this wrapper
handler.apply(obj.off(eventName, wrappedHandler), arguments);
}
// in order to allow that these wrapped handlers can be removed by
// removing the original function, we save a reference to the original
// function
wrappedHandler.h = handler;


// remove a listener // call the regular add listener function with our new wrapper
obj.off = function(eventName, handler) { return obj.on(eventName, wrappedHandler);
// loop through all handlers for this eventName, assuming a handler
// was passed in, to see if the handler passed in was any of them so
// we can remove it
// it would be more efficient to stash the length and compare i
// to that, but that is longer so we'll go with this.
for (var list = handlers[eventName], i = 0; handler && list && list[i]; i++) {
// either this item is the handler passed in, or this item is a
// wrapper for the handler passed in. See the 'once' function
list[i] != handler && list[i].h != handler ||
// remove it!
list.splice(i--,1);
} }
// if i is 0 (i.e. falsy), then there are no items in the array for this
// event name (or the array doesn't exist) // remove a listener
if (!i) { obj.off = function(eventName, handler) {
// remove the array for this eventname (if it doesn't exist then // loop through all handlers for this eventName, assuming a handler
// this isn't really hurting anything) // was passed in, to see if the handler passed in was any of them so
delete handlers[eventName]; // we can remove it
// it would be more efficient to stash the length and compare i
// to that, but that is longer so we'll go with this.
for (var list = handlers[eventName], i = 0; handler && list && list[i]; i++) {
// either this item is the handler passed in, or this item is a
// wrapper for the handler passed in. See the 'once' function
list[i] != handler && list[i].h != handler ||
// remove it!
list.splice(i--,1);
}
// if i is 0 (i.e. falsy), then there are no items in the array for this
// event name (or the array doesn't exist)
if (!i) {
// remove the array for this eventname (if it doesn't exist then
// this isn't really hurting anything)
delete handlers[eventName];
}
return obj;
} }
return obj;
}


obj.emit = function(eventName) { obj.emit = function(eventName) {
// loop through all handlers for this event name and call them all // loop through all handlers for this event name and call them all
// it would be more efficient to stash the length and compare i // it would be more efficient to stash the length and compare i
// to that, but that is longer so we'll go with this. // to that, but that is longer so we'll go with this.
for(var list = handlers[eventName], i = 0; list && list[i];) { for(var list = handlers[eventName], i = 0; list && list[i];) {
list[i++].apply(obj, list.slice.call(arguments, 1)); list[i++].apply(obj, list.slice.call(arguments, 1));
}
return obj;
} }

return obj; return obj;
} }

return obj;
} }
} });
2 changes: 1 addition & 1 deletion smokesignals.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test.js
Expand Up @@ -6,7 +6,7 @@ console.log('test do not pollute node globals when requiring');
globalKeys.push(key); globalKeys.push(key);
} }


var smokesignals = require('./index'); var smokesignals = require('./');


for (var key in global) { for (var key in global) {
assert.ok(globalKeys.indexOf(key) > -1); assert.ok(globalKeys.indexOf(key) > -1);
Expand Down