cjs-emitter
Advanced tools
Comparing version 1.4.1 to 1.5.0
385
index.js
/** | ||
* @author Stanislav Kalashnik <darkpark.main@gmail.com> | ||
* @license GNU GENERAL PUBLIC LICENSE Version 3 | ||
* @license The MIT License (MIT) | ||
* @copyright Stanislav Kalashnik <darkpark.main@gmail.com> | ||
*/ | ||
/* eslint no-path-concat: 0 */ | ||
'use strict'; | ||
@@ -19,24 +21,26 @@ | ||
function Emitter () { | ||
if ( DEBUG ) { | ||
if ( typeof this !== 'object' ) { throw new Error(__filename + ': must be constructed via new'); } | ||
} | ||
console.assert(typeof this === 'object', 'must be constructed via new'); | ||
/** | ||
* Inner hash table for event names and linked callbacks. | ||
* Manual editing should be avoided. | ||
* | ||
* @member {Object.<string, function[]>} | ||
* | ||
* @example | ||
* { | ||
* click: [ | ||
* function click1 () { ... }, | ||
* function click2 () { ... } | ||
* ], | ||
* keydown: [ | ||
* function () { ... } | ||
* ] | ||
* } | ||
**/ | ||
this.events = {}; | ||
// if ( DEVELOP ) { | ||
// if ( typeof this !== 'object' ) { throw new Error(__filename + ': must be constructed via new'); } | ||
// } | ||
/** | ||
* Inner hash table for event names and linked callbacks. | ||
* Manual editing should be avoided. | ||
* | ||
* @member {Object.<string, function[]>} | ||
* | ||
* @example | ||
* { | ||
* click: [ | ||
* function click1 () { ... }, | ||
* function click2 () { ... } | ||
* ], | ||
* keydown: [ | ||
* function () { ... } | ||
* ] | ||
* } | ||
**/ | ||
this.events = {}; | ||
} | ||
@@ -46,187 +50,196 @@ | ||
Emitter.prototype = { | ||
/** | ||
* Bind an event to the given callback function. | ||
* The same callback function can be added multiple times for the same event name. | ||
* | ||
* @param {string} name event identifier | ||
* @param {function} callback function to call on this event | ||
* | ||
* @example | ||
* emitter.addListener('click', function ( data ) { ... }); | ||
* // one more click handler | ||
* emitter.addListener('click', function ( data ) { ... }); | ||
*/ | ||
addListener: function ( name, callback ) { | ||
if ( DEBUG ) { | ||
if ( arguments.length !== 2 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
if ( typeof callback !== 'function' ) { throw new Error(__filename + ': wrong callback type'); } | ||
} | ||
/** | ||
* Bind an event to the given callback function. | ||
* The same callback function can be added multiple times for the same event name. | ||
* | ||
* @param {string} name event identifier | ||
* @param {function} callback function to call on this event | ||
* | ||
* @example | ||
* emitter.addListener('click', function ( data ) { ... }); | ||
* // one more click handler | ||
* emitter.addListener('click', function ( data ) { ... }); | ||
*/ | ||
addListener: function ( name, callback ) { | ||
console.assert(arguments.length === 2, 'wrong arguments number'); | ||
console.assert(typeof name === 'string', 'wrong name type'); | ||
console.assert(name.length > 0, 'empty name'); | ||
console.assert(typeof callback === 'function', 'callback should be a function'); | ||
// initialization may be required | ||
this.events[name] = this.events[name] || []; | ||
// append this new event to the list | ||
this.events[name].push(callback); | ||
}, | ||
// if ( DEVELOP ) { | ||
// if ( arguments.length !== 2 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
// if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
// if ( typeof callback !== 'function' ) { throw new Error(__filename + ': wrong callback type'); } | ||
// } | ||
// initialization may be required | ||
this.events[name] = this.events[name] || []; | ||
// append this new event to the list | ||
this.events[name].push(callback); | ||
}, | ||
/** | ||
* Add a one time listener for the event. | ||
* This listener is invoked only the next time the event is fired, after which it is removed. | ||
* | ||
* @param {string} name event identifier | ||
* @param {function} callback function to call on this event | ||
* | ||
* @example | ||
* emitter.once('click', function ( data ) { ... }); | ||
*/ | ||
once: function ( name, callback ) { | ||
// current execution context | ||
var self = this; | ||
if ( DEBUG ) { | ||
if ( arguments.length !== 2 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
if ( typeof callback !== 'function' ) { throw new Error(__filename + ': wrong callback type'); } | ||
} | ||
/** | ||
* Add a one time listener for the event. | ||
* This listener is invoked only the next time the event is fired, after which it is removed. | ||
* | ||
* @param {string} name event identifier | ||
* @param {function} callback function to call on this event | ||
* | ||
* @example | ||
* emitter.once('click', function ( data ) { ... }); | ||
*/ | ||
once: function ( name, callback ) { | ||
// current execution context | ||
var self = this; | ||
// initialization may be required | ||
this.events[name] = this.events[name] || []; | ||
// append this new event to the list | ||
this.events[name].push(function onceWrapper () { | ||
callback.apply(this, arguments); | ||
self.removeListener(name, onceWrapper); | ||
}); | ||
}, | ||
if ( DEVELOP ) { | ||
if ( arguments.length !== 2 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
if ( typeof callback !== 'function' ) { throw new Error(__filename + ': wrong callback type'); } | ||
} | ||
// initialization may be required | ||
this.events[name] = this.events[name] || []; | ||
// append this new event to the list | ||
this.events[name].push(function onceWrapper () { | ||
callback.apply(self, arguments); | ||
self.removeListener(name, onceWrapper); | ||
}); | ||
}, | ||
/** | ||
* Apply multiple listeners at once. | ||
* | ||
* @param {Object} callbacks event names with callbacks | ||
* | ||
* @example | ||
* emitter.addListeners({ | ||
* click: function ( data ) {}, | ||
* close: function ( data ) {} | ||
* }); | ||
*/ | ||
addListeners: function ( callbacks ) { | ||
var name; | ||
if ( DEBUG ) { | ||
if ( arguments.length !== 1 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof callbacks !== 'object' ) { throw new Error(__filename + ': wrong callbacks type'); } | ||
if ( Object.keys(callbacks).length === 0 ) { throw new Error(__filename + ': no callbacks given'); } | ||
} | ||
/** | ||
* Apply multiple listeners at once. | ||
* | ||
* @param {Object} callbacks event names with callbacks | ||
* | ||
* @example | ||
* emitter.addListeners({ | ||
* click: function ( data ) {}, | ||
* close: function ( data ) {} | ||
* }); | ||
*/ | ||
addListeners: function ( callbacks ) { | ||
var name; | ||
for ( name in callbacks ) { | ||
if ( callbacks.hasOwnProperty(name) ) { | ||
this.addListener(name, callbacks[name]); | ||
} | ||
} | ||
}, | ||
if ( DEVELOP ) { | ||
if ( arguments.length !== 1 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof callbacks !== 'object' ) { throw new Error(__filename + ': wrong callbacks type'); } | ||
if ( Object.keys(callbacks).length === 0 ) { throw new Error(__filename + ': no callbacks given'); } | ||
} | ||
for ( name in callbacks ) { | ||
if ( callbacks.hasOwnProperty(name) ) { | ||
this.addListener(name, callbacks[name]); | ||
} | ||
} | ||
}, | ||
/** | ||
* Remove all instances of the given callback. | ||
* | ||
* @param {string} name event identifier | ||
* @param {function} callback function to remove | ||
* | ||
* @example | ||
* emitter.removeListener('click', func1); | ||
*/ | ||
removeListener: function ( name, callback ) { | ||
if ( DEBUG ) { | ||
if ( arguments.length !== 2 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
if ( typeof callback !== 'function' ) { throw new Error(__filename + ': wrong callback type'); } | ||
if ( this.events[name] && !Array.isArray(this.events[name]) ) { throw new Error(__filename + ': corrupted inner data'); } | ||
} | ||
// the event exists and should have some callbacks | ||
if ( this.events[name] ) { | ||
// rework the callback list to exclude the given one | ||
this.events[name] = this.events[name].filter(function callbacksFilter ( fn ) { return fn !== callback; }); | ||
// event has no more callbacks so clean it | ||
if ( this.events[name].length === 0 ) { | ||
// as if there were no listeners at all | ||
this.events[name] = undefined; | ||
} | ||
} | ||
}, | ||
/** | ||
* Remove all instances of the given callback. | ||
* | ||
* @param {string} name event identifier | ||
* @param {function} callback function to remove | ||
* | ||
* @example | ||
* emitter.removeListener('click', func1); | ||
*/ | ||
removeListener: function ( name, callback ) { | ||
if ( DEVELOP ) { | ||
if ( arguments.length !== 2 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
if ( typeof callback !== 'function' ) { throw new Error(__filename + ': wrong callback type'); } | ||
if ( this.events[name] && !Array.isArray(this.events[name]) ) { throw new Error(__filename + ': corrupted inner data'); } | ||
} | ||
// the event exists and should have some callbacks | ||
if ( this.events[name] ) { | ||
// rework the callback list to exclude the given one | ||
this.events[name] = this.events[name].filter(function callbacksFilter ( fn ) { return fn !== callback; }); | ||
// event has no more callbacks so clean it | ||
if ( this.events[name].length === 0 ) { | ||
// as if there were no listeners at all | ||
this.events[name] = undefined; | ||
} | ||
} | ||
}, | ||
/** | ||
* Remove all callbacks for the given event name. | ||
* Without event name clears all events. | ||
* | ||
* @param {string} [name] event identifier | ||
* | ||
* @example | ||
* emitter.removeAllListeners('click'); | ||
* emitter.removeAllListeners(); | ||
*/ | ||
removeAllListeners: function ( name ) { | ||
if ( DEBUG ) { | ||
if ( arguments.length !== 0 && (typeof name !== 'string' || name.length === 0) ) { throw new Error(__filename + ': wrong or empty name'); } | ||
} | ||
// check input | ||
if ( arguments.length === 0 ) { | ||
// no arguments so remove everything | ||
this.events = {}; | ||
} else if ( name ) { | ||
if ( DEBUG ) { | ||
if ( this.events[name] ) { throw new Error(__filename + ': event is not removed'); } | ||
} | ||
/** | ||
* Remove all callbacks for the given event name. | ||
* Without event name clears all events. | ||
* | ||
* @param {string} [name] event identifier | ||
* | ||
* @example | ||
* emitter.removeAllListeners('click'); | ||
* emitter.removeAllListeners(); | ||
* | ||
* @deprecated | ||
*/ | ||
/*removeAllListeners: function ( name ) { | ||
if ( DEVELOP ) { | ||
if ( arguments.length !== 0 && (typeof name !== 'string' || name.length === 0) ) { | ||
throw new Error(__filename + ': wrong or empty name'); | ||
} | ||
} | ||
// only name is given so remove all callbacks for the given event | ||
// but object structure modification should be avoided | ||
this.events[name] = undefined; | ||
} | ||
}, | ||
// check input | ||
if ( arguments.length === 0 ) { | ||
// no arguments so remove everything | ||
this.events = {}; | ||
} else if ( name ) { | ||
if ( DEVELOP ) { | ||
if ( this.events[name] ) { throw new Error(__filename + ': event is not removed'); } | ||
} | ||
// only name is given so remove all callbacks for the given event | ||
// but object structure modification should be avoided | ||
this.events[name] = undefined; | ||
} | ||
},*/ | ||
/** | ||
* Execute each of the listeners in the given order with the supplied arguments. | ||
* | ||
* @param {string} name event identifier | ||
* | ||
* @example | ||
* emitter.emit('init'); | ||
* emitter.emit('click', {src: panel1, dst: panel2}); | ||
* emitter.emit('load', error, data); | ||
* | ||
* // it's a good idea to emit event only when there are some listeners | ||
* if ( this.events['click'] ) { | ||
* this.emit('click', {event: event}); | ||
* } | ||
*/ | ||
emit: function ( name ) { | ||
var event = this.events[name], | ||
i; | ||
if ( DEBUG ) { | ||
if ( arguments.length < 1 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
} | ||
/** | ||
* Execute each of the listeners in the given order with the supplied arguments. | ||
* | ||
* @param {string} name event identifier | ||
* | ||
* @example | ||
* emitter.emit('init'); | ||
* emitter.emit('click', {src: panel1, dst: panel2}); | ||
* emitter.emit('load', error, data); | ||
* | ||
* // it's a good idea to emit event only when there are some listeners | ||
* if ( this.events['click'] ) { | ||
* this.emit('click', {event: event}); | ||
* } | ||
*/ | ||
emit: function ( name ) { | ||
var event = this.events[name], | ||
index; | ||
// the event exists and should have some callbacks | ||
if ( event ) { | ||
if ( DEBUG ) { | ||
if ( !Array.isArray(event) ) { throw new Error(__filename + ': wrong event type'); } | ||
} | ||
if ( DEVELOP ) { | ||
if ( arguments.length < 1 ) { throw new Error(__filename + ': wrong arguments number'); } | ||
if ( typeof name !== 'string' || name.length === 0 ) { throw new Error(__filename + ': wrong or empty name'); } | ||
} | ||
for ( i = 0; i < event.length; i++ ) { | ||
if ( DEBUG ) { | ||
if ( typeof event[i] !== 'function' ) { throw new Error(__filename + ': wrong event callback type'); } | ||
} | ||
// the event exists and should have some callbacks | ||
if ( event ) { | ||
if ( DEVELOP ) { | ||
if ( !Array.isArray(event) ) { throw new Error(__filename + ': wrong event type'); } | ||
} | ||
// invoke the callback with parameters | ||
event[i].apply(this, Array.prototype.slice.call(arguments, 1)); | ||
} | ||
} | ||
} | ||
for ( index = 0; index < event.length; index++ ) { | ||
if ( DEVELOP ) { | ||
if ( typeof event[index] !== 'function' ) { throw new Error(__filename + ': wrong event callback type'); } | ||
} | ||
// invoke the callback with parameters | ||
event[index].apply(this, Array.prototype.slice.call(arguments, 1)); | ||
} | ||
} | ||
} | ||
}; | ||
@@ -233,0 +246,0 @@ |
{ | ||
"name": "cjs-emitter", | ||
"version": "1.4.1", | ||
"description": "Basic events emitter implementation.", | ||
"author": { | ||
"name": "Stanislav Kalashnik", | ||
"email": "darkpark.main@gmail.com" | ||
}, | ||
"repository": "cjssdk/emitter", | ||
"scripts": { | ||
"lint": "eslint ./*.js" | ||
}, | ||
"devDependencies": {}, | ||
"keywords": [ | ||
"commonjs", | ||
"sdk", | ||
"framework", | ||
"emitter" | ||
], | ||
"license": "GPL-3.0" | ||
"name": "cjs-emitter", | ||
"version": "1.5.0", | ||
"description": "Basic events emitter implementation.", | ||
"author": { | ||
"name": "Stanislav Kalashnik", | ||
"email": "darkpark.main@gmail.com" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/cjssdk/emitter.git" | ||
}, | ||
"scripts": { | ||
"lint": "eslint .", | ||
"test": "npm run lint", | ||
"jsdoc": "jsdoc --destination doc *.js readme.md" | ||
}, | ||
"devDependencies": { | ||
"cjs-eslint-config": "1.*.*", | ||
"eslint": "3.*.*" | ||
}, | ||
"keywords": [ | ||
"commonjs", | ||
"sdk", | ||
"cjssdk", | ||
"framework", | ||
"emitter" | ||
], | ||
"license": "MIT" | ||
} |
Basic events emitter implementation | ||
=================================== | ||
[![Build Status](https://img.shields.io/travis/cjssdk/emitter.svg?style=flat-square)](https://travis-ci.org/cjssdk/emitter) | ||
[![NPM version](https://img.shields.io/npm/v/cjs-emitter.svg?style=flat-square)](https://www.npmjs.com/package/cjs-emitter) | ||
[![Dependencies Status](https://img.shields.io/david/cjssdk/emitter.svg?style=flat-square)](https://david-dm.org/cjssdk/emitter) | ||
[![Gitter](https://img.shields.io/badge/gitter-join%20chat-blue.svg?style=flat-square)](https://gitter.im/DarkPark/stb) | ||
[![Gitter](https://img.shields.io/badge/gitter-join%20chat-blue.svg?style=flat-square)](https://gitter.im/DarkPark/cjssdk) | ||
[![RunKit](https://img.shields.io/badge/RunKit-try-yellow.svg?style=flat-square)](https://runkit.com/npm/cjs-emitter) | ||
Almost all components in STB SDK emit events: a [Model](https://github.com/cjssdk/model) emits an event each time an attribute is set, a [router](https://github.com/stbsdk/router) emits an event when a page is opened. | ||
All components which emit events are instances of `Emitter`. | ||
Typically, there are no strict restrictions on event names, as any string will be accepted. | ||
Usually it's a lowercase string with no spaces. Possible values: `click`, `move`, `focus:item`. | ||
Typically, there aren't any strict restrictions on event names, as any string will be accepted. Usually it's a lowercase string with no spaces. Possible values: `click`, `move`, `focus:item`. | ||
Functions can then be attached to objects, to be executed when an event is emitted. | ||
These functions are called listeners. Inside a listener function, this refers to the `Emitter` that the listener was attached to. | ||
Functions can then be attached to objects, to be executed when an event is emitted. These functions are called listeners. Inside a listener function, this refers to the `Emitter` that the listener was attached to. | ||
## Installation ## | ||
## Installation | ||
```bash | ||
@@ -24,3 +25,3 @@ npm install cjs-emitter | ||
## Usage | ||
## Usage ## | ||
@@ -42,4 +43,4 @@ Add the constructor to the scope: | ||
```js | ||
emitter.addListener('click', function ( data ) { ... }); | ||
emitter.addListener('click', function ( data ) { ... }); | ||
emitter.addListener('click', function ( data ) { /* ... */ }); | ||
emitter.addListener('click', function ( data ) { /* ... */ }); | ||
``` | ||
@@ -50,3 +51,3 @@ | ||
```js | ||
emitter.once('click', function ( data ) { ... }); | ||
emitter.once('click', function ( data ) { /* ... */ }); | ||
``` | ||
@@ -90,9 +91,9 @@ | ||
## Performance notes | ||
## Performance notes ## | ||
It's a good idea to emit event only when there are some listeners: | ||
It's a good idea to emit events only when there are some listeners: | ||
```js | ||
if ( emitter.events['click'] ) { | ||
// notify listeners | ||
// notify listeners | ||
emitter.emit('click', {event: event}); | ||
@@ -103,8 +104,8 @@ } | ||
## Debug mode | ||
## Development mode ## | ||
> There is a global var `DEBUG` which activates additional consistency checks and protection logic not available in release mode. | ||
> There is a global var `DEVELOP` which activates additional consistency checks and protection logic not available in release mode. | ||
## Contribution | ||
## Contribution ## | ||
@@ -115,4 +116,4 @@ If you have any problem or suggestion please open an issue [here](https://github.com/cjssdk/emitter/issues). | ||
## License | ||
## License ## | ||
`cjs-emitter` is released under the [GPL-3.0 License](http://opensource.org/licenses/GPL-3.0). | ||
`cjs-emitter` is released under the [MIT License](license.md). |
Sorry, the diff of this file is not supported yet
Copyleft License
License(Experimental) Copyleft license information was found.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
Non-permissive License
License(Experimental) A license not known to be considered permissive was found.
Found 1 instance in 1 package
13119
5
0
100
216
114
0
2