| /* |
| * Copyright (c) 2013 DataTorrent, Inc. ALL Rights Reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /*global settings, console, angular, jQuery, _*/ |
| (function () { |
| 'use strict'; |
| |
| angular.module('socket', []) |
| .factory('visibly', function ($window) { |
| return $window.visibly; |
| }) |
| .provider('socket', function () { |
| |
| var webSocketURL; |
| var webSocketObject; // for testing only |
| |
| return { |
| $get: function ($q, $rootScope, $timeout, visibly) { |
| if (!webSocketURL && !webSocketObject) { |
| throw 'WebSocket URL is not defined'; |
| } |
| |
| var socket = !webSocketObject ? new WebSocket(webSocketURL) : webSocketObject; |
| |
| var deferred = $q.defer(); |
| |
| socket.onopen = function () { |
| deferred.resolve(); |
| $rootScope.$apply(); |
| |
| jQuery.pnotify({ |
| title: 'WebSocket', |
| text: 'WebSocket connection established.', |
| type: 'success', |
| delay: 2000, |
| icon: false, |
| history: false |
| }); |
| }; |
| |
| var webSocketError = false; |
| |
| socket.onclose = function () { |
| if (!webSocketError) { |
| jQuery.pnotify({ |
| title: 'WebSocket Closed', |
| text: 'WebSocket connection has been closed. Try refreshing the page.', |
| type: 'error', |
| icon: false, |
| hide: false, |
| history: false |
| }); |
| } |
| }; |
| |
| //TODO |
| socket.onerror = function () { |
| webSocketError = true; |
| jQuery.pnotify({ |
| title: 'WebSocket Error', |
| text: 'WebSocket error. Try refreshing the page.', |
| type: 'error', |
| icon: false, |
| hide: false, |
| history: false |
| }); |
| }; |
| |
| var topicMap = {}; // topic -> [callbacks] mapping |
| |
| var stopUpdates = false; |
| |
| socket.onmessage = function (event) { |
| if (stopUpdates) { // stop updates if page is inactive |
| return; |
| } |
| |
| var message = JSON.parse(event.data); |
| |
| var topic = message.topic; |
| |
| if (topicMap.hasOwnProperty(topic)) { |
| topicMap[topic].fire(message); |
| } |
| }; |
| |
| var timeoutPromise; |
| |
| visibly.onHidden(function () { |
| timeoutPromise = $timeout(function () { |
| stopUpdates = true; |
| timeoutPromise = null; |
| }, 60000); |
| }); |
| |
| visibly.onVisible(function () { |
| /* |
| if (stopUpdates && !webSocketError) { |
| jQuery.pnotify({ |
| title: 'Warning', |
| text: 'Page has not been visible for more than 60 seconds. WebSocket real-time updates have been suspended to conserve system resources. ' + |
| 'Refreshing the page is recommended.', |
| type: 'warning', |
| icon: false, |
| hide: false, |
| history: false |
| }); |
| } |
| */ |
| |
| stopUpdates = false; |
| |
| if (timeoutPromise) { |
| $timeout.cancel(timeoutPromise); |
| } |
| }); |
| |
| return { |
| send: function (message) { |
| var msg = JSON.stringify(message); |
| |
| deferred.promise.then(function () { |
| console.log('send ' + msg); |
| socket.send(msg); |
| }); |
| }, |
| |
| publish: function(topic, data) { |
| var message = { "type": "publish", "topic": topic, "data": data }; |
| this.send(message); |
| }, |
| |
| subscribe: function (topic, callback, $scope) { |
| var callbacks = topicMap[topic]; |
| |
| if (!callbacks) { |
| var message = { type: 'subscribe', topic: topic }; // subscribe message |
| this.send(message); |
| |
| callbacks = jQuery.Callbacks(); |
| topicMap[topic] = callbacks; |
| } |
| |
| callbacks.add(callback); |
| |
| if ($scope) { |
| $scope.$on('$destroy', function () { |
| this.unsubscribe(topic, callback); |
| }.bind(this)); |
| } |
| }, |
| |
| unsubscribe: function (topic, callback) { |
| if (topicMap.hasOwnProperty(topic)) { |
| var callbacks = topicMap[topic]; |
| callbacks.remove(callback); //TODO remove topic from topicMap if callbacks is empty |
| } |
| } |
| }; |
| }, |
| |
| setWebSocketURL: function (wsURL) { |
| webSocketURL = wsURL; |
| }, |
| |
| setWebSocketObject: function (wsObject) { |
| webSocketObject = wsObject; |
| } |
| }; |
| }); |
| |
| })(); |