/** @namespace */ (function(module, ns) { /** * Constructor * * @param {Object} list of events to add onto responder. */ function Responder(events) { this._$events = Object.create(null); if (typeof(events) !== 'undefined') { this.addEventListener(events); } }; /** * Stringifies request to websocket * * * @param {String} command command name. * @param {Object} data object to be sent over the wire. * @return {String} json object. */ Responder.stringify = function stringify(command, data) { return JSON.stringify([command, data]); }; /** * Parses request from WebSocket. * * @param {String} json json string to translate. * @return {Object} ex: { event: 'test', data: {} }. */ Responder.parse = function parse(json) { var data; try { data = (json.forEach) ? json : JSON.parse(json); } catch (e) { throw new Error("Could not parse json: '" + json + '"'); } return {event: data[0], data: data[1]}; }; Responder.prototype = { parse: Responder.parse, stringify: Responder.stringify, /** * Events on this instance * * @type Object */ _$events: null, /** * Recieves json string event and dispatches an event. * * @param {String|Object} json data object to respond to. * @param {String} json.event event to emit. * @param {Object} json.data data to emit with event. * @param {Object} [params] option number of params to pass to emit. * @return {Object} result of WebSocketCommon.parse. */ respond: function respond(json) { var event = Responder.parse(json), args = Array.prototype.slice.call(arguments).slice(1); args.unshift(event.data); args.unshift(event.event); this.emit.apply(this, args); return event; }, //TODO: Extract event emitter logic /** * Adds an event listener to this object. * * * @param {String} type event name. * @param {Function} callback event callback. */ addEventListener: function addEventListener(type, callback) { var event; if (typeof(callback) === 'undefined' && typeof(type) === 'object') { for (event in type) { if (Object.hasOwnProperty.call(type, event)) { this.addEventListener(event, type[event]); } } return this; } if (!(type in this._$events)) { this._$events[type] = []; } this._$events[type].push(callback); return this; }, /** * Adds an event listener which will * only fire once and then remove itself. * * * @param {String} type event name. * @param {Function} callback fired when event is emitted. */ once: function once(type, callback) { var self = this; function onceCb() { self.removeEventListener(type, onceCb); callback.apply(this, arguments); } this.addEventListener(type, onceCb); return this; }, /** * Emits an event. * * Accepts any number of additional arguments to pass unto * event listener. * * @param {String} eventName name of the event to emit. * @param {Object} [arguments] additional arguments to pass. */ emit: function emit() { var args = Array.prototype.slice.call(arguments), event = args.shift(), eventList, self = this; if (event in this._$events) { eventList = this._$events[event]; eventList.forEach(function(callback) { callback.apply(self, args); }); } return this; }, /** * Removes all event listeners for a given event type * * * @param {String} event event type to remove. */ removeAllEventListeners: function removeAllEventListeners(name) { if (name in this._$events) { //reuse array this._$events[name].length = 0; } return this; }, /** * Removes a single event listener from a given event type * and callback function. * * * @param {String} eventName event name. * @param {Function} callback same instance of event handler. */ removeEventListener: function removeEventListener(name, callback) { var i, length, events; if (!(name in this._$events)) { return false; } events = this._$events[name]; for (i = 0, length = events.length; i < length; i++) { if (events[i] && events[i] === callback) { events.splice(i, 1); return true; } } return false; } }; Responder.prototype.on = Responder.prototype.addEventListener; module.exports = Responder; }.apply( this, (this.Caldav) ? [Caldav('responder'), Caldav] : [module, require('./caldav')] ));