Comparing version 0.3.8 to 1.0.0
@@ -1,7 +0,1 @@ | ||
// eventify - v0.3.6 (2013-04-28) | ||
// ----------------- | ||
// Copyright(c) 2010-2012 Jeremy Ashkenas, DocumentCloud | ||
// Copyright(c) 2012 Bermi Ferrer <bermi@bermilabs.com> | ||
// MIT Licensed | ||
(function(a){"use strict";var b,c=a.Eventify,d=/\s+/,e=a.localEventifyLibraryName||"Eventify",f=Object.keys||function(a){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("keys() called on a non-object");var b,c=[];for(b in a)a.hasOwnProperty(b)&&(c[c.length]=b);return c},g=function(a){return this};g.prototype={version:"0.3.3",on:function(a,b,c){var e,f,g;if(!b)return this;a=a.split(d),e=this._callbacks||(this._callbacks={}),f=a.shift();while(f)g=e[f]||(e[f]=[]),g.push(b,c),f=a.shift();return this},off:function(a,b,c){var e,g,h,i;if(!(g=this._callbacks))return this;if(!(a||b||c))return delete this._callbacks,this;a?a=a.split(d):a=f(g),e=a.shift();while(e){if(!(h=g[e])||!b&&!c){delete g[e],e=a.shift();continue}for(i=h.length-2;i>=0;i-=2)b&&h[i]!==b||c&&h[i+1]!==c||h.splice(i,2);e=a.shift()}return this},trigger:function(a){var b,c,e,f,g,h,i,j;if(!(c=this._callbacks))return this;j=[],a=a.split(d);for(f=1,g=arguments.length;f<g;f=f+1)j[f-1]=arguments[f];b=a.shift();while(b){i=c.all,i&&(i=i.slice()),e=c[b],e&&(e=e.slice());if(e)for(f=0,g=e.length;f<g;f+=2)e[f].apply(e[f+1]||this,j);if(i){h=[b].concat(j);for(f=0,g=i.length;f<g;f+=2)i[f].apply(i[f+1]||this,h)}b=a.shift()}return this},noConflict:function(){return a.Eventify=c,this},enable:function(a){var b,c,d=["on","off","trigger"];a=a||{};for(b=0,c=d.length;b<c;b=b+1)a[d[b]]=this[d[b]];return a}},b=new g,(typeof exports!="undefined"?exports:a)[e]=b,typeof exports!="undefined"&&typeof module!="undefined"&&module.exports&&(module.exports=b)})(this); | ||
!function(a,b,c){"undefined"!=typeof module?module.exports=c(a,b):"function"==typeof define&&"object"==typeof define.amd?define(c):b[a]=c(a,b)}(this.localEventifyLibraryName||"Eventify",this,function(a,b){"use strict";function c(){return{keys:Object.keys,uniqueId:function(a){k+=1;var b=k+"";return a?a+b:b},has:function(a,b){return hasOwnProperty.call(a,b)},each:function(a,b,c){var d,e,f;if(null!=a)if(i&&a.forEach===i)a.forEach(b,c);else if(a.length===+a.length){for(e=0,f=a.length;f>e;e+=1)if(b.call(c,a[e],e,a)===h)return}else for(d in a)if(this.has(a,d)&&b.call(c,a[d],d,a)===h)return},once:function(a){var b,c=!1;return function(){return c?b:(c=!0,b=a.apply(this,arguments),a=null,b)}}}}var d,e,f,g={listenTo:"on",listenToOnce:"once"},h={},i=Array.prototype.forEach,j=Array.prototype.slice,k=0,l=b.Eventify,m=c(),n=/\s+/,o=function(){return this};return o.prototype={version:"1.0.0",on:function(a,b,c){if(!f(this,"on",a,[b,c])||!b)return this;this._events=this._events||{};var d=this._events[a]||(this._events[a]=[]);return d.push({callback:b,context:c,ctx:c||this}),this},once:function(a,b,c){var d,e=this;return f(this,"once",a,[b,c])&&b?(d=m.once(function(){e.off(a,d),b.apply(this,arguments)}),d._callback=b,this.on(a,d,c)):this},off:function(a,b,c){var d,e,g,h,i,j,k,l;if(!this._events||!f(this,"off",a,[b,c]))return this;if(!a&&!b&&!c)return this._events={},this;for(h=a?[a]:m.keys(this._events),i=0,j=h.length;j>i;i+=1)if(a=h[i],g=this._events[a]){if(this._events[a]=d=[],b||c)for(k=0,l=g.length;l>k;k+=1)e=g[k],(b&&b!==e.callback&&b!==e.callback._callback||c&&c!==e.context)&&d.push(e);d.length||delete this._events[a]}return this},trigger:function(a){if(!this._events)return this;var b,c,d=j.call(arguments,1);return f(this,"trigger",a,d)?(b=this._events[a],c=this._events.all,b&&e(b,d),c&&e(c,arguments),this):this},stopListening:function(a,b,c){var d,e,f=this._listeners;if(!f)return this;d=!b&&!c,"object"==typeof b&&(c=this),f={},a&&(f[a._listenerId]=a);for(e in f)f.hasOwnProperty(e)&&(f[e].off(b,c,this),d&&delete this._listeners[e]);return this},noConflict:function(){return b.Eventify=l,this},enable:function(a){var b,c,d=["on","once","off","trigger","stopListening","listenTo","listenToOnce","bind","unbind"];for(a=a||{},b=0,c=d.length;c>b;b+=1)a[d[b]]=this[d[b]];return a}},f=function(a,b,c,d){var e,f,g,h;if(!c)return!0;if("object"==typeof c){for(e in c)c.hasOwnProperty(e)&&a[b].apply(a,[e,c[e]].concat(d));return!1}if(n.test(c)){for(h=c.split(n),f=0,g=h.length;g>f;f+=1)a[b].apply(a,[h[f]].concat(d));return!1}return!0},e=function(a,b){var c,d=0,e=a.length,f=b[0],g=b[1],h=b[2];switch(b.length){case 0:for(;e>d;)c=a[d],c.callback.call(c.ctx),d+=1;return;case 1:for(;e>d;)c=a[d],c.callback.call(c.ctx,f),d+=1;return;case 2:for(;e>d;)c=a[d],c.callback.call(c.ctx,f,g),d+=1;return;case 3:for(;e>d;)c=a[d],c.callback.call(c.ctx,f,g,h),d+=1;return;default:for(;e>d;)c=a[d],c.callback.apply(c.ctx,b),d+=1}},m.each(g,function(a,b){o.prototype[b]=function(b,c,d){var e,f=this._listeners||(this._listeners={});return b._listenerId=b._listenerId||m.uniqueId("l"),e=b._listenerId,f[e]=b,"object"==typeof c&&(d=this),b[a](c,d,this),this}}),d=new o,d.mixin=d.enable,d}); |
// Eventify | ||
// ----------------- | ||
// Copyright(c) 2010-2012 Jeremy Ashkenas, DocumentCloud | ||
// Copyright(c) 2012 Bermi Ferrer <bermi@bermilabs.com> | ||
// Copyright(c) 2014 Bermi Ferrer <bermi@bermilabs.com> | ||
// Copyright(c) 2013 Nicolas Perriault | ||
// MIT Licensed | ||
@@ -19,3 +21,3 @@ | ||
module.exports = definition(name, global); | ||
} else if (typeof define === 'function' && typeof define.amd === 'object') { | ||
} else if (typeof define === 'function' && typeof define.amd === 'object') { | ||
define(definition); | ||
@@ -31,5 +33,73 @@ } else { | ||
// Returns a partial implementation matching the minimal API subset required | ||
// by Backbone.Events | ||
function miniscore() { | ||
return { | ||
keys: Object.keys, | ||
uniqueId: function (prefix) { | ||
idCounter = idCounter + 1; | ||
var id = idCounter + ''; | ||
return prefix ? prefix + id : id; | ||
}, | ||
has: function (obj, key) { | ||
return hasOwnProperty.call(obj, key); | ||
}, | ||
each: function (obj, iterator, context) { | ||
var key, i, l; | ||
if (obj == null) { | ||
return; | ||
} | ||
if (nativeForEach && obj.forEach === nativeForEach) { | ||
obj.forEach(iterator, context); | ||
} else if (obj.length === +obj.length) { | ||
for (i = 0, l = obj.length; i < l; i += 1) { | ||
if (iterator.call(context, obj[i], i, obj) === breaker) { | ||
return; | ||
} | ||
} | ||
} else { | ||
for (key in obj) { | ||
if (this.has(obj, key)) { | ||
if (iterator.call(context, obj[key], key, obj) === breaker) { | ||
return; | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
once: function (func) { | ||
var ran = false, | ||
memo; | ||
return function () { | ||
if (ran) { | ||
return memo; | ||
} | ||
ran = true; | ||
memo = func.apply(this, arguments); | ||
func = null; | ||
return memo; | ||
}; | ||
} | ||
}; | ||
} | ||
var EventifyInstance, | ||
triggerEvents, | ||
listenMethods = { | ||
listenTo: 'on', | ||
listenToOnce: 'once' | ||
}, | ||
breaker = {}, | ||
nativeForEach = Array.prototype.forEach, | ||
slice = Array.prototype.slice, | ||
idCounter = 0, | ||
eventsApi, | ||
// Save the previous value of the `Eventify` variable. | ||
previousEventify = root.Eventify, | ||
_ = miniscore(), | ||
@@ -45,19 +115,4 @@ // Regular expression used to split event strings | ||
// Retrieve the names of an object's properties. | ||
// Delegates to **ECMAScript 5**'s native `Object.keys` | ||
keys = Object.keys || function (obj) { | ||
if (typeof obj !== "object" && typeof obj !== "function" || obj === null) { | ||
throw new TypeError("keys() called on a non-object"); | ||
} | ||
var key, keys = []; | ||
for (key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
keys[keys.length] = key; | ||
} | ||
} | ||
return keys; | ||
}, | ||
// Create a safe reference to the Eventify object for use below. | ||
Eventify = function (options) { | ||
Eventify = function () { | ||
return this; | ||
@@ -68,3 +123,3 @@ }; | ||
version: "0.3.3", | ||
version: "1.0.0", | ||
@@ -74,59 +129,71 @@ // Event Functions | ||
// Bind one or more space separated events, `events`, to a `callback` | ||
// function. Passing `"all"` will bind the callback to all events fired. | ||
on: function (events, callback, context) { | ||
var calls, event, list; | ||
if (!callback) { | ||
// Bind an event to a `callback` function. Passing `"all"` will bind | ||
// the callback to all events fired. | ||
on: function (name, callback, context) { | ||
if (!eventsApi(this, 'on', name, [callback, context]) || !callback) { | ||
return this; | ||
} | ||
this._events = this._events || {}; | ||
var events = this._events[name] || (this._events[name] = []); | ||
events.push({ | ||
callback: callback, | ||
context: context, | ||
ctx: context || this | ||
}); | ||
return this; | ||
}, | ||
events = events.split(eventSplitter); | ||
calls = this._callbacks || (this._callbacks = {}); | ||
event = events.shift(); | ||
while (event) { | ||
list = calls[event] || (calls[event] = []); | ||
list.push(callback, context); | ||
event = events.shift(); | ||
// Bind an event to only be triggered a single time. After the first time | ||
// the callback is invoked, it will be removed. | ||
once: function (name, callback, context) { | ||
var self = this, | ||
once; | ||
if (!eventsApi(this, 'once', name, [callback, context]) || !callback) { | ||
return this; | ||
} | ||
return this; | ||
once = _.once(function () { | ||
self.off(name, once); | ||
callback.apply(this, arguments); | ||
}); | ||
once._callback = callback; | ||
return this.on(name, once, context); | ||
}, | ||
// Remove one or many callbacks. If `context` is null, removes all callbacks | ||
// with that function. If `callback` is null, removes all callbacks for the | ||
// event. If `events` is null, removes all bound callbacks for all events. | ||
off: function (events, callback, context) { | ||
var event, calls, list, i; | ||
// No events, or removing *all* events. | ||
if (!(calls = this._callbacks)) { | ||
// Remove one or many callbacks. If `context` is null, removes all | ||
// callbacks with that function. If `callback` is null, removes all | ||
// callbacks for the event. If `name` is null, removes all bound | ||
// callbacks for all events. | ||
off: function (name, callback, context) { | ||
var retain, ev, events, names, i, l, j, k; | ||
if (!this._events || !eventsApi(this, 'off', name, [callback, context])) { | ||
return this; | ||
} | ||
if (!(events || callback || context)) { | ||
delete this._callbacks; | ||
if (!name && !callback && !context) { | ||
this._events = {}; | ||
return this; | ||
} | ||
if (events) { | ||
events = events.split(eventSplitter); | ||
} else { | ||
events = keys(calls); | ||
} | ||
// Loop through the callback list, splicing where appropriate. | ||
event = events.shift(); | ||
while (event) { | ||
if (!(list = calls[event]) || !(callback || context)) { | ||
delete calls[event]; | ||
event = events.shift(); | ||
continue; | ||
} | ||
for (i = list.length - 2; i >= 0; i -= 2) { | ||
if (!(callback && list[i] !== callback || context && list[i + 1] !== context)) { | ||
list.splice(i, 2); | ||
names = name ? [name] : _.keys(this._events); | ||
for (i = 0, l = names.length; i < l; i += 1) { | ||
name = names[i]; | ||
events = this._events[name]; | ||
if (events) { | ||
this._events[name] = retain = []; | ||
if (callback || context) { | ||
for (j = 0, k = events.length; j < k; j += 1) { | ||
ev = events[j]; | ||
if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || | ||
(context && context !== ev.context)) { | ||
retain.push(ev); | ||
} | ||
} | ||
} | ||
if (!retain.length) { | ||
delete this._events[name]; | ||
} | ||
} | ||
event = events.shift(); | ||
} | ||
@@ -141,43 +208,45 @@ | ||
// receive the true name of the event as the first argument). | ||
trigger: function (events) { | ||
var event, calls, list, i, length, args, all, rest; | ||
if (!(calls = this._callbacks)) { | ||
trigger: function (name) { | ||
if (!this._events) { | ||
return this; | ||
} | ||
var events, allEvents, | ||
args = slice.call(arguments, 1); | ||
if (!eventsApi(this, 'trigger', name, args)) { | ||
return this; | ||
} | ||
events = this._events[name]; | ||
allEvents = this._events.all; | ||
if (events) { | ||
triggerEvents(events, args); | ||
} | ||
if (allEvents) { | ||
triggerEvents(allEvents, arguments); | ||
} | ||
return this; | ||
}, | ||
rest = []; | ||
events = events.split(eventSplitter); | ||
for (i = 1, length = arguments.length; i < length; i = i + 1) { | ||
rest[i - 1] = arguments[i]; | ||
// Tell this object to stop listening to either specific events ... or | ||
// to every object it's currently listening to. | ||
stopListening: function (obj, name, callback) { | ||
var deleteListener, id, | ||
listeners = this._listeners; | ||
if (!listeners) { | ||
return this; | ||
} | ||
// For each event, walk through the list of callbacks twice, first to | ||
// trigger the event, then to trigger any `"all"` callbacks. | ||
event = events.shift(); | ||
while (event) { | ||
// Copy callback lists to prevent modification. | ||
all = calls.all; | ||
if (all) { | ||
all = all.slice(); | ||
} | ||
list = calls[event]; | ||
if (list) { | ||
list = list.slice(); | ||
} | ||
// Execute event callbacks. | ||
if (list) { | ||
for (i = 0, length = list.length; i < length; i += 2) { | ||
list[i].apply(list[i + 1] || this, rest); | ||
deleteListener = !name && !callback; | ||
if (typeof name === 'object') { | ||
callback = this; | ||
} | ||
listeners = {}; | ||
if (obj) { | ||
listeners[obj._listenerId] = obj; | ||
} | ||
for (id in listeners) { | ||
if (listeners.hasOwnProperty(id)) { | ||
listeners[id].off(name, callback, this); | ||
if (deleteListener) { | ||
delete this._listeners[id]; | ||
} | ||
} | ||
// Execute "all" callbacks. | ||
if (all) { | ||
args = [event].concat(rest); | ||
for (i = 0, length = all.length; i < length; i += 2) { | ||
all[i].apply(all[i + 1] || this, args); | ||
} | ||
} | ||
event = events.shift(); | ||
} | ||
@@ -187,2 +256,4 @@ return this; | ||
// Utility Functions | ||
@@ -202,3 +273,4 @@ // ----------------- | ||
var i, len, | ||
methods = ['on', 'off', 'trigger']; | ||
methods = ['on', 'once', 'off', 'trigger', 'stopListening', 'listenTo', | ||
'listenToOnce', 'bind', 'unbind']; | ||
target = target || {}; | ||
@@ -214,2 +286,104 @@ for (i = 0, len = methods.length; i < len; i = i + 1) { | ||
// Implement fancy features of the Events API such as multiple event | ||
// names `"change blur"` and jQuery-style event maps `{change: action}` | ||
// in terms of the existing API. | ||
eventsApi = function (obj, action, name, rest) { | ||
var key, i, l, names; | ||
if (!name) { | ||
return true; | ||
} | ||
// Handle event maps. | ||
if (typeof name === 'object') { | ||
for (key in name) { | ||
if (name.hasOwnProperty(key)) { | ||
obj[action].apply(obj, [key, name[key]].concat(rest)); | ||
} | ||
} | ||
return false; | ||
} | ||
// Handle space separated event names. | ||
if (eventSplitter.test(name)) { | ||
names = name.split(eventSplitter); | ||
for (i = 0, l = names.length; i < l; i += 1) { | ||
obj[action].apply(obj, [names[i]].concat(rest)); | ||
} | ||
return false; | ||
} | ||
return true; | ||
}; | ||
// A difficult-to-believe, but optimized internal dispatch function for | ||
// triggering events. Tries to keep the usual cases speedy (most internal | ||
// Backbone events have 3 arguments). | ||
triggerEvents = function (events, args) { | ||
var ev, | ||
i = 0, | ||
l = events.length, | ||
a1 = args[0], | ||
a2 = args[1], | ||
a3 = args[2]; | ||
switch (args.length) { | ||
case 0: | ||
while (i < l) { | ||
ev = events[i]; | ||
ev.callback.call(ev.ctx); | ||
i += 1; | ||
} | ||
return; | ||
case 1: | ||
while (i < l) { | ||
ev = events[i]; | ||
ev.callback.call(ev.ctx, a1); | ||
i += 1; | ||
} | ||
return; | ||
case 2: | ||
while (i < l) { | ||
ev = events[i]; | ||
ev.callback.call(ev.ctx, a1, a2); | ||
i += 1; | ||
} | ||
return; | ||
case 3: | ||
while (i < l) { | ||
ev = events[i]; | ||
ev.callback.call(ev.ctx, a1, a2, a3); | ||
i += 1; | ||
} | ||
return; | ||
default: | ||
while (i < l) { | ||
ev = events[i]; | ||
ev.callback.apply(ev.ctx, args); | ||
i += 1; | ||
} | ||
} | ||
}; | ||
// Inversion-of-control versions of `on` and `once`. Tell *this* object to | ||
// listen to an event in another object ... keeping track of what it's | ||
// listening to. | ||
_.each(listenMethods, function (implementation, method) { | ||
Eventify.prototype[method] = function (obj, name, callback) { | ||
var id, | ||
listeners = this._listeners || (this._listeners = {}); | ||
obj._listenerId = obj._listenerId || _.uniqueId('l'); | ||
id = obj._listenerId; | ||
listeners[id] = obj; | ||
if (typeof name === 'object') { | ||
callback = this; | ||
} | ||
obj[implementation](name, callback, this); | ||
return this; | ||
}; | ||
}); | ||
// Export an Eventify instance for **Node.js**, with | ||
@@ -220,6 +394,10 @@ // backwards-compatibility for the old `require()` API. If we're in | ||
EventifyInstance = new Eventify(); | ||
// Backbone.Events drop in replacement compatibility | ||
EventifyInstance.mixin = EventifyInstance.enable; | ||
// Sets Eventify on the browser window or on the process | ||
return EventifyInstance; | ||
// Establish the root object, `window` in the browser, or `global` on the server. | ||
// Establish the root object, `window` in the browser, or `global` on the server. | ||
})); |
{ | ||
"name": "eventify", | ||
"version": "0.3.8", | ||
"version": "1.0.0", | ||
"description": "Lightweight module that can be mixed in to any object in order to provide it with custom events. For node.js and the browser. Based on Backbone.Events", | ||
@@ -8,14 +8,17 @@ "author": "Bermi Ferrer <bermi@bermilabs.com>", | ||
"keywords": [ | ||
"event", | ||
"eventify", | ||
"events", | ||
"browser", | ||
"trigger", | ||
"observer", | ||
"bind", | ||
"backbone", | ||
"ender" | ||
"event", | ||
"eventify", | ||
"events", | ||
"browser", | ||
"trigger", | ||
"observer", | ||
"bind", | ||
"backbone", | ||
"standalone", | ||
"backbone-events", | ||
"EventEmitter", | ||
"ender" | ||
], | ||
"bugs": { | ||
"url": "https://github.com/bermi/eventify/issues" | ||
"url": "https://github.com/bermi/eventify/issues" | ||
}, | ||
@@ -28,6 +31,5 @@ "licenses": [ | ||
], | ||
"repository": | ||
{ | ||
"type": "git", | ||
"url": "git://github.com/bermi/eventify.git" | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/bermi/eventify.git" | ||
}, | ||
@@ -37,8 +39,12 @@ "engines": { | ||
}, | ||
"dependencies": { | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"mocha": "~1.9.0", | ||
"expect.js": "~0.2.0", | ||
"grunt": "~0.3.x" | ||
"expect.js": "~0.3.1", | ||
"grunt": "~0.4.x", | ||
"grunt-cli": "^0.1.13", | ||
"grunt-contrib-concat": "^0.4.0", | ||
"grunt-contrib-jshint": "^0.10.0", | ||
"grunt-contrib-uglify": "^0.5.0", | ||
"grunt-contrib-watch": "^0.6.1", | ||
"mocha": "~1.20.1" | ||
}, | ||
@@ -67,2 +73,2 @@ "scripts": { | ||
} | ||
} | ||
} |
@@ -13,3 +13,3 @@ # Eventify | ||
A 1.7k (867 bytes gzipped) browser ready version is available on the dist/ folder. | ||
A 3.19 kB (1.4K gzipped) browser ready version is available on the dist/ folder. | ||
@@ -70,2 +70,11 @@ <script src="dist/eventify.min.js" type="text/javascript"></script> | ||
All event methods also support an event map syntax, as an alternative to positional arguments: | ||
book.on({ | ||
"change:title": titleView.update, | ||
"change:author": authorPane.update, | ||
"destroy": bookView.remove | ||
}); | ||
### *off* object.off([event], [callback], [context]) | ||
@@ -90,2 +99,3 @@ | ||
### *trigger* object.trigger(event, [*args]) | ||
@@ -95,3 +105,26 @@ | ||
### *once** object.once(event, callback, [context]) | ||
Just like on, but causes the bound callback to only fire once before being removed. Handy for saying "the next time that X happens, do this". | ||
### **listenTo** object.listenTo(other, event, callback) | ||
Tell an object to listen to a particular event on an other object. The advantage of using this form, instead of other.on(event, callback, object), is that listenTo allows the object to keep track of the events, and they can be removed all at once later on. The callback will always be called with object as context. | ||
view.listenTo(model, 'change', view.render); | ||
### **stopListening** object.stopListening([other], [event], [callback]) | ||
Tell an object to stop listening to events. Either call stopListening with no arguments to have the object remove all of its registered callbacks ... or be more precise by telling it to remove just the events it's listening to on a specific object, or a specific event, or just a specific callback. | ||
view.stopListening(); | ||
view.stopListening(model); | ||
### **listenToOnce** object.listenToOnce(other, event, callback) | ||
Just like listenTo, but causes the bound callback to only fire once before being removed. | ||
### *noClonflict* var LocalEventify = Eventify.noConflict(); | ||
@@ -98,0 +131,0 @@ |
@@ -26,7 +26,45 @@ (function (root) { | ||
describe("when enabling events using Eventify.enable, it:", function () { | ||
it("should add the Events mixin to passed prototype", function () { | ||
var target = {}; | ||
Eventify.enable(target); | ||
expect(target).to.include.keys("on,once,off,trigger,stopListening".split(",")); | ||
}); | ||
it("should return augmented object", function (done) { | ||
Eventify.enable({}).on("foo", function (message) { | ||
expect(message).eql("hello emitter"); | ||
done(); | ||
}).trigger("foo", "hello emitter"); | ||
}); | ||
it("should augment an existing prototype", function (done) { | ||
function Plop() {} | ||
Eventify.enable(Plop.prototype); | ||
(new Plop()).on("foo", function (message) { | ||
expect(message).eql("hello emitter"); | ||
done(); | ||
}).trigger("foo", "hello emitter"); | ||
}); | ||
it("should only augment prototype with expected methods", function () { | ||
function Plop() {} | ||
Plop.prototype.foo = function () {}; | ||
Eventify.enable(Plop.prototype); | ||
expect(Plop.prototype).to.have.keys(['foo', 'on', 'once', 'off', 'trigger', | ||
'stopListening', 'listenTo', 'listenToOnce', 'bind', 'unbind']); | ||
}); | ||
}); | ||
describe("On and trigger", function () { | ||
var obj = { counter: 0 }; | ||
var obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
it('should increment counter', function () { | ||
obj.on('event', function () { obj.counter += 1; }); | ||
obj.on('event', function () { | ||
obj.counter += 1; | ||
}); | ||
obj.trigger('event'); | ||
@@ -45,6 +83,10 @@ expect(obj.counter).to.be(1); | ||
describe("Binding and triggering multiple events", function () { | ||
var obj = { counter: 0 }; | ||
var obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
obj.on('a b c', function () { obj.counter += 1; }); | ||
obj.on('a b c', function () { | ||
obj.counter += 1; | ||
}); | ||
@@ -67,3 +109,5 @@ it('should only affect active counters', function () { | ||
it('should trigger all for each event', function () { | ||
var a, b, obj = { counter: 0 }; | ||
var a, b, obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
@@ -79,3 +123,3 @@ obj.on('all', function (event) { | ||
}) | ||
.trigger('a b'); | ||
.trigger('a b'); | ||
expect(a).to.be(true); | ||
@@ -86,2 +130,169 @@ expect(b).to.be(true); | ||
it("binding and triggering with event maps", function () { | ||
var increment, | ||
obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
increment = function () { | ||
this.counter += 1; | ||
}; | ||
obj.on({ | ||
a: increment, | ||
b: increment, | ||
c: increment | ||
}, obj); | ||
obj.trigger('a'); | ||
expect(obj.counter).eql(1); | ||
obj.trigger('a b'); | ||
expect(obj.counter).eql(3); | ||
obj.trigger('c'); | ||
expect(obj.counter).eql(4); | ||
obj.off({ | ||
a: increment, | ||
c: increment | ||
}, obj); | ||
obj.trigger('a b c'); | ||
expect(obj.counter).eql(5); | ||
}); | ||
it("listenTo and stopListening", function () { | ||
var a = Eventify.enable({}), | ||
b = Eventify.enable({}); | ||
a.listenTo(b, 'all', function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
b.trigger('anything'); | ||
a.listenTo(b, 'all', function () { | ||
expect(false).not.to.be.ok(); | ||
}); | ||
a.stopListening(); | ||
b.trigger('anything'); | ||
}); | ||
it("listenTo and stopListening with event maps", function () { | ||
var a = Eventify.enable({}), | ||
b = Eventify.enable({}), | ||
cb = function () { | ||
expect(true).to.be.ok(); | ||
}; | ||
a.listenTo(b, { | ||
event: cb | ||
}); | ||
b.trigger('event'); | ||
a.listenTo(b, { | ||
event2: cb | ||
}); | ||
b.on('event2', cb); | ||
a.stopListening(b, { | ||
event2: cb | ||
}); | ||
b.trigger('event event2'); | ||
a.stopListening(); | ||
b.trigger('event event2'); | ||
}); | ||
it("stopListening with omitted args", function () { | ||
var a = Eventify.enable({}), | ||
b = Eventify.enable({}), | ||
cb = function () { | ||
expect(true).to.be.ok(); | ||
}; | ||
a.listenTo(b, 'event', cb); | ||
b.on('event', cb); | ||
a.listenTo(b, 'event2', cb); | ||
a.stopListening(null, { | ||
event: cb | ||
}); | ||
b.trigger('event event2'); | ||
b.off(); | ||
a.listenTo(b, 'event event2', cb); | ||
a.stopListening(null, 'event'); | ||
a.stopListening(); | ||
b.trigger('event2'); | ||
}); | ||
it("listenToOnce and stopListening", function () { | ||
var a = Eventify.enable({}), | ||
b = Eventify.enable({}); | ||
a.listenToOnce(b, 'all', function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
b.trigger('anything'); | ||
b.trigger('anything'); | ||
a.listenToOnce(b, 'all', function () { | ||
expect(false).not.to.be.ok(); | ||
}); | ||
a.stopListening(); | ||
b.trigger('anything'); | ||
}); | ||
it("listenTo, listenToOnce and stopListening", function () { | ||
var a = Eventify.enable({}), | ||
b = Eventify.enable({}); | ||
a.listenToOnce(b, 'all', function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
b.trigger('anything'); | ||
b.trigger('anything'); | ||
a.listenTo(b, 'all', function () { | ||
expect(false).not.to.be.ok(); | ||
}); | ||
a.stopListening(); | ||
b.trigger('anything'); | ||
}); | ||
it("listenTo and stopListening with event maps", function () { | ||
var a = Eventify.enable({}), | ||
b = Eventify.enable({}); | ||
a.listenTo(b, { | ||
change: function () { | ||
expect(true).to.be.ok(); | ||
} | ||
}); | ||
b.trigger('change'); | ||
a.listenTo(b, { | ||
change: function () { | ||
expect(false).not.to.be.ok(); | ||
} | ||
}); | ||
a.stopListening(); | ||
b.trigger('change'); | ||
}); | ||
it("listenTo yourself", function () { | ||
var e = Eventify.enable({}); | ||
e.listenTo(e, "foo", function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
e.trigger("foo"); | ||
}); | ||
it("listenTo yourself cleans yourself up with stopListening", function () { | ||
var e = Eventify.enable({}); | ||
e.listenTo(e, "foo", function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
e.trigger("foo"); | ||
e.stopListening(); | ||
e.trigger("foo"); | ||
}); | ||
it("listenTo with empty callback doesn't throw an error", function () { | ||
var e = Eventify.enable({}); | ||
e.listenTo(e, "foo", null); | ||
e.trigger("foo"); | ||
expect(true).to.be.ok(); | ||
}); | ||
}); | ||
@@ -91,5 +302,9 @@ | ||
var callback, | ||
obj = { counter: 0 }; | ||
obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
callback = function () { obj.counter = obj.counter + 1; }; | ||
callback = function () { | ||
obj.counter = obj.counter + 1; | ||
}; | ||
obj.on('event', callback); | ||
@@ -106,7 +321,14 @@ obj.trigger('event'); | ||
var callback, | ||
obj = { counterA: 0, counterB: 0 }; | ||
obj = { | ||
counterA: 0, | ||
counterB: 0 | ||
}; | ||
Eventify.enable(obj); | ||
callback = function () { obj.counterA = obj.counterA + 1; }; | ||
callback = function () { | ||
obj.counterA = obj.counterA + 1; | ||
}; | ||
obj.on('event', callback); | ||
obj.on('event', function () { obj.counterB = obj.counterB + 1; }); | ||
obj.on('event', function () { | ||
obj.counterB = obj.counterB + 1; | ||
}); | ||
obj.trigger('event'); | ||
@@ -125,3 +347,5 @@ obj.off('event', callback); | ||
var callback, | ||
obj = {counter: 0}; | ||
obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
@@ -142,4 +366,8 @@ callback = function () { | ||
describe("Two binds that unbind themselves", function () { | ||
var obj = { counterA: 0, counterB: 0 }; | ||
var obj = { | ||
counterA: 0, | ||
counterB: 0 | ||
}; | ||
Eventify.enable(obj); | ||
function incrA() { | ||
@@ -149,2 +377,3 @@ obj.counterA = obj.counterA + 1; | ||
} | ||
function incrB() { | ||
@@ -171,4 +400,4 @@ obj.counterB = obj.counterB + 1; | ||
TestClass = function () { | ||
return this; | ||
}; | ||
return this; | ||
}; | ||
TestClass.prototype.assertTrue = function () { | ||
@@ -180,4 +409,4 @@ expect(true).to.be(true); | ||
obj.on('event', function () { | ||
this.assertTrue(); | ||
}, (new TestClass())); | ||
this.assertTrue(); | ||
}, (new TestClass())); | ||
obj.trigger('event'); | ||
@@ -188,4 +417,7 @@ }); | ||
describe("nested trigger with unbind", function () { | ||
var obj = { counter: 0 }; | ||
var obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
function incr1() { | ||
@@ -196,2 +428,3 @@ obj.counter = obj.counter + 1; | ||
} | ||
function incr2() { | ||
@@ -213,2 +446,3 @@ obj.counter = obj.counter + 1; | ||
obj = Eventify.enable(); | ||
function incr() { | ||
@@ -221,3 +455,3 @@ counter = counter + 1; | ||
}) | ||
.trigger('event'); | ||
.trigger('event'); | ||
expect(counter).to.be(0); | ||
@@ -227,8 +461,8 @@ }); | ||
obj.off() | ||
.on('event', function () { | ||
obj.off('event', incr).off('all', incr); | ||
}) | ||
.on('event', incr) | ||
.on('all', incr) | ||
.trigger('event'); | ||
.on('event', function () { | ||
obj.off('event', incr).off('all', incr); | ||
}) | ||
.on('event', incr) | ||
.on('all', incr) | ||
.trigger('event'); | ||
expect(counter).to.be(2); | ||
@@ -241,2 +475,3 @@ }); | ||
obj = Eventify.enable(); | ||
function incr() { | ||
@@ -249,3 +484,3 @@ counter = counter + 1; | ||
}) | ||
.trigger('x y'); | ||
.trigger('x y'); | ||
expect(counter).to.be(2); | ||
@@ -259,2 +494,10 @@ }); | ||
it("if callback is truthy but not a function, `on` should throw an error" + | ||
" just like jQuery", function () { | ||
var view = Eventify.enable({}).on('test', 'noop'); | ||
expect(function () { | ||
view.trigger('test'); | ||
}).to.throwException(Error); | ||
}); | ||
describe("remove all events for a specific context", function () { | ||
@@ -278,5 +521,7 @@ it("should remove context", function (done) { | ||
var obj = Eventify.enable(); | ||
function success() { | ||
expect(true).to.be(true); | ||
} | ||
function fail() { | ||
@@ -310,4 +555,8 @@ expect(true).to.be(false); | ||
var obj = Eventify.enable(); | ||
obj.on('event', function () { expect(true).to.be(false); }, obj); | ||
obj.on('event', function () { expect(true).to.be(false); }, obj); | ||
obj.on('event', function () { | ||
expect(true).to.be(false); | ||
}, obj); | ||
obj.on('event', function () { | ||
expect(true).to.be(false); | ||
}, obj); | ||
obj.off(null, null, obj); | ||
@@ -319,2 +568,144 @@ obj.trigger('event'); | ||
describe("When attaching an event listener only once, it:", function () { | ||
it("once", function () { | ||
// Same as the previous test, but we use once rather than having to explicitly unbind | ||
var incrA, incrB, | ||
obj = { | ||
counterA: 0, | ||
counterB: 0 | ||
}; | ||
Eventify.enable(obj); | ||
incrA = function () { | ||
obj.counterA += 1; | ||
obj.trigger('event'); | ||
}; | ||
incrB = function () { | ||
obj.counterB += 1; | ||
}; | ||
obj.once('event', incrA); | ||
obj.once('event', incrB); | ||
obj.trigger('event'); | ||
expect(obj.counterA, 1, 'counterA should have only been incremented once.'); | ||
expect(obj.counterB, 1, 'counterB should have only been incremented once.'); | ||
}); | ||
it("once variant one", function () { | ||
var f = function () { | ||
expect(true).to.be.ok(); | ||
}, | ||
a = Eventify.enable({}).once('event', f), | ||
b = Eventify.enable({}).on('event', f); | ||
a.trigger('event'); | ||
b.trigger('event'); | ||
b.trigger('event'); | ||
}); | ||
it("once variant two", function () { | ||
var f = function () { | ||
expect(true).to.be.ok(); | ||
}, | ||
obj = Eventify.enable({}); | ||
obj | ||
.once('event', f) | ||
.on('event', f) | ||
.trigger('event') | ||
.trigger('event'); | ||
}); | ||
it("once with off", function () { | ||
var f = function () { | ||
expect(true).to.be.ok(); | ||
}, | ||
obj = Eventify.enable({}); | ||
obj.once('event', f); | ||
obj.off('event', f); | ||
obj.trigger('event'); | ||
}); | ||
it("once with event maps", function () { | ||
var increment, | ||
obj = { | ||
counter: 0 | ||
}; | ||
Eventify.enable(obj); | ||
increment = function () { | ||
this.counter += 1; | ||
}; | ||
obj.once({ | ||
a: increment, | ||
b: increment, | ||
c: increment | ||
}, obj); | ||
obj.trigger('a'); | ||
expect(obj.counter).eql(1); | ||
obj.trigger('a b'); | ||
expect(obj.counter).eql(2); | ||
obj.trigger('c'); | ||
expect(obj.counter).eql(3); | ||
obj.trigger('a b c'); | ||
expect(obj.counter).eql(3); | ||
}); | ||
it("once with off only by context", function () { | ||
var context = {}, | ||
obj = Eventify.enable({}); | ||
obj.once('event', function () { | ||
expect(false).not.to.be.ok(); | ||
}, context); | ||
obj.off(null, null, context); | ||
obj.trigger('event'); | ||
}); | ||
it("once with asynchronous events", function (done) { | ||
var func = function () { | ||
setTimeout(done, 50); | ||
}, | ||
obj = Eventify.enable({}).once('async', func); | ||
obj.trigger('async'); | ||
obj.trigger('async'); | ||
}); | ||
it("once with multiple events.", function () { | ||
var obj = Eventify.enable({}); | ||
obj.once('x y', function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
obj.trigger('x y'); | ||
}); | ||
it("Off during iteration with once.", function () { | ||
var obj = Eventify.enable({}), | ||
f = function () { | ||
this.off('event', f); | ||
}; | ||
obj.on('event', f); | ||
obj.once('event', function () {}); | ||
obj.on('event', function () { | ||
expect(true).to.be.ok(); | ||
}); | ||
obj.trigger('event'); | ||
obj.trigger('event'); | ||
}); | ||
it("once without a callback is a noop", function () { | ||
Eventify.enable({}).once('event').trigger('event'); | ||
}); | ||
}); | ||
describe("Additional parameters", function () { | ||
@@ -321,0 +712,0 @@ it("should include additional parameters", function (done) { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
46625
14
1005
1
204
8
1