summaryrefslogtreecommitdiff
path: root/www
diff options
context:
space:
mode:
authorArjun Roychowdhury <pliablepixels@gmail.com>2015-10-06 16:57:33 -0400
committerArjun Roychowdhury <pliablepixels@gmail.com>2015-10-06 16:57:33 -0400
commitdd8d072fdae253c611e8ca3ff9ed8d92f0d4483a (patch)
tree696d990d460f00dd8969a226138e8f505207602c /www
parentb4e1f72cfc6f38046bb3afce3eb12664251c1c94 (diff)
ng-websockets with patch for reconnect exponential issue
Diffstat (limited to 'www')
-rw-r--r--www/external/ng-websocket.js371
1 files changed, 371 insertions, 0 deletions
diff --git a/www/external/ng-websocket.js b/www/external/ng-websocket.js
new file mode 100644
index 00000000..8354eb2f
--- /dev/null
+++ b/www/external/ng-websocket.js
@@ -0,0 +1,371 @@
+'use strict';
+
+(function () {
+ /**
+ * @ngdoc provider
+ * @name $websocketProvider
+ * @module ngWebsocket
+ * @description
+ * HTML5 WebSocket provider for AngularJS
+ */
+ function $websocketProvider () {
+ var wsp = this;
+
+ wsp.$$config = {
+ lazy: false,
+ reconnect: true,
+ reconnectInterval: 2000,
+ mock: false,
+ enqueue: false,
+ protocols: null
+ };
+
+ wsp.$setup = function (cfg) {
+ cfg = cfg || {};
+ wsp.$$config = angular.extend({}, wsp.$$config, cfg);
+
+ return wsp;
+ };
+
+ wsp.$get = ['$http', function ($http) {
+ return new $websocketService(wsp.$$config, $http);
+ }];
+ }
+
+ /**
+ * @ngdoc service
+ * @name $websocketService
+ * @module ngWebsocketService
+ * @description
+ * HTML5 Websocket service for AngularJS
+ */
+ function $websocketService (cfg, $http) {
+ var wss = this;
+
+ wss.$$websocketList = {};
+ wss.$$config = cfg || {};
+
+ wss.$get = function (url) {
+ return wss.$$websocketList[url];
+ };
+
+ wss.$new = function (cfg) {
+ cfg = cfg || {};
+
+ // Url or url + protocols initialization
+ if (typeof cfg === 'string') {
+ cfg = {url: cfg};
+
+ // url + protocols
+ if (arguments.length > 1) {
+ if (typeof arguments[1] === 'string' && arguments[1].length > 0) cfg.protocols = [arguments[1]];
+ else if (typeof arguments[1] === 'object' && arguments[1].length > 0) cfg.protocols = arguments[1];
+ }
+ }
+
+ // If the websocket already exists, return that instance
+ var ws = wss.$get(cfg.url);
+ if (typeof ws === 'undefined') {
+ var wsCfg = angular.extend({}, wss.$$config, cfg);
+
+ ws = new $websocket(wsCfg, $http);
+ wss.$$websocketList[wsCfg.url] = ws;
+ }
+
+ return ws;
+ };
+ }
+
+ /**
+ * @ngdoc class
+ * @name $websocket
+ * @module ngWebsocket
+ * @description
+ * HTML5 Websocket wrapper class for AngularJS
+ */
+ function $websocket (cfg, $http) {
+ var me = this;
+
+ if (typeof cfg === 'undefined' || (typeof cfg === 'object' && typeof cfg.url === 'undefined')) throw new Error('An url must be specified for WebSocket');
+
+ me.$$eventMap = {};
+ me.$$ws = undefined;
+ me.$$reconnectTask = undefined;
+ me.$$reconnectCopy = true;
+ me.$$queue = [];
+ me.$$config = {
+ url: undefined,
+ lazy: false,
+ reconnect: true,
+ reconnectInterval: 2000,
+ enqueue: false,
+ mock: false,
+ protocols: null
+ };
+
+ me.$$fireEvent = function () {
+ var args = [];
+
+ Array.prototype.push.apply(args, arguments);
+
+ var event = args.shift(),
+ handlers = me.$$eventMap[event];
+
+ if (typeof handlers !== 'undefined') {
+ for (var i = 0; i < handlers.length; i++) {
+ if (typeof handlers[i] === 'function') handlers[i].apply(me, args);
+ }
+ }
+ };
+
+ me.$$init = function (cfg) {
+ me.$$ws = cfg.mock ? new $$mockWebsocket(cfg.mock, $http) : new WebSocket(cfg.url, cfg.protocols);
+
+ me.$$ws.onmessage = function (message) {
+ try {
+ var decoded = JSON.parse(message.data);
+ me.$$fireEvent(decoded.event, decoded.data);
+ me.$$fireEvent('$message', decoded);
+ }
+ catch (err) {
+ me.$$fireEvent('$message', message.data);
+ }
+ };
+
+ me.$$ws.onerror = function (error) {
+ me.$$fireEvent('$error', error);
+ };
+
+ me.$$ws.onopen = function () {
+ // Clear the reconnect task if exists
+ if (me.$$reconnectTask) {
+ clearInterval(me.$$reconnectTask);
+ delete me.$$reconnectTask;
+ }
+
+ // Flush the message queue
+ if (me.$$config.enqueue && me.$$queue.length > 0) {
+ while (me.$$queue.length > 0) {
+ if (me.$ready()) me.$$send(me.$$queue.shift());
+ else break;
+ }
+ }
+
+ me.$$fireEvent('$open');
+ };
+
+ me.$$ws.onclose = function () {
+ // Activate the reconnect task
+ // PP https://github.com/cdupetit/ng-websocket/commit/bec0d2c56316871758fcd0e33cb55904efb877f1
+ if (me.$$config.reconnect && !me.$$reconnectTask) {
+ me.$$reconnectTask = setInterval(function () {
+ if (me.$status() === me.$CLOSED) me.$open();
+ }, me.$$config.reconnectInterval);
+ }
+
+ me.$$fireEvent('$close');
+ };
+
+ return me;
+ };
+
+ me.$CONNECTING = 0;
+ me.$OPEN = 1;
+ me.$CLOSING = 2;
+ me.$CLOSED = 3;
+
+ // TODO: it doesn't refresh the view (maybe $apply on something?)
+ /*me.$bind = function (event, scope, model) {
+ me.$on(event, function (message) {
+ model = message;
+ scope.$apply();
+ });
+ };*/
+
+ me.$on = function () {
+ var handlers = [];
+
+ Array.prototype.push.apply(handlers, arguments);
+
+ var event = handlers.shift();
+ if (typeof event !== 'string' || handlers.length === 0) throw new Error('$on accept two parameters at least: a String and a Function or an array of Functions');
+
+ me.$$eventMap[event] = me.$$eventMap[event] || [];
+ for (var i = 0; i < handlers.length; i++) {
+ me.$$eventMap[event].push(handlers[i]);
+ }
+
+ return me;
+ };
+
+ me.$un = function (event) {
+ if (typeof event !== 'string') throw new Error('$un needs a String representing an event.');
+
+ if (typeof me.$$eventMap[event] !== 'undefined') delete me.$$eventMap[event];
+
+ return me;
+ };
+
+ me.$$send = function (message) {
+ if (me.$ready()) me.$$ws.send(JSON.stringify(message));
+ else if (me.$$config.enqueue) me.$$queue.push(message);
+ };
+
+ me.$emit = function (event, data) {
+ if (typeof event !== 'string') throw new Error('$emit needs two parameter: a String and a Object or a String');
+
+ var message = {
+ event: event,
+ data: data
+ };
+
+ me.$$send(message);
+
+ return me;
+ };
+
+ me.$open = function () {
+ me.$$config.reconnect = me.$$reconnectCopy;
+
+ if (me.$status() !== me.$OPEN) me.$$init(me.$$config);
+ return me;
+ };
+
+ me.$close = function () {
+ if (me.$status() !== me.$CLOSED) me.$$ws.close();
+
+ if (me.$$reconnectTask) {
+ clearInterval(me.$$reconnectTask);
+ delete me.$$reconnectTask;
+ }
+
+ me.$$config.reconnect = false;
+
+ return me;
+ };
+
+ me.$status = function () {
+ if (typeof me.$$ws === 'undefined') return me.$CLOSED;
+ else return me.$$ws.readyState;
+ };
+
+ me.$ready = function () {
+ return me.$status() === me.$OPEN;
+ };
+
+ me.$mockup = function () {
+ return me.$$config.mock;
+ };
+
+ // setup
+ me.$$config = angular.extend({}, me.$$config, cfg);
+ me.$$reconnectCopy = me.$$config.reconnect;
+
+ if (!me.$$config.lazy) me.$$init(me.$$config);
+
+ return me;
+ }
+
+ function $$mockWebsocket (cfg, $http) {
+ cfg = cfg || {};
+
+ var me = this,
+ openTimeout = cfg.openTimeout || 500,
+ closeTimeout = cfg.closeTimeout || 1000,
+ messageInterval = cfg.messageInterval || 2000,
+ fixtures = cfg.fixtures || {},
+ messageQueue = [];
+
+ me.CONNECTING = 0;
+ me.OPEN = 1;
+ me.CLOSING = 2;
+ me.CLOSED = 3;
+
+ me.readyState = me.CONNECTING;
+
+ me.send = function (message) {
+ if (me.readyState === me.OPEN) {
+ messageQueue.push(message);
+ return me;
+ }
+ else throw new Error('WebSocket is already in CLOSING or CLOSED state.');
+ };
+
+ me.close = function () {
+ if (me.readyState === me.OPEN) {
+ me.readyState = me.CLOSING;
+
+ setTimeout(function () {
+ me.readyState = me.CLOSED;
+
+ me.onclose();
+ }, closeTimeout);
+ }
+
+ return me;
+ };
+
+ me.onmessage = function () {};
+ me.onerror = function () {};
+ me.onopen = function () {};
+ me.onclose = function () {};
+
+ setInterval(function () {
+ if (messageQueue.length > 0) {
+ var message = messageQueue.shift(),
+ msgObj = JSON.parse(message);
+
+ switch (msgObj.event) {
+ case '$close':
+ me.close();
+ break;
+ default:
+ // Check for a custom response
+ if (typeof fixtures[msgObj.event] !== 'undefined') {
+ msgObj.data = fixtures[msgObj.event].data || msgObj.data;
+ msgObj.event = fixtures[msgObj.event].event || msgObj.event;
+ }
+
+ message = JSON.stringify(msgObj);
+
+ me.onmessage({
+ data: message
+ });
+ }
+ }
+ }, messageInterval);
+
+ var start = function (fixs) {
+ fixs = fixs || {};
+ fixs = fixs instanceof Error ? {} : fixs;
+
+ fixtures = fixs;
+
+ setTimeout(function () {
+ me.readyState = me.OPEN;
+ me.onopen();
+ }, openTimeout);
+ };
+
+ // Get fixtures from a server or a file if it's a string
+ if (typeof fixtures === 'string') {
+ $http.get(fixtures)
+ .success(start)
+ .error(start);
+ }
+ else start(fixtures);
+
+ return me;
+ }
+
+ /**
+ * @ngdoc module
+ * @name $websocket
+ * @module ngWebsocket
+ * @description
+ * HTML5 WebSocket module for AngularJS
+ */
+ angular
+ .module('ngWebsocket', [])
+ .provider('$websocket', $websocketProvider);
+})();