forerunnerdb
Version:
A NoSQL document store database for browsers and Node.js.
396 lines (336 loc) • 13.1 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: Mixin.Events.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: Mixin.Events.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>"use strict";
var Overload = require('./Overload');
/**
* Provides event emitter functionality including the methods: on, off, once, emit, deferEmit.
* @mixin
* @name Events
*/
var Events = {
on: new Overload({
/**
* Attach an event listener to the passed event.
* @name on
* @method Events.on
* @param {String} event The name of the event to listen for.
* @param {Function} listener The method to call when the event is fired.
* @returns {*}
*/
'string, function': function (event, listener) {
this._listeners = this._listeners || {};
this._listeners[event] = this._listeners[event] || {};
this._listeners[event]['*'] = this._listeners[event]['*'] || [];
this._listeners[event]['*'].push(listener);
return this;
},
/**
* Attach an event listener to the passed event only if the passed
* id matches the document id for the event being fired.
* @name on
* @method Events.on
* @param {String} event The name of the event to listen for.
* @param {*} id The document id to match against.
* @param {Function} listener The method to call when the event is fired.
* @returns {*}
*/
'string, *, function': function (event, id, listener) {
this._listeners = this._listeners || {};
this._listeners[event] = this._listeners[event] || {};
this._listeners[event][id] = this._listeners[event][id] || [];
this._listeners[event][id].push(listener);
return this;
}
}),
once: new Overload({
/**
* Attach an event listener to the passed event that will be called only once.
* @name once
* @method Events.once
* @param {String} event The name of the event to listen for.
* @param {Function} listener The method to call when the event is fired.
* @returns {*}
*/
'string, function': function (event, listener) {
var self = this,
fired = false,
internalCallback = function () {
if (!fired) {
self.off(event, internalCallback);
listener.apply(self, arguments);
fired = true;
}
};
return this.on(event, internalCallback);
},
/**
* Attach an event listener to the passed event that will be called only once.
* @name once
* @method Events.once
* @param {String} event The name of the event to listen for.
* @param {String} id The document id to match against.
* @param {Function} listener The method to call when the event is fired.
* @returns {*}
*/
'string, *, function': function (event, id, listener) {
var self = this,
fired = false,
internalCallback = function () {
if (!fired) {
self.off(event, id, internalCallback);
listener.apply(self, arguments);
fired = true;
}
};
return this.on(event, id, internalCallback);
}
}),
off: new Overload({
/**
* Cancels all event listeners for the passed event.
* @name off
* @method Events.off
* @param {String} event The name of the event.
* @returns {*}
*/
'string': function (event) {
var self = this;
if (this._emitting) {
this._eventRemovalQueue = this._eventRemovalQueue || [];
this._eventRemovalQueue.push(function () {
self.off(event);
});
} else {
if (this._listeners && this._listeners[event] && event in this._listeners) {
delete this._listeners[event];
}
}
return this;
},
/**
* Cancels the event listener for the passed event and listener function.
* @name off
* @method Events.off
* @param {String} event The event to cancel listener for.
* @param {Function} listener The event listener function used in the on()
* or once() call to cancel.
* @returns {*}
*/
'string, function': function (event, listener) {
var self = this,
arr,
index;
if (this._emitting) {
this._eventRemovalQueue = this._eventRemovalQueue || [];
this._eventRemovalQueue.push(function () {
self.off(event, listener);
});
} else {
if (typeof(listener) === 'string') {
if (this._listeners && this._listeners[event] && this._listeners[event][listener]) {
delete this._listeners[event][listener];
}
} else {
if (this._listeners && event in this._listeners) {
arr = this._listeners[event]['*'];
index = arr.indexOf(listener);
if (index > -1) {
arr.splice(index, 1);
}
}
}
}
return this;
},
/**
* Cancels an event listener based on an event name, id and listener function.
* @name off
* @method Events.off
* @param {String} event The event to cancel listener for.
* @param {String} id The ID of the event to cancel listening for.
* @param {Function} listener The event listener function used in the on()
* or once() call to cancel.
*/
'string, *, function': function (event, id, listener) {
var self = this;
if (this._emitting) {
this._eventRemovalQueue = this._eventRemovalQueue || [];
this._eventRemovalQueue.push(function () {
self.off(event, id, listener);
});
} else {
if (this._listeners && event in this._listeners && id in this.listeners[event]) {
var arr = this._listeners[event][id],
index = arr.indexOf(listener);
if (index > -1) {
arr.splice(index, 1);
}
}
}
},
/**
* Cancels all listeners for an event based on the passed event name and id.
* @name off
* @method Events.off
* @param {String} event The event name to cancel listeners for.
* @param {*} id The ID to cancel all listeners for.
*/
'string, *': function (event, id) {
var self = this;
if (this._emitting) {
this._eventRemovalQueue = this._eventRemovalQueue || [];
this._eventRemovalQueue.push(function () {
self.off(event, id);
});
} else {
if (this._listeners && event in this._listeners && id in this._listeners[event]) {
// Kill all listeners for this event id
delete this._listeners[event][id];
}
}
}
}),
/**
* Emit an event with data.
* @name emit
* @method Events.emit
* @param {String} event The event to emit.
* @param {*} data Data to emit with the event.
* @returns {*}
*/
emit: function (event, data) {
this._listeners = this._listeners || {};
this._emitting = true;
if (event in this._listeners) {
var arrIndex,
arrCount,
tmpFunc,
arr,
listenerIdArr,
listenerIdCount,
listenerIdIndex;
// Handle global emit
if (this._listeners[event]['*']) {
arr = this._listeners[event]['*'];
arrCount = arr.length;
for (arrIndex = 0; arrIndex < arrCount; arrIndex++) {
// Check we have a function to execute
tmpFunc = arr[arrIndex];
if (typeof tmpFunc === 'function') {
tmpFunc.apply(this, Array.prototype.slice.call(arguments, 1));
}
}
}
// Handle individual emit
if (data instanceof Array) {
// Check if the array is an array of objects in the collection
if (data[0] && data[0][this._primaryKey]) {
// Loop the array and check for listeners against the primary key
listenerIdArr = this._listeners[event];
arrCount = data.length;
for (arrIndex = 0; arrIndex < arrCount; arrIndex++) {
if (listenerIdArr[data[arrIndex][this._primaryKey]]) {
// Emit for this id
listenerIdCount = listenerIdArr[data[arrIndex][this._primaryKey]].length;
for (listenerIdIndex = 0; listenerIdIndex < listenerIdCount; listenerIdIndex++) {
tmpFunc = listenerIdArr[data[arrIndex][this._primaryKey]][listenerIdIndex];
if (typeof tmpFunc === 'function') {
listenerIdArr[data[arrIndex][this._primaryKey]][listenerIdIndex].apply(this, Array.prototype.slice.call(arguments, 1));
}
}
}
}
}
}
}
this._emitting = false;
this._processRemovalQueue();
return this;
},
/**
* If events are cleared with the off() method while the event emitter is
* actively processing any events then the off() calls get added to a
* queue to be executed after the event emitter is finished. This stops
* errors that might occur by potentially modifying the event queue while
* the emitter is running through them. This method is called after the
* event emitter is finished processing.
* @name _processRemovalQueue
* @method Events._processRemovalQueue
* @private
*/
_processRemovalQueue: function () {
var i;
if (this._eventRemovalQueue && this._eventRemovalQueue.length) {
// Execute each removal call
for (i = 0; i < this._eventRemovalQueue.length; i++) {
this._eventRemovalQueue[i]();
}
// Clear the removal queue
this._eventRemovalQueue = [];
}
},
/**
* Queues an event to be fired. This has automatic de-bouncing so that any
* events of the same type that occur within 100 milliseconds of a previous
* one will all be wrapped into a single emit rather than emitting tons of
* events for lots of chained inserts etc. Only the data from the last
* de-bounced event will be emitted.
* @name deferEmit
* @method Events.deferEmit
* @param {String} eventName The name of the event to emit.
* @param {*=} data Optional data to emit with the event.
*/
deferEmit: function (eventName, data) {
var self = this,
args;
if (!this._noEmitDefer && (!this._db || (this._db && !this._db._noEmitDefer))) {
args = arguments;
// Check for an existing timeout
this._deferTimeout = this._deferTimeout || {};
if (this._deferTimeout[eventName]) {
clearTimeout(this._deferTimeout[eventName]);
}
// Set a timeout
this._deferTimeout[eventName] = setTimeout(function () {
if (self.debug()) {
console.log(self.logIdentifier() + ' Emitting ' + args[0]);
}
self.emit.apply(self, args);
}, 1);
} else {
this.emit.apply(this, arguments);
}
return this;
}
};
module.exports = Events;</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ActiveBucket.html">ActiveBucket</a></li><li><a href="Angular.html">Angular</a></li><li><a href="AutoBind.html">AutoBind</a></li><li><a href="Collection.html">Collection</a></li><li><a href="CollectionGroup.html">CollectionGroup</a></li><li><a href="Condition.html">Condition</a></li><li><a href="Core.html">Core</a></li><li><a href="Db.html">Db</a></li><li><a href="Document.html">Document</a></li><li><a href="Grid.html">Grid</a></li><li><a href="Highchart.html">Highchart</a></li><li><a href="Index2d.html">Index2d</a></li><li><a href="IndexBinaryTree.html">IndexBinaryTree</a></li><li><a href="IndexHashMap.html">IndexHashMap</a></li><li><a href="Infinilist.html">Infinilist</a></li><li><a href="KeyValueStore.html">KeyValueStore</a></li><li><a href="Metrics.html">Metrics</a></li><li><a href="MyModule.html">MyModule</a></li><li><a href="NodeApiClient.html">NodeApiClient</a></li><li><a href="NodeApiServer.html">NodeApiServer</a></li><li><a href="NodeRAS.html">NodeRAS</a></li><li><a href="Odm.html">Odm</a></li><li><a href="OldView.html">OldView</a></li><li><a href="Operation.html">Operation</a></li><li><a href="Overload.html">Overload</a></li><li><a href="Overview.html">Overview</a></li><li><a href="Overview_init.html">init</a></li><li><a href="Path.html">Path</a></li><li><a href="Persist.html">Persist</a></li><li><a href="Procedure.html">Procedure</a></li><li><a href="ReactorIO.html">ReactorIO</a></li><li><a href="Section.html">Section</a></li><li><a href="Serialiser.html">Serialiser</a></li><li><a href="Shared.overload.html">overload</a></li><li><a href="View.html">View</a></li></ul><h3>Mixins</h3><ul><li><a href="ChainReactor.html">ChainReactor</a></li><li><a href="Common.html">Common</a></li><li><a href="Constants.html">Constants</a></li><li><a href="Events.html">Events</a></li><li><a href="Matching.html">Matching</a></li><li><a href="Shared.html">Shared</a></li><li><a href="Sorting.html">Sorting</a></li><li><a href="Tags.html">Tags</a></li><li><a href="Triggers.html">Triggers</a></li><li><a href="Updating.html">Updating</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Thu Mar 01 2018 11:34:22 GMT+0000 (GMT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>