137 lines
3.4 KiB
JavaScript
137 lines
3.4 KiB
JavaScript
/**
|
||
* Create an event emitter with namespaces
|
||
* @name createNamespaceEmitter
|
||
* @example
|
||
* var emitter = require('./index')()
|
||
*
|
||
* emitter.on('*', function () {
|
||
* console.log('all events emitted', this.event)
|
||
* })
|
||
*
|
||
* emitter.on('example', function () {
|
||
* console.log('example event emitted')
|
||
* })
|
||
*/
|
||
module.exports = function createNamespaceEmitter () {
|
||
var emitter = {}
|
||
var _fns = emitter._fns = {}
|
||
|
||
/**
|
||
* Emit an event. Optionally namespace the event. Handlers are fired in the order in which they were added with exact matches taking precedence. Separate the namespace and event with a `:`
|
||
* @name emit
|
||
* @param {String} event – the name of the event, with optional namespace
|
||
* @param {...*} data – up to 6 arguments that are passed to the event listener
|
||
* @example
|
||
* emitter.emit('example')
|
||
* emitter.emit('demo:test')
|
||
* emitter.emit('data', { example: true}, 'a string', 1)
|
||
*/
|
||
emitter.emit = function emit (event, arg1, arg2, arg3, arg4, arg5, arg6) {
|
||
var toEmit = getListeners(event)
|
||
|
||
if (toEmit.length) {
|
||
emitAll(event, toEmit, [arg1, arg2, arg3, arg4, arg5, arg6])
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Create en event listener.
|
||
* @name on
|
||
* @param {String} event
|
||
* @param {Function} fn
|
||
* @example
|
||
* emitter.on('example', function () {})
|
||
* emitter.on('demo', function () {})
|
||
*/
|
||
emitter.on = function on (event, fn) {
|
||
if (!_fns[event]) {
|
||
_fns[event] = []
|
||
}
|
||
|
||
_fns[event].push(fn)
|
||
}
|
||
|
||
/**
|
||
* Create en event listener that fires once.
|
||
* @name once
|
||
* @param {String} event
|
||
* @param {Function} fn
|
||
* @example
|
||
* emitter.once('example', function () {})
|
||
* emitter.once('demo', function () {})
|
||
*/
|
||
emitter.once = function once (event, fn) {
|
||
function one () {
|
||
fn.apply(this, arguments)
|
||
emitter.off(event, one)
|
||
}
|
||
this.on(event, one)
|
||
}
|
||
|
||
/**
|
||
* Stop listening to an event. Stop all listeners on an event by only passing the event name. Stop a single listener by passing that event handler as a callback.
|
||
* You must be explicit about what will be unsubscribed: `emitter.off('demo')` will unsubscribe an `emitter.on('demo')` listener,
|
||
* `emitter.off('demo:example')` will unsubscribe an `emitter.on('demo:example')` listener
|
||
* @name off
|
||
* @param {String} event
|
||
* @param {Function} [fn] – the specific handler
|
||
* @example
|
||
* emitter.off('example')
|
||
* emitter.off('demo', function () {})
|
||
*/
|
||
emitter.off = function off (event, fn) {
|
||
var keep = []
|
||
|
||
if (event && fn) {
|
||
var fns = this._fns[event]
|
||
var i = 0
|
||
var l = fns ? fns.length : 0
|
||
|
||
for (i; i < l; i++) {
|
||
if (fns[i] !== fn) {
|
||
keep.push(fns[i])
|
||
}
|
||
}
|
||
}
|
||
|
||
keep.length ? this._fns[event] = keep : delete this._fns[event]
|
||
}
|
||
|
||
function getListeners (e) {
|
||
var out = _fns[e] ? _fns[e] : []
|
||
var idx = e.indexOf(':')
|
||
var args = (idx === -1) ? [e] : [e.substring(0, idx), e.substring(idx + 1)]
|
||
|
||
var keys = Object.keys(_fns)
|
||
var i = 0
|
||
var l = keys.length
|
||
|
||
for (i; i < l; i++) {
|
||
var key = keys[i]
|
||
if (key === '*') {
|
||
out = out.concat(_fns[key])
|
||
}
|
||
|
||
if (args.length === 2 && args[0] === key) {
|
||
out = out.concat(_fns[key])
|
||
break
|
||
}
|
||
}
|
||
|
||
return out
|
||
}
|
||
|
||
function emitAll (e, fns, args) {
|
||
var i = 0
|
||
var l = fns.length
|
||
|
||
for (i; i < l; i++) {
|
||
if (!fns[i]) break
|
||
fns[i].event = e
|
||
fns[i].apply(fns[i], args)
|
||
}
|
||
}
|
||
|
||
return emitter
|
||
}
|