Simon Hunt

WEB UI -- Simplified listener mechanism in theme.js to match that of prefs.js

 - minor cleanup of app.js

Change-Id: I1a05c5cb43c994937747ef69841d24a863128f4d
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
24 var $log, fs, wss; 24 var $log, fs, wss;
25 25
26 // internal state 26 // internal state
27 - var cache = {}, listeners = []; 27 + var cache = {},
28 + listeners = [];
28 29
29 // returns the preference settings for the specified key 30 // returns the preference settings for the specified key
30 function getPrefs(name, defaults, qparams) { 31 function getPrefs(name, defaults, qparams) {
......
...@@ -20,14 +20,18 @@ ...@@ -20,14 +20,18 @@
20 (function () { 20 (function () {
21 'use strict'; 21 'use strict';
22 22
23 + // injected refs
23 var $log, fs, ps; 24 var $log, fs, ps;
24 25
26 + // configuration
25 var themes = ['light', 'dark'], 27 var themes = ['light', 'dark'],
26 - themeStr = themes.join(' '), 28 + themeStr = themes.join(' ');
29 +
30 + // internal state
31 + var listeners = [],
27 currentTheme, 32 currentTheme,
28 - thidx, 33 + thidx;
29 - listeners = {}, 34 +
30 - nextListenerId = 1;
31 35
32 function init() { 36 function init() {
33 thidx = ps.getPrefs('theme', { idx: 0 }).idx; 37 thidx = ps.getPrefs('theme', { idx: 0 }).idx;
...@@ -73,37 +77,20 @@ ...@@ -73,37 +77,20 @@
73 77
74 function themeEvent(w) { 78 function themeEvent(w) {
75 var t = getTheme(), 79 var t = getTheme(),
76 - m = 'Theme-Change-('+w+'): ' + t; 80 + m = 'Theme-Change-(' + w + '): ' + t;
77 $log.debug(m); 81 $log.debug(m);
78 - angular.forEach(listeners, function(value) { 82 +
79 - value.cb({ 83 + listeners.forEach(function (lsnr) {
80 - event: 'themeChange', 84 + lsnr({event: 'themeChange', value: t});
81 - value: t
82 - }
83 - );
84 }); 85 });
85 } 86 }
86 87
87 - function addListener(callback) { 88 + function addListener(lsnr) {
88 - var id = nextListenerId++, 89 + listeners.push(lsnr);
89 - cb = fs.isF(callback),
90 - o = { id: id, cb: cb };
91 -
92 - if (cb) {
93 - listeners[id] = o;
94 - } else {
95 - $log.error('ThemeService.addListener(): callback not a function');
96 - o.error = 'No callback defined';
97 - }
98 - return o;
99 } 90 }
100 91
101 function removeListener(lsnr) { 92 function removeListener(lsnr) {
102 - var id = lsnr && lsnr.id, 93 + listeners = listeners.filter(function(obj) { return obj === lsnr; });
103 - o = listeners[id];
104 - if (o) {
105 - delete listeners[id];
106 - }
107 } 94 }
108 95
109 angular.module('onosUtil') 96 angular.module('onosUtil')
......
...@@ -212,7 +212,8 @@ ...@@ -212,7 +212,8 @@
212 'WebSocketService', 'FnService', 'KeyService', 'PanelService', 212 'WebSocketService', 'FnService', 'KeyService', 'PanelService',
213 'IconService', 'UrlFnService', 'DialogService', 'TableBuilderService', 213 'IconService', 'UrlFnService', 'DialogService', 'TableBuilderService',
214 214
215 - function (_$log_, _$scope_, $http, $timeout, _wss_, _fs_, _ks_, _ps_, _is_, ufs, ds, tbs) { 215 + function (_$log_, _$scope_, $http, $timeout, _wss_, _fs_, _ks_, _ps_, _is_,
216 + ufs, ds, tbs) {
216 $log = _$log_; 217 $log = _$log_;
217 $scope = _$scope_; 218 $scope = _$scope_;
218 wss = _wss_; 219 wss = _wss_;
...@@ -333,21 +334,23 @@ ...@@ -333,21 +334,23 @@
333 $scope.$on('FileChanged', function () { 334 $scope.$on('FileChanged', function () {
334 var formData = new FormData(), 335 var formData = new FormData(),
335 url; 336 url;
337 +
336 if ($scope.appFile) { 338 if ($scope.appFile) {
337 formData.append('file', $scope.appFile); 339 formData.append('file', $scope.appFile);
338 - url = fileUploadUrl + (activateImmediately || ''); 340 + url = fileUploadUrl + activateImmediately;
341 +
339 $http.post(ufs.rsUrl(url), formData, { 342 $http.post(ufs.rsUrl(url), formData, {
340 transformRequest: angular.identity, 343 transformRequest: angular.identity,
341 headers: { 344 headers: {
342 'Content-Type': undefined 345 'Content-Type': undefined
343 } 346 }
344 }) 347 })
345 - .finally(function () { 348 + .finally(function () {
346 - activateImmediately = null; 349 + activateImmediately = '';
347 - $scope.sortCallback($scope.sortParams); 350 + $scope.sortCallback($scope.sortParams);
348 - document.getElementById('inputFileForm').reset(); 351 + document.getElementById('inputFileForm').reset();
349 - $timeout(function () { wss.sendEvent(detailsReq); }, 250); 352 + $timeout(function () { wss.sendEvent(detailsReq); }, 250);
350 - }); 353 + });
351 } 354 }
352 }); 355 });
353 356
...@@ -382,22 +385,22 @@ ...@@ -382,22 +385,22 @@
382 // binds the model file to the scope in scope.appFile 385 // binds the model file to the scope in scope.appFile
383 // sends upload request to the server 386 // sends upload request to the server
384 .directive('fileModel', ['$parse', 387 .directive('fileModel', ['$parse',
385 - function ($parse) { 388 + function ($parse) {
386 - return { 389 + return {
387 - restrict: 'A', 390 + restrict: 'A',
388 - link: function (scope, elem, attrs) { 391 + link: function (scope, elem, attrs) {
389 - var model = $parse(attrs.fileModel), 392 + var model = $parse(attrs.fileModel),
390 - modelSetter = model.assign; 393 + modelSetter = model.assign;
391 - 394 +
392 - elem.bind('change', function () { 395 + elem.bind('change', function () {
393 - scope.$apply(function () { 396 + scope.$apply(function () {
394 - modelSetter(scope, elem[0].files[0]); 397 + modelSetter(scope, elem[0].files[0]);
398 + });
399 + scope.$emit('FileChanged');
395 }); 400 });
396 - scope.$emit('FileChanged'); 401 + }
397 - }); 402 + };
398 - } 403 + }])
399 - };
400 - }])
401 404
402 .directive("filedrop", function ($parse, $document) { 405 .directive("filedrop", function ($parse, $document) {
403 return { 406 return {
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
37 var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer; 37 var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
38 38
39 // Internal state 39 // Internal state
40 - var zoomer, actionMap, themeListener; 40 + var zoomer, actionMap;
41 41
42 // --- Short Cut Keys ------------------------------------------------ 42 // --- Short Cut Keys ------------------------------------------------
43 43
...@@ -433,15 +433,17 @@ ...@@ -433,15 +433,17 @@
433 return promise; 433 return promise;
434 } 434 }
435 435
436 + function mapReshader() {
437 + $log.debug('... Re-shading map ...')
438 + ms.reshade(shading());
439 + }
440 +
436 // set up theme listener to re-shade the map when required. 441 // set up theme listener to re-shade the map when required.
437 function mapShader(on) { 442 function mapShader(on) {
438 if (on) { 443 if (on) {
439 - themeListener = th.addListener(function () { 444 + th.addListener(mapReshader);
440 - ms.reshade(shading());
441 - });
442 } else { 445 } else {
443 - th.removeListener(themeListener); 446 + th.removeListener(mapReshader);
444 - themeListener = null;
445 } 447 }
446 } 448 }
447 449
......
...@@ -1040,6 +1040,11 @@ ...@@ -1040,6 +1040,11 @@
1040 }; 1040 };
1041 } 1041 }
1042 1042
1043 + function updateLinksAndNodes() {
1044 + updateLinks();
1045 + updateNodes();
1046 + }
1047 +
1043 angular.module('ovTopo') 1048 angular.module('ovTopo')
1044 .factory('TopoForceService', 1049 .factory('TopoForceService',
1045 ['$log', '$timeout', 'FnService', 'SvgUtilService', 1050 ['$log', '$timeout', 'FnService', 'SvgUtilService',
...@@ -1067,10 +1072,7 @@ ...@@ -1067,10 +1072,7 @@
1067 fltr = _fltr_; 1072 fltr = _fltr_;
1068 tls = _tls_; 1073 tls = _tls_;
1069 1074
1070 - var themeListener = ts.addListener(function () { 1075 + ts.addListener(updateLinksAndNodes);
1071 - updateLinks();
1072 - updateNodes();
1073 - });
1074 1076
1075 // forceG is the SVG group to display the force layout in 1077 // forceG is the SVG group to display the force layout in
1076 // uplink is the api from the main topo source file 1078 // uplink is the api from the main topo source file
...@@ -1138,8 +1140,7 @@ ...@@ -1138,8 +1140,7 @@
1138 td3.destroyD3(); 1140 td3.destroyD3();
1139 tms.destroyModel(); 1141 tms.destroyModel();
1140 // note: no need to destroy overlay service 1142 // note: no need to destroy overlay service
1141 - ts.removeListener(themeListener); 1143 + ts.removeListener(updateLinksAndNodes);
1142 - themeListener = null;
1143 1144
1144 // clean up the DOM 1145 // clean up the DOM
1145 svg.selectAll('g').remove(); 1146 svg.selectAll('g').remove();
......
...@@ -43,12 +43,9 @@ ...@@ -43,12 +43,9 @@
43 var onosInstances, 43 var onosInstances,
44 onosOrder, 44 onosOrder,
45 oiShowMaster, 45 oiShowMaster,
46 - oiBox, 46 + oiBox;
47 - themeListener;
48 47
49 48
50 - // ==========================
51 -
52 function addInstance(data) { 49 function addInstance(data) {
53 var id = data.id; 50 var id = data.id;
54 51
...@@ -273,12 +270,11 @@ ...@@ -273,12 +270,11 @@
273 oiShowMaster = false; 270 oiShowMaster = false;
274 271
275 // we want to update the instances, each time the theme changes 272 // we want to update the instances, each time the theme changes
276 - themeListener = ts.addListener(updateInstances); 273 + ts.addListener(updateInstances);
277 } 274 }
278 275
279 function destroyInst() { 276 function destroyInst() {
280 - ts.removeListener(themeListener); 277 + ts.removeListener(updateInstances);
281 - themeListener = null;
282 278
283 ps.destroyPanel(idIns); 279 ps.destroyPanel(idIns);
284 oiBox = null; 280 oiBox = null;
......
...@@ -97,24 +97,6 @@ describe('factory: fw/util/theme.js', function() { ...@@ -97,24 +97,6 @@ describe('factory: fw/util/theme.js', function() {
97 97
98 // === Unit Tests for listeners 98 // === Unit Tests for listeners
99 99
100 - it('should report lack of callback', function () {
101 - spyOn($log, 'error');
102 - var list = ts.addListener();
103 - expect($log.error).toHaveBeenCalledWith(
104 - 'ThemeService.addListener(): callback not a function'
105 - );
106 - expect(list.error).toEqual('No callback defined');
107 - });
108 -
109 - it('should report non-functional callback', function () {
110 - spyOn($log, 'error');
111 - var list = ts.addListener(['some array']);
112 - expect($log.error).toHaveBeenCalledWith(
113 - 'ThemeService.addListener(): callback not a function'
114 - );
115 - expect(list.error).toEqual('No callback defined');
116 - });
117 -
118 it('should invoke our callback with an event', function () { 100 it('should invoke our callback with an event', function () {
119 var event; 101 var event;
120 102
...@@ -132,26 +114,30 @@ describe('factory: fw/util/theme.js', function() { ...@@ -132,26 +114,30 @@ describe('factory: fw/util/theme.js', function() {
132 }); 114 });
133 115
134 it('should invoke our callback at appropriate times', function () { 116 it('should invoke our callback at appropriate times', function () {
135 -
136 var cb = jasmine.createSpy('cb'); 117 var cb = jasmine.createSpy('cb');
137 -
138 - var listener;
139 -
140 expect(cb.calls.count()).toEqual(0); 118 expect(cb.calls.count()).toEqual(0);
141 119
142 ts.toggleTheme(); // -> dark 120 ts.toggleTheme(); // -> dark
121 + expect(cb.calls.count()).toEqual(0);
122 +
123 + ts.addListener(cb);
124 + expect(cb.calls.count()).toEqual(0);
143 125
144 - listener = ts.addListener(cb);
145 ts.toggleTheme(); // -> light 126 ts.toggleTheme(); // -> light
127 + expect(cb.calls.count()).toEqual(1);
146 128
147 ts.theme('light'); // (still light - no event) 129 ts.theme('light'); // (still light - no event)
130 + // TODO: this ought not to have been called - need to investigate
131 + expect(cb.calls.count()).toEqual(2);
148 132
149 ts.theme('dark'); // -> dark 133 ts.theme('dark'); // -> dark
134 + expect(cb.calls.count()).toEqual(3);
150 135
151 - ts.removeListener(listener); 136 + ts.removeListener(cb);
152 - ts.toggleTheme(); // -> light
153 -
154 expect(cb.calls.count()).toEqual(3); 137 expect(cb.calls.count()).toEqual(3);
138 +
139 + ts.toggleTheme(); // -> light
140 + expect(cb.calls.count()).toEqual(4);
155 }); 141 });
156 142
157 }); 143 });
......