API Docs for: 0.2.2
Show:

File: src\R.EventEmitter.js

module.exports = function(R) {
    var _ = require("lodash");
    var assert = require("assert");

    /**
    * <p>R.EventEmitter is similar to R.Store. <br />
    * Event Emitters are event-oriented stores without persistence. <br />
    * It juste provides a slightly different abstraction, that is sometimes more suited.</p>
    * @class R.EventEmitter
    */
    var EventEmitter = {
        /**
        * <p> Returns a new EventEmitter constructor
        * @method createEventEmitter
        * @param {object} specs The specifications
        * @return {object} EventEmitterInstance The created EventEmitterInstance
        */
        createEventEmitter: function createEventEmitter(specs) {
            R.Debug.dev(function() {
                assert(_.isObject(specs), "R.EventEmitter.createEventEmitter(...): expecting an Object as specs.");
                assert(_.has(specs, "displayName") && _.isString(specs.displayName), "R.EventEmitter.createEventEmitter(...): requires displayName(String).");
                assert(_.has(specs, "addListener") && _.isFunction(specs.addListener), "R.EventEmitter.createEventEmitter(...): requires addListener(String, Function): R.EventEmitter.Listener.");
                assert(_.has(specs, "removeListener") && _.isFunction(specs.removeListener), "R.EventEmitter.createEventEmitter(...)");
            });
            /**
             * @memberOf R.EventEmitter
             * @public
             */
            var EventEmitterInstance = function EventEmitterInstance() {};
            _.extend(EventEmitterInstance.prototype, specs, {
                /**
                 *  Type dirty-checking.
                 *  @private
                 *  @readOnly
                 */
                _isEventEmitterInstance_: true,
            });
            return EventEmitterInstance;
        },
        Listener: function Listener(event) {
            this.uniqueId = _.uniqueId("R.EventEmitter.Listener");
            this.event = event;
        },
        /**
        * <p> Returns a new MemoryEventEmitter that represents a memory-local store, eg. clicks, window events.</p>
        * @method createMemoryEventEmitter
        * @return {object} MemoryEventEmitter The created MemoryEventEmitter instance
        */
        createMemoryEventEmitter: function createMemoryEventEmitter() {
            return function MemoryEventEmitter() {
                var listeners = {};
                var addListener = function addListener(event, fn) {
                    var listener = new R.EventEmitter.Listener(event);
                    if(!_.has(listeners, event)) {
                        listeners[event] = {};
                    }
                    listeners[event][listener.uniqueId] = fn;
                    return listener;
                };
                var removeListener = function removeListener(listener) {
                    R.Debug.dev(function() {
                        assert(listener instanceof R.EventEmitter.Listener, "R.EventEmitter.MemoryEventEmitter.removeListener(...): type R.EventEmitter.Listener expected.");
                        assert(_.has(listeners, listener.event), "R.EventEmitter.MemoryEventEmitter.removeListener(...): no listeners for this event.");
                        assert(_.has(listeners[listener.event], listener.uniqueId), "R.EventEmitter.MemoryEventEmitter.removeListener(...): no such listener.");
                    });
                    delete listeners[listener.event][listener.uniqueId];
                    if(_.size(listeners[listener.event]) === 0) {
                        delete listeners[listener.event];
                    }
                };
                var emit = function emit(event, params) {
                    params = params || {};
                    if(_.has(listeners, event)) {
                        _.each(listeners[event], function(fn) {
                            if(fn) {
                                fn(params);
                            }
                        });
                    }
                };
                return new (R.EventEmitter.createEventEmitter({
                    displayName: "MemoryEventEmitter",
                    addListener: addListener,
                    removeListener: removeListener,
                    emit: emit,
                }))();
            };
        },
        /**
        * <p> Returns a new UplinkEventEmitter that represents a remote event emmiter, eg. global notifications, broadcasts. </p>
        * @method createUplinkEventEmitter
        * @return {object} UplinkEventEmitter The created UplinkEventEmitter instance
        */
        createUplinkEventEmitter: function createUplinkEventEmitter() {
            return function UplinkEventEmitter(uplink) {
                R.Debug.dev(function() {
                    assert(uplink.listenTo && _.isFunction(uplink.listenTo), "R.EventEmitter.createUplinkEventEmitter(...).uplink.listenTo: expecting Function.");
                    assert(uplink.unlistenFrom && _.isFunction(uplink.unlistenFrom), "R.EventEmitter.createUplinkEventEmitter(...).uplink.unlistenFrom: expecting Function.");
                });
                var listenTo = uplink.listenTo;
                var unlistenFrom = uplink.unlistenFrom;
                var listeners = {};
                var emitters = {};
                var addListener = function addListener(event, fn) {
                    var listener = new R.EventEmitter.Listener(event);
                    if(!_.has(listeners, event)) {
                        emitters[event] = listenTo(event, _.partial(emit, event));
                        listeners[event] = {};
                    }
                    listeners[event][listener.uniqueId] = fn;
                    return listener;
                };
                var removeListener = function removeListener(listener) {
                    R.Debug.dev(function() {
                        assert(listener instanceof R.EventEmitter.Listener, "R.EventEmitter.UplinkEventEmitter.removeListener(...): type R.EventEmitter.Listener expected.");
                        assert(_.has(listeners, listener.event), "R.EventEmitter.UplinkEventEmitter.removeListener(...): no listeners for this event.");
                        assert(_.has(listeners[listener.event], listener.uniqueId), "R.EventEmitter.UplinkEventEmitter.removeListener(...): no such listener.");
                    });
                    delete listeners[listener.event][listener.uniqueId];
                    if(_.size(listeners[listener.event]) === 0) {
                        unlistenFrom(listener.event, emitters[event]);
                        delete listeners[listener.event];
                        delete emitters[listener.event];
                    }
                };
                var emit = function emit(event, params) {
                    params = params || {};
                    if(_.has(listeners, event)) {
                        _.each(listeners[event], function(fn) {
                            if(fn) {
                                fn(params);
                            }
                        });
                    }
                };
                return new (R.EventEmitter.createEventEmitter({
                    displayName: "UplinkEventEmitter",
                    addListener: addListener,
                    removeListener: removeListener,
                }))();
            };
        },
    };

    _.extend(EventEmitter.Listener.prototype, /** @lends R.EventEmitter.Listener.prototype */ {
        /**
         * @property uniqueId
         * @type {String}
         * @public
         * @readOnly
         */
        uniqueId: null,
        /**
         * @property event
         * @type {String}
         * @public
         * @readOnly
         */
        event: null,
    });

    return EventEmitter;
};