UNPKG

chronosjs

Version:

JS Channels Mechanism

1,117 lines (1,034 loc) 42.7 kB
;(function (root, factory) { "use strict"; /* istanbul ignore if */ //<amd> if ("function" === typeof define && define.amd) { // AMD. Register as an anonymous module. define("Chronos.EventsUtil", [], function () { return factory(root, root, true); }); return; } //</amd> /* istanbul ignore next */ if ("object" === typeof exports) { // CommonJS factory(root, exports); } /* istanbul ignore next */ else { // Browser globals root.Chronos = root.Chronos || {}; factory(root, root.Chronos); } }(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, hide) { "use strict"; function getListeners(lstnrs, eventName, appName) { var callBacks = []; if (lstnrs[eventName] && lstnrs[eventName].length) { for (var i = 0; i < lstnrs[eventName].length; i++) { if ((!appName || "*" === lstnrs[eventName][i].appName) ||//generic event // && lstnrs[eventName][i].appName === appName) {//Specific events for a named instance callBacks.push(lstnrs[eventName][i]); } } } if (lstnrs["*"]) { for (var k = 0; k < lstnrs["*"].length; k++) { if ((!appName || "*" === lstnrs["*"][k].appName) ||//generic event // && lstnrs["*"][k].appName === appName) {//Specific events for a named instance callBacks.push(lstnrs["*"][k]); } } } return callBacks; } /* istanbul ignore next */ function log(msg, level, app) { if (root && "function" === typeof root.log) { root.log(msg, level, app); } } /** * var eventObj = { * unbindObj: unbindObj, * attrName: "eventName", * loggerName: "Events", * lstnrs: {} * }; */ function unbind(eventObj) { var cmdName = eventObj.unbindObj[eventObj.attrName]; var unBound = false; var updatedListeners; if (!eventObj.unbindObj) { log("CMD listen id not spec for unbind", "ERROR", eventObj.loggerName); return null; } if (typeof eventObj.unbindObj === "string") {//Data is of type commandId return _unregister(eventObj.lstnrs, eventObj.unbindObj); } else if (!eventObj.unbindObj.func && !eventObj.unbindObj.context && !eventObj.unbindObj.appName) {//No data passed in to help us find unbind return false; } var listeners = eventObj.lstnrs; if (cmdName) { listeners = {}; listeners[cmdName] = eventObj.lstnrs[cmdName]; } for (var key in listeners) { if (listeners.hasOwnProperty(key)) { if (listeners[key] && listeners[key].length) { updatedListeners = _unbind(listeners[key], eventObj.unbindObj.func, eventObj.unbindObj.context, eventObj.unbindObj.appName); if (updatedListeners.length !== listeners[key].length) { eventObj.lstnrs[key] = updatedListeners; unBound = true; } } } } return unBound; } /** * Clones objects and properties (everything except functions) * @param cloneObj - the object we want to clone * @return {Object} */ function cloneEventData(cloneObj) { var resultObj = {}; if (cloneObj.constructor === Object) {//If this is an object for (var key in cloneObj) { //noinspection JSUnfilteredForInLoop if (cloneObj.hasOwnProperty(key) && cloneObj[key] !== null && cloneObj[key] !== undefined) {//Make sure we have some data that's object specific //noinspection JSUnfilteredForInLoop if (typeof cloneObj[key] === "object" && cloneObj[key].constructor !== Array) { //noinspection JSUnfilteredForInLoop resultObj[key] = cloneEventData(cloneObj[key]); } else { //noinspection JSUnfilteredForInLoop if (cloneObj[key].constructor === Array) { //noinspection JSUnfilteredForInLoop resultObj[key] = cloneObj[key].slice(0) || []; } else { //noinspection JSUnfilteredForInLoop if (typeof cloneObj[key] !== "function") { //noinspection JSUnfilteredForInLoop resultObj[key] = cloneObj[key] !== null && cloneObj[key] !== undefined ? cloneObj[key] : ""; } } } } } } else {//Return copy of Array or primitive type in case of no Object if (cloneObj.constructor === Array) { resultObj = cloneObj.slice(0) || []; } else if (typeof cloneObj !== "function") { resultObj = cloneObj; } } return resultObj; } function hasFired(fired, app, evName) { if ((typeof (evName) === "undefined" || evName === "*") && app === "*") { return fired; } var firedEvents = []; for (var n = 0; n < fired.length; n++) { if (fired[n].eventName === evName || evName === "*") { if ((app && app === fired[n].appName) ||//For events specific to a caller (!fired[n].appName || fired[n].appName === "*") || app === "*") { //For all events that don't have a specific appName firedEvents.push(fired[n]); } } } return firedEvents; } /** * Stores events so we can later ask for them, can be set to a limited store by defaults on instantiation * @param data = { * triggerData: triggerData, * eventBufferLimit: eventBufferLimit, * attrName: attrName, * fired: fired, * index: index * } */ function storeEventData(data) { //noinspection JSUnresolvedVariable if (data.eventBufferLimit === 0 || (data.triggerData.data && !!data.triggerData.data.doNotStore)) {//No events should be stored or this event should not be stored data = null; return; } var firedEventData = {eventName: data.triggerData[data.attrName], appName: data.triggerData.appName}; firedEventData.data = data.triggerData.passDataByRef ? data.triggerData.data : cloneEventData(data.triggerData.data); if (data.eventBufferLimit > 0) {//Limiting Array size to what was decided on creation if (data.index >= data.eventBufferLimit) { data.index = 0; } data.fired[data.index] = firedEventData; data.index++; } else {//All events should be stored data.fired.push(firedEventData); } data = null; } function _unregister(lstnrs, eventId) { var unBound = false; if (!eventId) { log("Ev listen id not spec for unregister", "ERROR", "Events"); return null; } for (var eventName in lstnrs) { if (lstnrs.hasOwnProperty(eventName)) { for (var i = 0; i < lstnrs[eventName].length; i++) { if (lstnrs[eventName][i].id == eventId) { lstnrs[eventName].splice(i, 1); log("Ev listen=" + eventId + " and name=" + eventName + " unregister", "DEBUG", "Events"); unBound = true; break; } } } } if (!unBound) { log("Ev listen not found " + eventId + " unregister", "DEBUG", "Events"); } return unBound; } /** * The actual unbinding of the callbacks from the events mechanism * @param listeners - the array of listeners that match this query * @param func - the function we want to unbind * @param context - the context we want to unbind * @param appName - the specific appName we want to unbind (UID) * @return {Array} - the new array of listeners we want to use */ function _unbind(listeners, func, context, appName) { var newListeners = []; if (listeners && listeners.length) { for (var i = 0; i < listeners.length; i++) { try { var sameFunc = (!context && listeners[i].func === func);//If this fits the function and no context was passed var sameContext = (!func && context && listeners[i].context === context);//If this fits the context and no function was passed var sameFuncAndContext = (func && context && listeners[i].func === func && listeners[i].context === context);//if this fits the function and context var hasSameAppName = (appName && appName === listeners[i].appName);//If we're unbinding a specific appName var hasGlobalAppName = (listeners[i].appName === "*");//If we're unbinding a general appName if ((sameFunc || sameContext || sameFuncAndContext)) { if (hasSameAppName || hasGlobalAppName) { continue;//This is a callback to remove } if (sameContext) { continue; } } else if (!func && !context && hasSameAppName) {//This should only happen if nothing but an appName was passed in continue;//This is a callback to remove } newListeners.push(listeners[i]);//This is callbacks we keep } catch (err) { log("Error in unbind e=" + err.message, "ERROR", "Events"); } } } return newListeners; } // attach properties to the exports object to define // the exported module properties. var ret = { getListeners: getListeners, log: log, unbind: unbind, hasFired: hasFired, cloneEventData: cloneEventData, storeEventData: storeEventData }; if (!hide) { exports.EventsUtil = exports.EventsUtil || ret; } return ret; })); ;(function (root, factory) { "use strict"; /* istanbul ignore if */ //<amd> if ("function" === typeof define && define.amd) { // AMD. Register as an anonymous module. define("Chronos.Events", ["Chronos.EventsUtil"], function (EventsUtil) { return factory(root, root, EventsUtil, true); }); return; } //</amd> /* istanbul ignore next */ if ("object" === typeof exports) { // CommonJS factory(root, exports, require("./util/EventsUtil").EventsUtil); } /* istanbul ignore next */ else { /** * @depend ./util/EventsUtil.js */ // Browser globals root.Chronos = root.Chronos || {}; factory(root, root.Chronos, root.Chronos.EventsUtil); } }(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, evUtil, hide) { "use strict"; function Events(defaults) { var appName = "Events", attrName = "eventName", eventId = 0, lstnrs = {}, fired = [], prefix = "evId_", indexer = 0, cloneData, eventBufferLimit, defaultAppName; defaultAppName = defaults && defaults.appName || "*"; cloneData = (defaults && typeof defaults.cloneEventData === "boolean" ? defaults.cloneEventData : false); eventBufferLimit = (defaults && !isNaN(defaults.eventBufferLimit) ? defaults.eventBufferLimit : -1); /** * This registers to an event only once, if it has fired the bind will be removed * @param data * @return {*} */ function once(data) { if (data) { data.triggerOnce = true; return bind(data); } else { return null; } } /** * This function allows registering for events with the following structure: * @param app = { * eventName: string that is the name of the event that will be triggered like 'click' * aSync: boolean flag if this call back is called synchronously when the event fires, or after we queue all the listeners * appName: string that specifies an added identifier for multiple instances of the same event name (click by button1, click by button 2) * func: function - the callback function which the event data will be passed to * context: the context which the event data will be run with * triggerOnce: this is for listening only to the first trigger of this event * } || app = app name * * @param ev = event name * @param fn = callback function * @return {*} */ function bind(app, ev, fn) { var evData = app; if ("string" === typeof app) { evData = { appName: app, eventName: ev, func: fn }; } evData.appName = evData.appName || defaultAppName; if ("*" !== defaultAppName) { if ("string" === typeof app && ("function" === typeof ev || "undefined" === typeof ev)) { evData.eventName = app; } } if (!evData.eventName || !evData.func || ("function" !== typeof evData.func && evData.func.constructor !== Array)) { evUtil.log("Ev listen has invalid params: evName=[" + evData.eventName + "]", "ERROR", "Events"); return null; } if (evData.func.constructor === Array) { var evIds = [], cloneEvent, cloneId; for (var i = 0; i < evData.func.length; i++) { cloneEvent = evUtil.cloneEventData(evData); cloneEvent.func = evData.func[i]; cloneId = bind(cloneEvent); evIds.push(cloneId); } return evIds; } var evId = prefix + (eventId++); var newObj = { id: evId, func: evData.func, context: evData.context || null, aSync: evData.aSync ? true : false, appName: evData.appName, triggerOnce: evData.triggerOnce || false }; lstnrs[evData.eventName] = lstnrs[evData.eventName] || []; lstnrs[evData.eventName].push(newObj); evUtil.log("Ev listen rgstr: evName=[" + evData.eventName + "] aSync=" + newObj.aSync + " appName=" + newObj.name, "DEBUG", "Events"); evData = null; app = null; return evId; } /** * This function allows unbinding according to a permutation of the three parameters * @param unbindObj * eventName - the eventName you want to unbind * func - the pointer to the function you want to unbind * context - the context you want to unbind * appName - the specific appName we want to unbind * OR - eventId * @return {Boolean} */ function unbind(unbindObj) { if ("*" !== defaultAppName) { unbindObj.appName = unbindObj.appName || defaultAppName; } return evUtil.unbind({ unbindObj: unbindObj, attrName: attrName, loggerName: appName, lstnrs: lstnrs }); } /** * firedEventData can pass two request parameters * @param app name * @param evName = event name * @return {Array} */ function hasFired(app, evName) { if ("undefined" === typeof evName) { evName = app; app = defaultAppName; } return evUtil.hasFired(fired, app, evName); } /** * This publishes/triggers an event * @param app = { * eventName - the name of the event triggered * appName - optional specifies the identifier it is bound to * passDataByRef: boolean flag whether this callback will get the reference information of the event or a copy (this allows control of data manipulation) * data - optional event parameters to be passed to the listeners * } || app name * @param evName = event name * @param data = event data * @return {*} */ function trigger(app, evName, data) { var triggerData = app; if ("string" === typeof app) { triggerData = { eventName: evName, appName: app, data: data }; } if ("*" !== defaultAppName) { triggerData.appName = triggerData.appName || defaultAppName; if ("string" === typeof app && ("object" === typeof evName || "undefined" === typeof evName)) { triggerData.eventName = app; } } if (!triggerData || typeof (triggerData.eventName) === "undefined") { evUtil.log("Ev name not spec for publish", "ERROR", "Events"); triggerData = null; return null; } triggerData.passDataByRef = triggerData.passDataByRef || !cloneData; _storeEventData(triggerData); var callBacks = evUtil.getListeners(lstnrs, triggerData.eventName, triggerData.appName); if (callBacks.length > 0) { for (var j = 0; j < callBacks.length; j++) { var eventData = triggerData.passDataByRef ? triggerData.data : evUtil.cloneEventData(triggerData.data);//Clone the event data if there was not an explicit request to passByRef var eventInformation = {appName: triggerData.appName, eventName: triggerData.eventName}; var callBack = callBacks[j]; if (callBack.aSync || (eventData && eventData.aSync)) { setTimeout(_createCallBack(callBack, eventData, eventInformation), 0); } else { _createCallBack(callBack, eventData, eventInformation)(); } } } triggerData = null; return (callBacks.length > 0); } //------------------- Private methods ------------------------------// function _createCallBack(callBack, callBackEventData, triggerInformation) { return function () { try { callBack.func.call(callBack.context, callBackEventData, triggerInformation); callBackEventData = null;//Delete local pointer if (callBack.triggerOnce) { unbind(callBack); } callBack = null; } catch (err) { //noinspection JSUnresolvedVariable evUtil.log("Error executing " + triggerInformation.eventName + " eventId: " + callBack.id + "e=" + err.message, "ERROR", "Events"); } }; } /** * Stores events so we can later ask for them, can be set to a limited store by defaults on instantiation * @param triggerData */ function _storeEventData(triggerData) { evUtil.storeEventData({ triggerData: triggerData, eventBufferLimit: eventBufferLimit, attrName: attrName, fired: fired, index: indexer }); } this.once = once; this.hasFired = hasFired; this.trigger = trigger; this.publish = trigger; this.bind = bind; this.register = bind; this.unbind = unbind; this.unregister = unbind; } // attach properties to the exports object to define // the exported module properties. if (!hide) { exports.Events = exports.Events || Events; } return Events; })); ;(function (root, factory) { "use strict"; /* istanbul ignore if */ //<amd> if ("function" === typeof define && define.amd) { // AMD. Register as an anonymous module. define("Chronos.CommandsUtil", ["Chronos.EventsUtil"], function (EventsUtil) { return factory(root, root, EventsUtil, true); }); return; } //</amd> /* istanbul ignore next */ if ("object" === typeof exports) { // CommonJS factory(root, exports, require("./EventsUtil").EventsUtil); } /* istanbul ignore next */ else { /** * @depend ./EventsUtil.js */ // Browser globals root.Chronos = root.Chronos || {}; factory(root, root.Chronos, root.Chronos.EventsUtil); } }(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, evUtil, hide) { "use strict"; /** * var cmdObj = { * cmd: cmd, * attrName: "cmdName", * loggerName: "Commands", * prefix: "_somePrefix", * id: commandId, * lstnrs: {} * }; */ function bind(cmdObj) { var cmdName = cmdObj.cmd[cmdObj.attrName]; if (!cmdName || !cmdObj.cmd.func || "function" !== typeof cmdObj.cmd.func || !valid(cmdObj.cmd, cmdName)) { evUtil.log("comply: has invalid params: command=[" + cmdName + "]", "ERROR", cmdObj.loggerName); return null; } if (cmdObj.lstnrs[cmdName] && cmdObj.lstnrs[cmdName].length) { evUtil.log("comply: cannot comply because command already exist command=" + cmdName, "ERROR", cmdObj.loggerName); return null; } var cmdId = cmdObj.prefix + (cmdObj.id++); var newObj = { id: cmdId, func: cmdObj.cmd.func, context: cmdObj.cmd.context || null, appName: cmdObj.cmd.appName }; cmdObj.lstnrs[cmdName] = cmdObj.lstnrs[cmdName] || []; cmdObj.lstnrs[cmdName].push(newObj); evUtil.log("Cmd comply: evName=[" + cmdName + "] appName=" + newObj.appName, "DEBUG", cmdObj.loggerName); return cmdId; } function valid(cmd, name) { return !((name && name === "*") || (cmd.appName && cmd.appName === "*")); } // attach properties to the exports object to define // the exported module properties. var ret = { bind: bind, valid: valid }; if (!hide) { exports.CommandsUtil = exports.CommandsUtil || ret; } return ret; })); ;(function (root, factory) { "use strict"; /* istanbul ignore if */ //<amd> if ("function" === typeof define && define.amd) { // AMD. Register as an anonymous module. define("Chronos.Commands", ["Chronos.EventsUtil", "Chronos.CommandsUtil"], function (EventsUtil, CommandsUtil) { return factory(root, root, EventsUtil, CommandsUtil, true); }); return; } //</amd> /* istanbul ignore next */ if ("object" === typeof exports) { // CommonJS factory(root, exports, require("./util/EventsUtil").EventsUtil, require("./util/CommandsUtil").CommandsUtil); } /* istanbul ignore next */ else { /** * @depend ./util/EventsUtil.js * @depend ./util/CommandsUtil.js */ // Browser globals root.Chronos = root.Chronos || {}; factory(root, root.Chronos, root.Chronos.EventsUtil, root.Chronos.CommandsUtil); } }(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, evUtil, cmdUtil, hide) { "use strict"; function Commands(defaults) { var appName = "Commands", attrName = "cmdName", commandId = 0, commands = {}, fired = [], prefix = "cmdId_", indexer = 0, cloneData, eventBufferLimit, defaultAppName; defaultAppName = defaults && defaults.appName || "*"; cloneData = (defaults && typeof defaults.cloneEventData === "boolean" ? defaults.cloneEventData : false); eventBufferLimit = (defaults && !isNaN(defaults.eventBufferLimit) ? defaults.eventBufferLimit : -1); /** * This function allows registering for command with the following structure: * @param cmd = { * cmdName: string that is the name of the event that will be triggered like 'get' * appName: string that specifies an added identifier for multiple instances of the same event name (click by button1, click by button 2) * func: function - the callback function which the event data will be passed to * context: the context which the event data will be run with * } * * @return {String} - command Id. */ function comply(cmd) { if ("*" !== defaultAppName) { cmd.appName = cmd.appName || defaultAppName; } return cmdUtil.bind({ cmd: cmd, attrName: attrName, loggerName: appName, prefix: prefix, id: commandId, lstnrs: commands }); } /** * This function allows unbinding according to a permutation of the three parameters * @param unbindObj * cmdName - the eventName you want to unbind * func - the pointer to the function you want to unbind * context - the context you want to unbind * appName - the specific appName we want to unbind * OR - commandId * @return {Boolean} - has stopped complying. */ function stopComplying(unbindObj) { if ("*" !== defaultAppName) { unbindObj.appName = unbindObj.appName || defaultAppName; } return evUtil.unbind({ unbindObj: unbindObj, attrName: attrName, loggerName: appName, lstnrs: commands }); } /** * firedEventData can pass two request parameters * @param app name * @param cmdName = command name * @return {Array} */ function hasFired(app, cmdName) { if ("undefined" === typeof cmdName) { cmdName = app; app = defaultAppName; } return evUtil.hasFired(fired, app, cmdName); } /** * This triggers a command * @param cmd = { * cmdName - the name of the command triggered * appName - optional specifies the identifier it is bound to * passDataByRef: boolean flag whether this callback will get the reference information of the event or a copy (this allows control of data manipulation) * data - optional event parameters to be passed to the listeners * } * * @param cb - optional callback to notify when finished * @return {*} */ function command(cmd, cb) { if (!cmd || typeof (cmd.cmdName) === "undefined" || !cmdUtil.valid(cmd, cmd.cmdName)) { evUtil.log("CMD name not spec for command", "ERROR", "Commands"); return null; } if ("*" !== defaultAppName) { cmd.appName = cmd.appName || defaultAppName; } cmd.passDataByRef = cmd.passDataByRef || !cloneData; _storeEventData(cmd); if (!commands[cmd.cmdName]) { return false; } var callBacks = evUtil.getListeners(commands, cmd.cmdName, cmd.appName); if (callBacks.length > 0) { for (var j = 0; j < callBacks.length; j++) { var cmdData = cmd.passDataByRef ? cmd.data : evUtil.cloneEventData(cmd.data);//Clone the event data if there was not an explicit request to passByRef var callBack = callBacks[j]; try { if ("function" === typeof cb) { callBack.func.call(callBack.context, cmdData, cb); } else { callBack.func.call(callBack.context, cmdData); } cmdData = null;//Delete local pointer callBack = null; } catch (err) { if ("function" === typeof cb) { try { cb(err); } catch (e) { evUtil.log("Error executing callback on error, " +cmd.cmdName + " commandId: " + callBack.id + "e=" + e.message, "ERROR", "Commands"); } } //noinspection JSUnresolvedVariable evUtil.log("Error executing " + cmd.cmdName + " commandId: " + callBack.id + "e=" + err.message, "ERROR", "Commands"); } } } return (callBacks.length > 0); } //------------------- Private methods ------------------------------// /** * Stores commands so we can later ask for them, can be set to a limited store by defaults on instantiation * @param triggerData */ function _storeEventData(triggerData) { evUtil.storeEventData({ triggerData: triggerData, eventBufferLimit: eventBufferLimit, attrName: attrName, fired: fired, index: indexer }); } this.hasFired = hasFired; this.comply = comply; this.stopComplying = stopComplying; this.command = command; } // attach properties to the exports object to define // the exported module properties. if (!hide) { exports.Commands = exports.Commands || Commands; } return Commands; })); ;(function (root, factory) { "use strict"; /* istanbul ignore if */ //<amd> if ("function" === typeof define && define.amd) { // AMD. Register as an anonymous module. define("Chronos.Reqres", ["Chronos.EventsUtil", "Chronos.CommandsUtil"], function (EventsUtil, CommandsUtil) { return factory(root, root, EventsUtil, CommandsUtil, true); }); return; } //</amd> /* istanbul ignore next */ if ("object" === typeof exports) { // CommonJS factory(root, exports, require("./util/EventsUtil").EventsUtil, require("./util/CommandsUtil").CommandsUtil); } /* istanbul ignore next */ else { /** * @depend ./util/EventsUtil.js * @depend ./util/CommandsUtil.js */ // Browser globals root.Chronos = root.Chronos || {}; factory(root, root.Chronos, root.Chronos.EventsUtil, root.Chronos.CommandsUtil); } }(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, evUtil, cmdUtil, hide) { function ReqRes(defaults) { var appName = "ReqRes", attrName = "reqName", requestId = 0, requests = {}, fired = [], prefix = "reqId_", indexer = 0, cloneData, eventBufferLimit, defaultAppName; defaultAppName = defaults && defaults.appName || "*"; cloneData = (defaults && typeof defaults.cloneEventData === "boolean" ? defaults.cloneEventData : false); eventBufferLimit = (defaults && !isNaN(defaults.eventBufferLimit) ? defaults.eventBufferLimit : -1); /** * This function allows registering for command with the following structure: * @param req = { * reqName: string that is the name of the event that will be triggered like 'get' * appName: string that specifies an added identifier for multiple instances of the same event name (click by button1, click by button 2) * func: function - the callback function which the event data will be passed to * context: the context which the event data will be run with * } * * @return {String} - command Id. */ function reply(req) { if ("*" !== defaultAppName) { req.appName = req.appName || defaultAppName; } return cmdUtil.bind({ cmd: req, attrName: attrName, loggerName: appName, prefix: prefix, id: requestId, lstnrs: requests }); } /** * This function allows unbinding according to a permutation of the three parameters * @param unbindObj * reqName - the eventName you want to unbind * func - the pointer to the function you want to unbind * context - the context you want to unbind * appName - the specific appName we want to unbind * OR - requestId * @return {Boolean} - has stopped complying. */ function stopReplying(unbindObj) { if ("*" !== defaultAppName) { unbindObj.appName = unbindObj.appName || defaultAppName; } return evUtil.unbind({ unbindObj: unbindObj, attrName: attrName, loggerName: appName, lstnrs: requests }); } /** * firedEventData can pass two request parameters * @param app name * @param reqName = command name * @return {Array} */ function hasFired(app, reqName) { if ("undefined" === typeof reqName) { reqName = app; app = defaultAppName; } return evUtil.hasFired(fired, app, reqName); } /** * This triggers a command * @param req = { * reqName - the name of the command triggered * appName - optional specifies the identifier it is bound to * passDataByRef: boolean flag whether this callback will get the reference information of the event or a copy (this allows control of data manipulation) * data - optional event parameters to be passed to the listeners * } * @param cb - optional callback to notify when finished * @return {*} */ function request(req, cb) { var ret; if (!req || typeof (req.reqName) === "undefined" || !cmdUtil.valid(req, req.reqName)) { evUtil.log("request: name not spec for command", "ERROR", "ReqRes"); throw new Error("Invalid request object"); } if ("*" !== defaultAppName) { req.appName = req.appName || defaultAppName; } req.passDataByRef = req.passDataByRef || !cloneData; _storeEventData(req); if (!requests[req.reqName]) { return ret; //return undefined } var callBacks = evUtil.getListeners(requests, req.reqName, req.appName); if (callBacks.length > 0) { for (var j = 0; j < callBacks.length; j++) { var reqData = req.passDataByRef ? req.data : evUtil.cloneEventData(req.data);//Clone the event data if there was not an explicit request to passByRef var requestInformation = {appName: req.appName, reqName: req.reqName}; var callBack = callBacks[j]; try { if ("function" === typeof cb) { ret = callBack.func.call(callBack.context, reqData, cb); } else { ret = callBack.func.call(callBack.context, reqData); } reqData = null;//Delete local pointer callBack = null; } catch (err) { if ("function" === typeof cb) { try { cb(err); } catch (e) { evUtil.log("Error executing callback on error, " + requestInformation.reqName + " requestId: " + callBack.id + "e=" + e.message, "ERROR", "ReqRes"); } } //noinspection JSUnresolvedVariable evUtil.log("Error executing " + requestInformation.reqName + " requestId: " + callBack.id + "e=" + err.message, "ERROR", "ReqRes"); } } } return ret; } //------------------- Private methods ------------------------------// /** * Stores requests so we can later ask for them, can be set to a limited store by defaults on instantiation * @param triggerData */ function _storeEventData(triggerData) { evUtil.storeEventData({ triggerData: triggerData, eventBufferLimit: eventBufferLimit, attrName: attrName, fired: fired, index: indexer }); } this.hasFired = hasFired; this.request = request; this.reply = reply; this.stopReplying = stopReplying; } // attach properties to the exports object to define // the exported module properties. if (!hide) { exports.ReqRes = exports.ReqRes || ReqRes; } return ReqRes; })); // Just a very dumb proxy wrapper to unify // all events mechanisms inside a single // channel proxy wrapper ;(function (root, factory) { "use strict"; /* istanbul ignore if */ //<amd> if ("function" === typeof define && define.amd) { // AMD. Register as an anonymous module. define("Chronos.Channels", ["Chronos.Events", "Chronos.Commands", "Chronos.Reqres"], function (Events, Commands, Reqres) { return factory(root, root, Events, Commands, Reqres, true); }); return; } //</amd> /* istanbul ignore next */ if ("object" === typeof exports) { // CommonJS factory(root, exports, require("./Events").Events, require("./Commands").Commands, require("./Reqres").ReqRes); } /* istanbul ignore next */ else { /** * @depend ./Events.js * @depend ./Commands.js * @depend ./Reqres.js */ // Browser globals root.Chronos = root.Chronos || {}; factory(root, root.Chronos, root.Chronos.Events, root.Chronos.Commands, root.Chronos.ReqRes); } }(typeof ChronosRoot === "undefined" ? this : ChronosRoot, function (root, exports, Events, Commands, ReqRes, hide) { function Channels(options) { options = options || {}; var externalAPIS = []; var events = options.events || new Events(options.config && options.config.events); var commands = options.commands || new Commands(options.config && options.config.commands); var reqres = options.reqres || new ReqRes(options.config && options.config.reqres); this.once = events.once; this.hasFiredEvents = events.hasFired; this.trigger = events.trigger; this.publish = events.publish; this.bind = events.bind; this.register = events.register; this.unbind = events.unbind; this.unregister = events.unregister; this.hasFiredCommands = commands.hasFired; this.comply = commands.comply; this.stopComplying = commands.stopComplying; this.command = commands.command; this.hasFiredReqres = reqres.hasFired; this.request = reqres.request; this.reply = reqres.reply; this.stopReplying = reqres.stopReplying; if (options.externalProxy === true) { this.trigger = _wrapCalls({ func: events.trigger, context: events, triggerType: "trigger" }); this.publish = _wrapCalls({ func: events.publish, context: events, triggerType: "trigger" }); this.registerProxy = registerProxy; } /** * Wraps API calls to trigger other registered functions * @param options * @returns {Function} * @private */ function _wrapCalls(options){ return function(){ var api; options.func.apply(options.context, Array.prototype.slice.call(arguments, 0)); for (var i = 0; i < externalAPIS.length; i++) { api = externalAPIS[i]; if (api[options.triggerType]) { try { api[options.triggerType].apply(api.context,Array.prototype.slice.call(arguments, 0)); } catch (exc) {} } } }; } /** * Registers external proxy for trigger of events * @param external */ function registerProxy(external){ if (typeof external === 'object' && external.trigger) { externalAPIS.push(external); } } } // attach properties to the exports object to define // the exported module properties. if (!hide) { exports.Channels = exports.Channels || Channels; } return Channels; }));