UNPKG

edo

Version:
745 lines (588 loc) 118 kB
"use strict";var _keys = require("babel-runtime/core-js/object/keys");var _keys2 = _interopRequireDefault(_keys);var _symbol = require("babel-runtime/core-js/symbol");var _symbol2 = _interopRequireDefault(_symbol);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} /*; @module-license: The MIT License (MIT) @mit-license Copyright (@c) 2017 Richeve Siodina Bebedor @email: richeve.bebedor@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @end-module-license @module-configuration: { "package": "edo", "path": "edo/edo.js", "file": "edo.js", "module": "edo", "author": "Richeve S. Bebedor", "eMail": "richeve.bebedor@gmail.com", "contributors": [ "John Lenon Maghanoy <johnlenonmaghanoy@gmail.com>", "Vinse Vinalon <vinsevinalon@gmail.com>" ], "repository": "https://github.com/volkovasystems/edo.git", "test": "edo-test.js", "global": true } @end-module-configuration @module-documentation: EventEmitter extension. @end-module-documentation @include: { "arid": "arid", "asea": "asea", "asyum": "asyum", "called": "called", "clazof": "clazof", "depher": "depher", "diatom": "diatom", "eqe": "eqe", "embedd": "embedd", "EventEmitter": "events", "falzy": "falzy", "harden": "harden", "heredito": "heredito", "idntfy": "idntfy", "idntty": "idntty", "ferge": "ferge", "infray": "infray", "kein": "kein", "kurse": "kurse", "leveld": "leveld", "plough": "plough", "pyp": "pyp", "protype": "protype", "pyck": "pyck", "raze": "raze", "shft": "shft", "symbiote": "symbiote", "valu": "valu", "zelf": "zelf" } @end-include */ var arid = require("arid"); var asea = require("asea"); var asyum = require("asyum"); var called = require("called"); var clazof = require("clazof"); var depher = require("depher"); var diatom = require("diatom"); var een = require("een"); var embedd = require("embedd"); var eqe = require("eqe"); var falzy = require("falzy"); var harden = require("harden"); var heredito = require("heredito"); var idntfy = require("idntfy"); var idntty = require("idntty"); var ferge = require("ferge"); var infray = require("infray"); var kein = require("kein"); var kurse = require("kurse"); var leveld = require("leveld"); var plough = require("plough"); var pyp = require("pyp"); var protype = require("protype"); var pyck = require("pyck"); var raze = require("raze"); var shft = require("shft"); var symbiote = require("symbiote"); var valu = require("valu"); var zelf = require("zelf"); //: @client: var EventList = require("./event-list.support.js"); var listener = require("./listener.support.js"); //: @end-client var EVENT = (0, _symbol2.default)("event"); var HANDLER = (0, _symbol2.default)("handler"); var LIMIT = (0, _symbol2.default)("limit"); var LINK = (0, _symbol2.default)("link"); var TIMEOUT = (0, _symbol2.default)("timeout"); var DEFAULT_TIMEOUT = 1000; var DEFAULT_LIMIT = 10; var edo = function edo(parameter) { /*; @meta-configuration: { "parameter": "..." } @end-meta-configuration */ parameter = raze(arguments); var self = zelf(this); var Event = diatom("Event"); Event.prototype.initialize = function initialize() { this.delay(DEFAULT_TIMEOUT); this.restrict(DEFAULT_LIMIT); harden(HANDLER, {}, this); harden(LINK, [], this); kurse(this); var identity = idntty(this).toString(); this.on(identity + ":on-listener-added", function handle() {}); this.on(identity + ":once-listener-added", function handle() {}); return this; }; Event.prototype.on = function on(event, handler, option) {var _this = this; /*; @meta-configuration: { "event:required": [ "string", "..." ], "handler:required": [ "function", "..." ], "option": "object" } @end-meta-configuration */ var parameter = leveld(arguments); event = pyck(parameter, STRING); handler = pyck(parameter, FUNCTION); //: @note: Preserve the original handler. This will be used to emit notification. var handlerList = handler; option = depher(parameter, OBJECT, {}); /*; @note: Checks if the event-handler is already registered. Note that this will check the real handler function not the Handler instance. @end-note */ if (this.registered(event, handler)) { return this; } if (this.haveEvent(event)) { event.forEach(function (event) { if (_this.hasEvent(event)) { _this.holder(event).push(handler); } else { _this.on.apply(_this, event.concat(handler).concat(option)); } }); } else { var holder = listener().register(this).context(self); handler = handler.reduce(function (listener, handler) {return listener.push(handler);}, holder); if (asea.server) { var emitter = ferge(this, "EventEmitter"); event.forEach(function (event) {return emitter.on(event, handler);}); } else if (asea.client) { event.forEach(function (event) {return _this.handle(event, handler);}); } else { throw new Error("cannot determine platform, platform not supported"); } } /*; @note: This is our own notification that the event has been added. Note that we will not notify if the event is an identity event or "disableOnListenerNotification" is enabled. @end-note */ if (!embedd(this, event) && !option.disableOnListenerNotification) { this.emit(idntty(this).toString() + ":on-listener-added", event, handlerList); } return this; }; Event.prototype.once = function once(event, handler, option) {var _this2 = this; /*; @meta-configuration: { "event:required": [ "string", "..." ], "handler:required": "function", "option": "object" } @end-meta-configuration */ var parameter = leveld(arguments); event = pyck(parameter, STRING); handler = pyck(parameter, FUNCTION); //: @note: Preserve the original handler. This will be used to emit notification. var handlerList = handler; option = depher(parameter, OBJECT, {}); /*; @note: Checks if the event-handler is already registered. Note that this will check the real handler function not the Handler instance. @end-note */ if (this.registered(event, handler)) { return this; } handler = handler.map(function (handler) {return called.bind(self)(handler);}); if (this.haveEvent(event)) { event.forEach(function (event) { if (_this2.hasEvent(event)) { _this2.holder(event).push(handler); } else { _this2.once.apply(_this2, event.concat(handler).concat(option)); } }); } else { var holder = listener().register(this).context(self); handler = handler.reduce(function (listener, handler) {return listener.push(handler);}, holder); if (asea.server) { var emitter = ferge(this, "EventEmitter"); event.forEach(function (event) {return emitter.once(event, handler);}); } else if (asea.client) { event.forEach(function (event) {return _this2.handle(event, handler, true);}); } else { throw new Error("cannot determine platform, platform not supported"); } } /*; @note: This is our own notification that the event has been added once. Note that we will not notify if the event is an identity event or "disableOnceListenerNotification" is enabled. @end-note */ if (!embedd(this, event) && !option.disableOnceListenerNotification) { this.emit(idntty(this).toString() + ":once-listener-added", event, handlerList); } return this; }; Event.prototype.emit = function emit(event, parameter) {var _this3 = this; /*; @meta-configuration: { "event:required": "string", "parameter": "..." } @end-meta-configuration */ parameter = shft(arguments); if (this[LIMIT] <= 0) { this.restrict(DEFAULT_LIMIT); return this; } if (this.hasEvent(event)) { this.restrict(DEFAULT_LIMIT); if (asea.server) { var emitter = ferge(this, "EventEmitter"); emitter.emit.apply(this, [event].concat(parameter)); } else if (asea.client) { this.notify.apply(this, [event].concat(parameter)); } else { throw new Error("cannot determine platform, platform not supported"); } } else { var timeout = setTimeout(function () { _this3.emit.apply(_this3, [event].concat(parameter)); clearTimeout(timeout); }, this[TIMEOUT]); this[LIMIT]--; } return this; }; Event.prototype.invoke = function invoke(event, parameter, limit) { /*; @meta-configuration: { "event:required": "string", "parameter": "...", "limit": "EventList" } @end-meta-configuration */ parameter = shft(arguments); limit = asyum(pyp(parameter, EventList), function hasEvent() { return false; }); if (limit.hasEvent(this)) { return this; } asyum(pyp(parameter, EventList), function push(event) { parameter.push(EventList(event)); }).push(this); if (this.hasEvent(event)) { if (asea.server) { var emitter = ferge(this, "EventEmitter"); emitter.emit.apply(this, [event].concat(parameter)); } else if (asea.client) { this.notify.apply(this, [event].concat(parameter)); } else { throw new Error("cannot determine platform, platform not supported"); } } return this; }; Event.prototype.delay = function delay(timeout) { /*; @meta-configuration: { "timeout:required": "number" } @end-meta-configuration */ if (falzy(timeout) || !protype(timeout, NUMBER)) { throw new Error("invalid timeout"); } this[TIMEOUT] = timeout; return this; }; Event.prototype.restrict = function restrict(limit) { /*; @meta-configuration: { "limit:required": "number" } @end-meta-configuration */ if (falzy(limit) || !protype(limit, NUMBER)) { throw new Error("invalid limit"); } this[LIMIT] = limit; return this; }; Event.prototype.broadcast = function broadcast(event, parameter) {var _this4 = this; /*; @meta-configuration: { "event:required": "[string]", "parameter": "..." } @end-meta-configuration */ event = plough([event]); parameter = shft(arguments); event.forEach(function (event) {return _this4.emit.apply(_this4, [event].concat(parameter));}); return this; }; Event.prototype.count = function count(event) { if (asea.server) { return this.listenerCount(event); } else if (asea.client) { if (kein(event, this[HANDLER])) { return this[HANDLER][event].count(); } return 0; } else { throw new Error("cannot determine platform, platform not supported"); } }; Event.prototype.flush = function flush() {var _this5 = this; if (asea.server) { this.list().forEach(function (event) {return asyum(_this5.holder(event), function flush() {}).flush();}); this.removeAllListeners(); } else if (asea.client) { valu(this[HANDLER]).forEach(function (handler) {return handler.flush();}); (0, _keys2.default)(this[HANDLER]).forEach(function (event) {return delete _this5[HANDLER][event];}); } else { throw new Error("cannot determine platform, platform not supported"); } while (this[LINK].length) {this[LINK].pop().flush();} return this; }; /*; @method-documentation: Bi-directional forward flow merging of event handlers. @end-method-documentation */ Event.prototype.merge = function merge(event) { /*; @meta-configuration: { "event:required": "Event" } @end-meta-configuration */ if (falzy(event) || !clazof(event, "Event")) { throw new Error("cannot merge event"); } this.transfer(event); event.transfer(this); return this; }; /*; @method-documentation: Transfer event handlers. @end-method-documentation */ Event.prototype.transfer = function transfer(event) {var _this6 = this; /*; @meta-configuration: { "event:required": "Event" } @end-meta-configuration */ if (falzy(event) || !clazof(event, "Event")) { throw new Error("cannot transfer from event"); } var self = this; infray(event.list(), this.list()). forEach(function (name) { /*; @note: Identity events are not copied. @end-note */ if (embedd(_this6, name) || embedd(event, name)) { return; } /*; @note: If event is already link, do not link it anymore. @end-note */ if (_this6.hasLink(name, event)) { return; } var invoke = function invoke() { var parameter = raze(arguments); asyum(pyp(parameter, EventList), function push(event) { parameter.push(EventList(event)); }).push(self); event.invoke.apply(event, [name].concat(parameter)); }; _this6.on(name, invoke); asyum(invoke, function linkedTo() {}).linkedTo(event); }); var identity = idntty(this).toString(); this.on(identity + ":on-listener-added", function onListenerAdded(name) { /*; @note: Name of events are in array. @end-note */ if (event.haveLink(name, self)) { return; } var invoke = function invoke() { var parameter = raze(arguments); asyum(pyp(parameter, EventList), function push(event) { parameter.push(EventList(event)); }).push(event); name.forEach(function (name) {return self.invoke.apply(self, [name].concat(parameter));}); }; event.on(name, invoke); asyum(invoke, function linkedTo() {}).linkedTo(self); }); this.on(identity + ":once-listener-added", function onceListenerAdded(name) { /*; @note: Name of events are in array. @end-note */ if (event.haveLink(name, self)) { return; } var invoke = function invoke() { var parameter = raze(arguments); asyum(pyp(parameter, EventList), function push(event) { parameter.push(EventList(event)); }).push(event); name.forEach(function (name) {return self.invoke.apply(self, [name].concat(parameter));}); }; event.once(name, invoke); asyum(invoke, function linkedTo() {}).linkedTo(self); }); this.link(event); return this; }; Event.prototype.link = function link(event) { /*; @meta-configuration: { "event:required": "Event" } @end-meta-configuration */ if (falzy(event) || !clazof(event, "Event")) { throw new Error("cannot link event"); } if (!een(this[LINK], event, function (link, event) {return idntfy(link, event);})) { this[LINK].push(event); } return this; }; /*; @method-documentation: List registered event names. @end-method-documentation */ Event.prototype.list = function list() { if (asea.server) { return this.eventNames(); } else if (asea.client) { return (0, _keys2.default)(this[HANDLER]); } else { throw new Error("cannot determine platform, platform not supported"); } }; /*; @method-documentation: List the handlers of the event. @end-method-documentation */ Event.prototype.handler = function handler(event) { /*; @meta-configuration: { "event:required": "string" } @end-meta-configuration */ if (falzy(event) || !protype(event, STRING)) { return []; } if (asea.server) { return this.listeners(event).reduce(function (list, handler) { if (clazof(handler, "Handler")) { return list.concat(handler.list()); } else { list.push(handler); return list; } }, []); } else if (asea.client) { if (!kein(event, this[HANDLER])) { return []; } return this[HANDLER][event].list(); } else { throw new Error("cannot determine platform, platform not supported"); } }; /*; @method-documentation: Return the Handler that holds the handler procedures. @end-method-documentation */ Event.prototype.holder = function holder(event) {var _this7 = this; /*; @meta-configuration: { "event:required": [ "string", "[string], "... ] } @end-meta-configuration */ event = pyck(plough(arguments), STRING); if (asea.server) { return event.reduce(function (holder, event) { return _this7.listeners(event).reduce(function (holder, handler) { if (clazof(handler, "Handler")) { return handler;