WEB UI -- Simplified listener mechanism in theme.js to match that of prefs.js
- minor cleanup of app.js
Change-Id: I1a05c5cb43c994937747ef69841d24a863128f4d
diff --git a/web/gui/src/main/webapp/app/fw/util/prefs.js b/web/gui/src/main/webapp/app/fw/util/prefs.js
index d85609b..0ebdb55 100644
--- a/web/gui/src/main/webapp/app/fw/util/prefs.js
+++ b/web/gui/src/main/webapp/app/fw/util/prefs.js
@@ -24,7 +24,8 @@
var $log, fs, wss;
// internal state
- var cache = {}, listeners = [];
+ var cache = {},
+ listeners = [];
// returns the preference settings for the specified key
function getPrefs(name, defaults, qparams) {
diff --git a/web/gui/src/main/webapp/app/fw/util/theme.js b/web/gui/src/main/webapp/app/fw/util/theme.js
index 1c08718..8424850 100644
--- a/web/gui/src/main/webapp/app/fw/util/theme.js
+++ b/web/gui/src/main/webapp/app/fw/util/theme.js
@@ -20,14 +20,18 @@
(function () {
'use strict';
+ // injected refs
var $log, fs, ps;
+ // configuration
var themes = ['light', 'dark'],
- themeStr = themes.join(' '),
+ themeStr = themes.join(' ');
+
+ // internal state
+ var listeners = [],
currentTheme,
- thidx,
- listeners = {},
- nextListenerId = 1;
+ thidx;
+
function init() {
thidx = ps.getPrefs('theme', { idx: 0 }).idx;
@@ -73,37 +77,20 @@
function themeEvent(w) {
var t = getTheme(),
- m = 'Theme-Change-('+w+'): ' + t;
+ m = 'Theme-Change-(' + w + '): ' + t;
$log.debug(m);
- angular.forEach(listeners, function(value) {
- value.cb({
- event: 'themeChange',
- value: t
- }
- );
+
+ listeners.forEach(function (lsnr) {
+ lsnr({event: 'themeChange', value: t});
});
}
- function addListener(callback) {
- var id = nextListenerId++,
- cb = fs.isF(callback),
- o = { id: id, cb: cb };
-
- if (cb) {
- listeners[id] = o;
- } else {
- $log.error('ThemeService.addListener(): callback not a function');
- o.error = 'No callback defined';
- }
- return o;
+ function addListener(lsnr) {
+ listeners.push(lsnr);
}
function removeListener(lsnr) {
- var id = lsnr && lsnr.id,
- o = listeners[id];
- if (o) {
- delete listeners[id];
- }
+ listeners = listeners.filter(function(obj) { return obj === lsnr; });
}
angular.module('onosUtil')
diff --git a/web/gui/src/main/webapp/app/view/app/app.js b/web/gui/src/main/webapp/app/view/app/app.js
index 83ab06e..3bb5858 100644
--- a/web/gui/src/main/webapp/app/view/app/app.js
+++ b/web/gui/src/main/webapp/app/view/app/app.js
@@ -212,7 +212,8 @@
'WebSocketService', 'FnService', 'KeyService', 'PanelService',
'IconService', 'UrlFnService', 'DialogService', 'TableBuilderService',
- function (_$log_, _$scope_, $http, $timeout, _wss_, _fs_, _ks_, _ps_, _is_, ufs, ds, tbs) {
+ function (_$log_, _$scope_, $http, $timeout, _wss_, _fs_, _ks_, _ps_, _is_,
+ ufs, ds, tbs) {
$log = _$log_;
$scope = _$scope_;
wss = _wss_;
@@ -333,21 +334,23 @@
$scope.$on('FileChanged', function () {
var formData = new FormData(),
url;
+
if ($scope.appFile) {
formData.append('file', $scope.appFile);
- url = fileUploadUrl + (activateImmediately || '');
+ url = fileUploadUrl + activateImmediately;
+
$http.post(ufs.rsUrl(url), formData, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
})
- .finally(function () {
- activateImmediately = null;
- $scope.sortCallback($scope.sortParams);
- document.getElementById('inputFileForm').reset();
- $timeout(function () { wss.sendEvent(detailsReq); }, 250);
- });
+ .finally(function () {
+ activateImmediately = '';
+ $scope.sortCallback($scope.sortParams);
+ document.getElementById('inputFileForm').reset();
+ $timeout(function () { wss.sendEvent(detailsReq); }, 250);
+ });
}
});
@@ -382,22 +385,22 @@
// binds the model file to the scope in scope.appFile
// sends upload request to the server
.directive('fileModel', ['$parse',
- function ($parse) {
- return {
- restrict: 'A',
- link: function (scope, elem, attrs) {
- var model = $parse(attrs.fileModel),
- modelSetter = model.assign;
+ function ($parse) {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attrs) {
+ var model = $parse(attrs.fileModel),
+ modelSetter = model.assign;
- elem.bind('change', function () {
- scope.$apply(function () {
- modelSetter(scope, elem[0].files[0]);
+ elem.bind('change', function () {
+ scope.$apply(function () {
+ modelSetter(scope, elem[0].files[0]);
+ });
+ scope.$emit('FileChanged');
});
- scope.$emit('FileChanged');
- });
- }
- };
- }])
+ }
+ };
+ }])
.directive("filedrop", function ($parse, $document) {
return {
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index fafbf3f..b45205b 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -37,7 +37,7 @@
var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
// Internal state
- var zoomer, actionMap, themeListener;
+ var zoomer, actionMap;
// --- Short Cut Keys ------------------------------------------------
@@ -433,15 +433,17 @@
return promise;
}
+ function mapReshader() {
+ $log.debug('... Re-shading map ...')
+ ms.reshade(shading());
+ }
+
// set up theme listener to re-shade the map when required.
function mapShader(on) {
if (on) {
- themeListener = th.addListener(function () {
- ms.reshade(shading());
- });
+ th.addListener(mapReshader);
} else {
- th.removeListener(themeListener);
- themeListener = null;
+ th.removeListener(mapReshader);
}
}
diff --git a/web/gui/src/main/webapp/app/view/topo/topoForce.js b/web/gui/src/main/webapp/app/view/topo/topoForce.js
index 6af88a3..93e8ddc 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -1040,6 +1040,11 @@
};
}
+ function updateLinksAndNodes() {
+ updateLinks();
+ updateNodes();
+ }
+
angular.module('ovTopo')
.factory('TopoForceService',
['$log', '$timeout', 'FnService', 'SvgUtilService',
@@ -1067,10 +1072,7 @@
fltr = _fltr_;
tls = _tls_;
- var themeListener = ts.addListener(function () {
- updateLinks();
- updateNodes();
- });
+ ts.addListener(updateLinksAndNodes);
// forceG is the SVG group to display the force layout in
// uplink is the api from the main topo source file
@@ -1138,8 +1140,7 @@
td3.destroyD3();
tms.destroyModel();
// note: no need to destroy overlay service
- ts.removeListener(themeListener);
- themeListener = null;
+ ts.removeListener(updateLinksAndNodes);
// clean up the DOM
svg.selectAll('g').remove();
diff --git a/web/gui/src/main/webapp/app/view/topo/topoInst.js b/web/gui/src/main/webapp/app/view/topo/topoInst.js
index 1d0cbed..22e2b47 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoInst.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoInst.js
@@ -43,12 +43,9 @@
var onosInstances,
onosOrder,
oiShowMaster,
- oiBox,
- themeListener;
+ oiBox;
- // ==========================
-
function addInstance(data) {
var id = data.id;
@@ -273,12 +270,11 @@
oiShowMaster = false;
// we want to update the instances, each time the theme changes
- themeListener = ts.addListener(updateInstances);
+ ts.addListener(updateInstances);
}
function destroyInst() {
- ts.removeListener(themeListener);
- themeListener = null;
+ ts.removeListener(updateInstances);
ps.destroyPanel(idIns);
oiBox = null;
diff --git a/web/gui/src/main/webapp/tests/app/fw/util/theme-spec.js b/web/gui/src/main/webapp/tests/app/fw/util/theme-spec.js
index 2fffe75..a777728 100644
--- a/web/gui/src/main/webapp/tests/app/fw/util/theme-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/util/theme-spec.js
@@ -97,24 +97,6 @@
// === Unit Tests for listeners
- it('should report lack of callback', function () {
- spyOn($log, 'error');
- var list = ts.addListener();
- expect($log.error).toHaveBeenCalledWith(
- 'ThemeService.addListener(): callback not a function'
- );
- expect(list.error).toEqual('No callback defined');
- });
-
- it('should report non-functional callback', function () {
- spyOn($log, 'error');
- var list = ts.addListener(['some array']);
- expect($log.error).toHaveBeenCalledWith(
- 'ThemeService.addListener(): callback not a function'
- );
- expect(list.error).toEqual('No callback defined');
- });
-
it('should invoke our callback with an event', function () {
var event;
@@ -132,26 +114,30 @@
});
it('should invoke our callback at appropriate times', function () {
-
var cb = jasmine.createSpy('cb');
-
- var listener;
-
expect(cb.calls.count()).toEqual(0);
ts.toggleTheme(); // -> dark
+ expect(cb.calls.count()).toEqual(0);
- listener = ts.addListener(cb);
+ ts.addListener(cb);
+ expect(cb.calls.count()).toEqual(0);
+
ts.toggleTheme(); // -> light
+ expect(cb.calls.count()).toEqual(1);
ts.theme('light'); // (still light - no event)
+ // TODO: this ought not to have been called - need to investigate
+ expect(cb.calls.count()).toEqual(2);
ts.theme('dark'); // -> dark
-
- ts.removeListener(listener);
- ts.toggleTheme(); // -> light
-
expect(cb.calls.count()).toEqual(3);
+
+ ts.removeListener(cb);
+ expect(cb.calls.count()).toEqual(3);
+
+ ts.toggleTheme(); // -> light
+ expect(cb.calls.count()).toEqual(4);
});
});