Revert "GUI: Added ESLint to gulp tasks GUI: Linted files Fixed an error in the build script"

This reverts commit 46c5f1087d76d93497a1e8e5593564991ccb6682.

Change-Id: I1464fdd1df075e93f885e3c1fbd02f0cc563fd4f
diff --git a/tools/gui/gulp-tasks/bundles/bundle-js/index.js b/tools/gui/gulp-tasks/bundles/bundle-js/index.js
index 7b05051..212034a 100644
--- a/tools/gui/gulp-tasks/bundles/bundle-js/index.js
+++ b/tools/gui/gulp-tasks/bundles/bundle-js/index.js
@@ -45,13 +45,8 @@
 }
 
 const tasks = function () {
-    // gulp.task('bundle-vendor', () => bundle(vendor, 'vendor.js'));
+    gulp.task('bundle-vendor', () => bundle(vendor, 'vendor.js'));
     gulp.task('bundle-js', () => bundle(bundleFiles, 'onos.js'));
-    gulp.task('watch-js', () => {
-        gulp.watch([GUI_BASE + '**/*.js', `!${GUI_BASE}/dist/**/*`], ['bundle-js']);
-    }).on('change', (event) => {
-        console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
-    });
 };
 
 export default tasks();
\ No newline at end of file
diff --git a/tools/gui/gulp-tasks/dev-server/index.js b/tools/gui/gulp-tasks/dev-server/index.js
deleted file mode 100644
index f0dddf7..0000000
--- a/tools/gui/gulp-tasks/dev-server/index.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import gulp from 'gulp';
-import browserSync from 'browser-sync';
-import fs from 'fs';
-import webserver from 'gulp-webserver';
-import proxy from 'http-proxy-middleware';
-
-console.log(proxy)
-
-let external_apps;
-
-const files = ['../../web/gui/src/main/webapp/**/*.js'];
-const defaultViews = fs.readdirSync('../../web/gui/src/main/webapp/app/view/');
-const viewNameMatcher = new RegExp(/\/onos\/ui\/app\/view\/(.+)\/.+\.(?:js|css|html)/);
-
-if (process.env.ONOS_EXTERNAL_APP_DIRS) {
-    let external_apps = process.env.ONOS_EXTERNAL_APP_DIRS.replace(/\s/,'').split(',');
-
-    external_apps = external_apps.reduce(function (dict, app) {
-        const pieces = app.split(':');
-        const appName = pieces[0];
-        const appPath = pieces[1];
-        dict[appName] = appPath;
-        return dict;
-    }, {});
-}
-
-const checkExternalApp = (url) => {
-    if(external_apps){
-        for(let i = 0; i < Object.keys(external_apps).length; i++){
-            const key = Object.keys(external_apps)[i];
-            if (url.indexOf(key) !== -1) {
-                return key;
-            }
-        }
-    }
-    return false;
-};
-
-const serve = () => {
-    browserSync.init({
-        proxy: {
-            target: 'http://localhost:8181',
-            ws: true,
-            middleware: [
-                proxy(['**/*.js', '!/onos/ui/onos.js'], { target: 'http://localhost:8189' }),
-                proxy('**/*.js.map', {
-                    target: 'http://localhost:8189',
-                    changeOrigin: true,
-                    logLevel: 'debug'
-                })
-            ]
-        }
-    });
-};
-
-const tasks = () => {
-    gulp.task('serve', ['bundle-js', 'proxy-server'], serve);
-    gulp.task('proxy-server', function() {
-        gulp.src('../../web/gui/src/main/webapp')
-            .pipe(webserver({
-                port: 8189,
-                path: '/onos/ui/'
-            }));
-    });
-};
-
-export default tasks();
-
-
diff --git a/tools/gui/gulp-tasks/index.js b/tools/gui/gulp-tasks/index.js
index 2f2019b..3bef084 100644
--- a/tools/gui/gulp-tasks/index.js
+++ b/tools/gui/gulp-tasks/index.js
@@ -1,5 +1,2 @@
 export { default as BundleJS } from './bundles/bundle-js';
-export { default as BundleCSS } from './bundles/bundle-css';
-export { default as Lint } from './lint';
-export { default as DevServer } from './dev-server';
-// export { default as Tests } from './unit-tests';
\ No newline at end of file
+export { default as BundleCSS } from './bundles/bundle-css';
\ No newline at end of file
diff --git a/tools/gui/gulp-tasks/lint/esconfig.json b/tools/gui/gulp-tasks/lint/esconfig.json
deleted file mode 100644
index 7ce1a78..0000000
--- a/tools/gui/gulp-tasks/lint/esconfig.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-    "extends": "google",
-    "globals": {
-        "angular": true,
-        "d3": true,
-        "_": true
-    },
-    "rules": {
-        "prefer-spread": 0,
-        "prefer-rest-params": 0,
-        "no-var": 0,
-        "comma-dangle": 1,
-        "brace-style": 0,
-        "no-void": 0,
-        "require-jsdoc": 0,
-        "padded-blocks": 0,
-        "quote-props": 0,
-        "no-warning-comments": 0,
-        "object-curly-spacing": ["error", "always"],
-        "indent": 0,
-        "one-var": 0,
-        "block-spacing": ["error", "always"],
-        "space-before-function-paren": ["error", { "anonymous": "always", "named": "never" }],
-        "max-len": ["error", 120],
-        "no-invalid-this": 0
-    }
-}
diff --git a/tools/gui/gulp-tasks/lint/index.js b/tools/gui/gulp-tasks/lint/index.js
deleted file mode 100644
index 8dabc49..0000000
--- a/tools/gui/gulp-tasks/lint/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import gulp from 'gulp';
-import eslint from 'gulp-eslint';
-import gulpIf from 'gulp-if';
-import path from 'path';
-
-const files = [
-    '../../web/gui/src/main/webapp/app/**/*.js'
-];
-
-function isFixed(file) {
-    // Has ESLint fixed the file contents?
-    return file.eslint != null && file.eslint.fixed;
-}
-
-const lint = () => {
-    return gulp.src(files)
-        .pipe(eslint({
-            configFile: path.join(__dirname, 'esconfig.json'),
-            useEslintrc: false,
-            // Automatically fix trivial issues
-            fix: true,
-        }))
-        .pipe(eslint.format())
-        .pipe(gulpIf(isFixed,
-            gulp.dest('../../web/gui/src/main/webapp/app')
-        ));
-};
-
-const tasks = () => {
-    gulp.task('lint', () => lint());
-};
-
-export default tasks();
\ No newline at end of file
diff --git a/tools/gui/gulpfile.babel.js b/tools/gui/gulpfile.babel.js
index 59726cc..7c5056d 100644
--- a/tools/gui/gulpfile.babel.js
+++ b/tools/gui/gulpfile.babel.js
@@ -1,7 +1,9 @@
 import gulp from 'gulp';
 import * as Tasks from './gulp-tasks/';
 
-gulp.task('build', ['bundle-css', 'bundle-js']);
+gulp.task('build', ['bundle-css', 'bundle-vendor', 'bundle-js']);
 gulp.task('tests', ['test']);
 
-gulp.task('default', ['bundle-js', 'serve', 'watch-js']);
\ No newline at end of file
+gulp.task('default', function() {
+    // Do stuff
+});
\ No newline at end of file
diff --git a/tools/gui/package.json b/tools/gui/package.json
index a6a79f2..4c2aeb0 100644
--- a/tools/gui/package.json
+++ b/tools/gui/package.json
@@ -14,18 +14,11 @@
     "babel": "^6.23.0",
     "babel-core": "^6.25.0",
     "babel-preset-es2015": "^6.24.1",
-    "browser-sync": "^2.18.12",
-    "eslint": "^4.2.0",
-    "eslint-config-google": "^0.9.1",
     "gulp": "^3.9.1",
     "gulp-concat": "^2.6.1",
-    "gulp-eslint": "3.0.1",
-    "gulp-if": "^2.0.2",
     "gulp-sourcemaps": "^2.6.0",
     "gulp-strip-comments": "^2.4.5",
     "gulp-uglify": "^3.0.0",
-    "gulp-webserver": "^0.9.1",
-    "http-proxy-middleware": "^0.17.4",
     "jasmine-core": "^2.6.4",
     "karma": "^1.7.0",
     "karma-babel-preprocessor": "^6.0.1",
diff --git a/web/gui/onos-gui-build b/web/gui/onos-gui-build
index 07dfd35..8f6a2cb 100755
--- a/web/gui/onos-gui-build
+++ b/web/gui/onos-gui-build
@@ -1,10 +1,9 @@
 #!/bin/bash
-set -e
 
 ONOS_INSTALL_LOCATION=$2
 echo ${ONOS_INSTALL_LOCATION}
 
-export NODEJS_HOME=${ONOS_INSTALL_LOCATION}
+export NODEJS_HOME=${ONOS_INSTALL_LOCATION}/
 export PATH=$NODEJS_HOME/bin:$PATH
 
 cd $ONOS_ROOT/tools/gui
diff --git a/web/gui/src/main/webapp/app/directives.js b/web/gui/src/main/webapp/app/directives.js
index 22c6bc0..0e85d76 100644
--- a/web/gui/src/main/webapp/app/directives.js
+++ b/web/gui/src/main/webapp/app/directives.js
@@ -30,14 +30,14 @@
                 scope: {
                     offsetHeight: '@',
                     offsetWidth: '@',
-                    notifier: '&',
+                    notifier: '&'
                 },
                 link: function (scope, element) {
                     var elem = d3.select(element[0]);
                     scope.$watchCollection(function () {
                         return {
                             h: $window.innerHeight,
-                            w: $window.innerWidth,
+                            w: $window.innerWidth
                         };
                     }, function () {
                         var offH = scope.offsetHeight || 0,
@@ -46,7 +46,7 @@
 
                         elem.style({
                             height: wsz.height + 'px',
-                            width: wsz.width + 'px',
+                            width: wsz.width + 'px'
                         });
 
                         if (fs.isF(scope.notifier)) {
@@ -57,7 +57,7 @@
                     angular.element($window).bind('resize', function () {
                         scope.$apply();
                     });
-                },
+                }
             };
         }])
 
diff --git a/web/gui/src/main/webapp/app/fw/layer/dialog.js b/web/gui/src/main/webapp/app/fw/layer/dialog.js
index 9e9b1f8..70f1082 100644
--- a/web/gui/src/main/webapp/app/fw/layer/dialog.js
+++ b/web/gui/src/main/webapp/app/fw/layer/dialog.js
@@ -23,12 +23,12 @@
     'use strict';
 
     // injected refs
-    var $log, fs, ps, ks;
+    var $log, $window, fs, ps, bns, ks;
 
     // configuration
     var defaultSettings = {
             width: 300,
-            edge: 'left',
+            edge: 'left'
         };
 
     // internal state
@@ -92,7 +92,7 @@
             appendHeader: hAppend,
             appendBody: bAppend,
             appendFooter: fAppend,
-            destroy: destroy,
+            destroy: destroy
         };
     }
 
@@ -141,7 +141,7 @@
     function _addOk(cb, text, chained) {
         return addButton(cb, text || 'OK', 'enter', chained);
     }
-
+    
     function addOk(cb, text) {
         return _addOk(cb, text, false);
     }
@@ -178,7 +178,7 @@
             addCancel: addCancel,
             bindKeys: function () {
                 ks.dialogKeys(keyBindings);
-            },
+            }
         };
         return dApi;
     }
@@ -207,21 +207,25 @@
 
     angular.module('onosLayer')
     .factory('DialogService',
-        ['$log', 'FnService', 'PanelService', 'KeyService',
+        ['$log', '$window', 'FnService', 'PanelService', 'ButtonService',
+            'KeyService',
 
-        // TODO: use $window to provide an option to center the 
-        // dialog on the window.
+        // TODO: for now, $window is not used, but we should provide an option
+            // to center the dialog on the window.
 
-        function (_$log_, _fs_, _ps_, _ks_) {
+        function (_$log_, _$window_, _fs_, _ps_, _bns_, _ks_) {
             $log = _$log_;
+            $window = _$window_;
             fs = _fs_;
             ps = _ps_;
+            bns = _bns_;
             ks = _ks_;
 
             return {
                 openDialog: openDialog,
                 closeDialog: closeDialog,
-                createDiv: createDiv,
+                createDiv: createDiv
             };
         }]);
+
 }());
diff --git a/web/gui/src/main/webapp/app/fw/layer/flash.js b/web/gui/src/main/webapp/app/fw/layer/flash.js
index cbb072f..b3fa1f8 100644
--- a/web/gui/src/main/webapp/app/fw/layer/flash.js
+++ b/web/gui/src/main/webapp/app/fw/layer/flash.js
@@ -24,12 +24,12 @@
     'use strict';
 
     // injected references
-    var $timeout;
+    var $log, $timeout;
 
     // configuration
     var defaultSettings = {
             fade: 200,
-            showFor: 1200,
+            showFor: 1200
         },
         w = '100%',
         h = 200,
@@ -70,7 +70,7 @@
             svg = flashDiv.append('svg').attr({
                 width: w,
                 height: h,
-                viewBox: vbox,
+                viewBox: vbox
             });
         }
 
@@ -93,7 +93,7 @@
             .append('g')
             .attr({
                 class: 'flashItem',
-                opacity: 0,
+                opacity: 0
             })
             .transition()
             .duration(settings.fade)
@@ -151,8 +151,9 @@
     }
 
     angular.module('onosLayer')
-        .factory('FlashService', ['$timeout',
-        function (_$timeout_) {
+        .factory('FlashService', ['$log', '$timeout',
+        function (_$log_, _$timeout_) {
+            $log = _$log_;
             $timeout = _$timeout_;
 
             function initFlash(opts) {
@@ -165,7 +166,7 @@
                 initFlash: initFlash,
                 flash: flash,
                 enable: enable,
-                tempDiv: tempDiv,
+                tempDiv: tempDiv
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/layer/loading.js b/web/gui/src/main/webapp/app/fw/layer/loading.js
index 699cb39..3c8fd24 100644
--- a/web/gui/src/main/webapp/app/fw/layer/loading.js
+++ b/web/gui/src/main/webapp/app/fw/layer/loading.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected references
-    var $timeout, ts, fs;
+    var $log, $timeout, ts, fs;
 
     // constants
     var id = 'loading-anim',
@@ -122,9 +122,10 @@
 
     angular.module('onosLayer')
         .factory('LoadingService',
-        ['$timeout', 'ThemeService', 'FnService', 'WebSocketService',
+        ['$log', '$timeout', 'ThemeService', 'FnService', 'WebSocketService',
 
-            function (_$timeout_, _ts_, _fs_, wss) {
+            function (_$log_, _$timeout_, _ts_, _fs_, wss) {
+            $log = _$log_;
             $timeout = _$timeout_;
             ts = _ts_;
             fs = _fs_;
@@ -134,10 +135,10 @@
             var self = {
                 start: start,
                 stop: stop,
-                waiting: waiting,
+                waiting: waiting
             };
             wss._setLoadingDelegate(self);
             return self;
         }]);
 
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/fw/layer/panel.js b/web/gui/src/main/webapp/app/fw/layer/panel.js
index 3c4cfb9..f2b6bf0 100644
--- a/web/gui/src/main/webapp/app/fw/layer/panel.js
+++ b/web/gui/src/main/webapp/app/fw/layer/panel.js
@@ -28,7 +28,7 @@
         margin: 20,
         hideMargin: 20,
         xtnTime: 750,
-        fade: true,
+        fade: true
     };
 
     var panels,
@@ -71,7 +71,7 @@
                 id: id,
                 settings: settings,
                 on: false,
-                el: null,
+                el: null
             },
             api = {
                 show: showPanel,
@@ -84,7 +84,7 @@
                 bbox: panelBBox,
                 isVisible: panelIsVisible,
                 classed: classed,
-                el: panelEl,
+                el: panelEl
             };
 
         p.el = panelLayer.append('div')
@@ -215,7 +215,7 @@
             return {
                 init: init,
                 createPanel: createPanel,
-                destroyPanel: destroyPanel,
+                destroyPanel: destroyPanel
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/layer/quickhelp.js b/web/gui/src/main/webapp/app/fw/layer/quickhelp.js
index 9755e53..5ef4369 100644
--- a/web/gui/src/main/webapp/app/fw/layer/quickhelp.js
+++ b/web/gui/src/main/webapp/app/fw/layer/quickhelp.js
@@ -27,7 +27,7 @@
 
     // configuration
     var defaultSettings = {
-            fade: 500,
+            fade: 500
         },
         w = '100%',
         h = '80%',
@@ -56,12 +56,12 @@
         leftArrow: 'L-arrow',
         upArrow: 'U-arrow',
         rightArrow: 'R-arrow',
-        downArrow: 'D-arrow',
+        downArrow: 'D-arrow'
     };
 
     // list of needed bindings to use in aggregateData
     var neededBindings = [
-        'globalKeys', 'globalFormat', 'viewKeys', 'viewGestures',
+        'globalKeys', 'globalFormat', 'viewKeys', 'viewGestures'
     ];
 
     // ===========================================
@@ -88,7 +88,7 @@
                 aggKey = el.append('g').attr('visibility', 'hidden'),
                 gcol = el.append('g').attr({
                     'class': cls,
-                    transform: sus.translate(xCount, 0),
+                    transform: sus.translate(xCount, 0)
                 });
 
             c.forEach(function (j) {
@@ -101,12 +101,12 @@
                     gcol.append('text').text(k)
                         .attr({
                             'class': 'key',
-                            y: oy,
+                            y: oy
                         });
                     gcol.append('text').text(v)
                         .attr({
                             'class': 'desc',
-                            y: oy,
+                            y: oy
                         });
                 }
 
@@ -140,7 +140,7 @@
         var entering = rows.enter()
             .append('g')
             .attr({
-                'class': 'qhrow',
+                'class': 'qhrow'
             });
 
         entering.each(function (r, i) {
@@ -169,7 +169,7 @@
         rect.attr({
             width: paneW,
             height: paneH,
-            transform: sus.translate(-paneW/2-pad, 0),
+            transform: sus.translate(-paneW/2-pad, 0)
         });
 
     }
@@ -279,7 +279,7 @@
         pane = svg.append('g')
             .attr({
                 class: 'help',
-                opacity: 0,
+                opacity: 0
             });
 
         rect = pane.append('rect')
@@ -290,7 +290,7 @@
             .attr({
                 class: 'title',
                 dy: '1.2em',
-                transform: sus.translate(-pad, 0),
+                transform: sus.translate(-pad,0)
             });
 
         items = pane.append('g');
@@ -316,7 +316,7 @@
             .attr({
                 width: w,
                 height: h,
-                viewBox: vbox,
+                viewBox: vbox
             });
     }
 
@@ -338,7 +338,7 @@
                 'needed bindings for help panel not provided:',
                 neededBindings
             );
-            return false;
+            return false
         }
         return true;
     }
@@ -387,7 +387,7 @@
             return {
                 initQuickHelp: initQuickHelp,
                 showQuickHelp: showQuickHelp,
-                hideQuickHelp: hideQuickHelp,
+                hideQuickHelp: hideQuickHelp
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/layer/veil.js b/web/gui/src/main/webapp/app/fw/layer/veil.js
index 1a8d9c4..c7f5a29 100644
--- a/web/gui/src/main/webapp/app/fw/layer/veil.js
+++ b/web/gui/src/main/webapp/app/fw/layer/veil.js
@@ -41,7 +41,7 @@
 
         svg = veil.select('svg').attr({
             width: ww,
-            height: wh,
+            height: wh
         }).style('opacity', 0.2);
 
         gs.addGlyph(svg, 'bird', birdDim, false, [birdCenter, shrink/2]);
@@ -71,7 +71,7 @@
     function lostServer(ctrlName, msg) {
         if ($route.current.$$route.controller === ctrlName) {
             $log.debug('VEIL-service: ', ctrlName);
-            show(msg);
+            show(msg)
         } else {
             $log.debug('VEIL-service: IGNORING ', ctrlName);
         }
@@ -92,7 +92,7 @@
                 init: init,
                 show: show,
                 hide: hide,
-                lostServer: lostServer,
+                lostServer: lostServer
             };
             wss._setVeilDelegate(self);
             return self;
diff --git a/web/gui/src/main/webapp/app/fw/mast/mast.js b/web/gui/src/main/webapp/app/fw/mast/mast.js
index 525eea9..ae7c81b 100644
--- a/web/gui/src/main/webapp/app/fw/mast/mast.js
+++ b/web/gui/src/main/webapp/app/fw/mast/mast.js
@@ -24,7 +24,7 @@
     var mastHeight = 48,
         padMobile = 16,
         dialogOpts = {
-            edge: 'left',
+            edge: 'left'
         };
 
     var ls;
@@ -83,8 +83,8 @@
             }
 
             wss.bindHandlers({
-                'guiAdded': function () { triggerRefresh('add'); },
-                'guiRemoved': function () { triggerRefresh('rem'); },
+                'guiAdded': function () { triggerRefresh('add') },
+                'guiRemoved': function () { triggerRefresh('rem') }
             });
 
             // delegate to NavService
@@ -120,8 +120,8 @@
             return {
                 mastHeight: function () {
                     return fs.isMobile() ? mastHeight + padMobile : mastHeight;
-                },
-            };
+                }
+            }
         }]);
 
 }());
diff --git a/web/gui/src/main/webapp/app/fw/nav/nav.js b/web/gui/src/main/webapp/app/fw/nav/nav.js
index 30881d7..07a5603 100644
--- a/web/gui/src/main/webapp/app/fw/nav/nav.js
+++ b/web/gui/src/main/webapp/app/fw/nav/nav.js
@@ -79,7 +79,7 @@
 
                 self.hideNav = hideNav;
                 $log.log('NavCtrl has been created');
-            },
+            }
         ])
         .factory('NavService',
             ['$log', '$location', '$window', 'FnService',
@@ -95,7 +95,7 @@
                     hideNav: hideNav,
                     toggleNav: toggleNav,
                     hideIfShown: hideIfShown,
-                    navTo: navTo,
+                    navTo: navTo
                 };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/remote/rest.js b/web/gui/src/main/webapp/app/fw/remote/rest.js
index bd73ae9..1f349b8 100644
--- a/web/gui/src/main/webapp/app/fw/remote/rest.js
+++ b/web/gui/src/main/webapp/app/fw/remote/rest.js
@@ -66,7 +66,7 @@
 
             return {
                 get: get,
-                post: post,
+                post: post
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/remote/urlfn.js b/web/gui/src/main/webapp/app/fw/remote/urlfn.js
index 4005b8a..bf142d4 100644
--- a/web/gui/src/main/webapp/app/fw/remote/urlfn.js
+++ b/web/gui/src/main/webapp/app/fw/remote/urlfn.js
@@ -68,7 +68,7 @@
 
             return {
                 rsUrl: rsUrl,
-                wsUrl: wsUrl,
+                wsUrl: wsUrl
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/remote/websocket.js b/web/gui/src/main/webapp/app/fw/remote/websocket.js
index 8e7f5e5..5922c60 100644
--- a/web/gui/src/main/webapp/app/fw/remote/websocket.js
+++ b/web/gui/src/main/webapp/app/fw/remote/websocket.js
@@ -24,19 +24,19 @@
     var $log, $loc, fs, ufs, wsock, vs, ls;
 
     // internal state
-    var webSockOpts, // web socket options
-        ws = null, // web socket reference
-        wsUp = false, // web socket is good to go
-        handlers = {}, // event handler bindings
-        pendingEvents = [], // events TX'd while socket not up
-        host, // web socket host
-        url, // web socket URL
-        clusterNodes = [], // ONOS instances data for failover
-        clusterIndex = -1, // the instance to which we are connected
-        connectRetries = 0, // limit our attempts at reconnecting
-        openListeners = {}, // registered listeners for websocket open()
-        nextListenerId = 1, // internal ID for open listeners
-        loggedInUser = null; // name of logged-in user
+    var webSockOpts,            // web socket options
+        ws = null,              // web socket reference
+        wsUp = false,           // web socket is good to go
+        handlers = {},          // event handler bindings
+        pendingEvents = [],     // events TX'd while socket not up
+        host,                   // web socket host
+        url,                    // web socket URL
+        clusterNodes = [],      // ONOS instances data for failover
+        clusterIndex = -1,      // the instance to which we are connected
+        connectRetries = 0,     // limit our attempts at reconnecting
+        openListeners = {},     // registered listeners for websocket open()
+        nextListenerId = 1,     // internal ID for open listeners
+        loggedInUser = null;    // name of logged-in user
 
     // built-in handlers
     var builtinHandlers = {
@@ -62,9 +62,9 @@
             vs && vs.show([
                 'Oops!',
                 'Server reports error...',
-                m,
+                m
             ]);
-        },
+        }
     };
 
 
@@ -129,7 +129,7 @@
             vs && vs.show([
                 'Oops!',
                 'Web-socket connection to server closed...',
-                'Try refreshing the page.',
+                'Try refreshing the page.'
             ]);
         }
     }
@@ -210,7 +210,7 @@
             ws.onmessage = handleMessage;
             ws.onclose = handleClose;
 
-            sendEvent('authentication', { token: onosAuth });
+            sendEvent('authentication', {token: onosAuth});
         }
         // Note: Wsock logs an error if the new WebSocket call fails
         return url;
@@ -299,7 +299,7 @@
     function sendEvent(evType, payload) {
         var ev = {
                 event: evType,
-                payload: payload || {},
+                payload: payload || {}
             };
 
         if (wsUp) {
@@ -347,9 +347,9 @@
                 loggedInUser: function () { return loggedInUser || '(no-one)'; },
 
                 _setVeilDelegate: setVeilDelegate,
-                _setLoadingDelegate: setLoadingDelegate,
+                _setLoadingDelegate: setLoadingDelegate
             };
-        },
+        }
     ]);
 
 }());
diff --git a/web/gui/src/main/webapp/app/fw/remote/wsock.js b/web/gui/src/main/webapp/app/fw/remote/wsock.js
index 2c7342d..666c6e6 100644
--- a/web/gui/src/main/webapp/app/fw/remote/wsock.js
+++ b/web/gui/src/main/webapp/app/fw/remote/wsock.js
@@ -36,7 +36,7 @@
             }
 
             return {
-                newWebSocket: newWebSocket,
+                newWebSocket: newWebSocket
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/svg/geodata.js b/web/gui/src/main/webapp/app/fw/svg/geodata.js
index 8b24519..e740cbe 100644
--- a/web/gui/src/main/webapp/app/fw/svg/geodata.js
+++ b/web/gui/src/main/webapp/app/fw/svg/geodata.js
@@ -93,7 +93,7 @@
             promise.meta = {
                 id: id,
                 url: url,
-                wasCached: false,
+                wasCached: false
             };
 
             promise.then(function (response) {
@@ -118,7 +118,7 @@
         objectTag: 'states',
         projection: d3.geo.mercator(),
         logicalSize: 1000,
-        mapFillScale: .95,
+        mapFillScale: .95
     };
 
     // converts given TopoJSON-format data into corresponding GeoJSON
@@ -138,7 +138,7 @@
         return {
             geodata: geoData,
             pathgen: path,
-            settings: settings,
+            settings: settings
         };
     }
 
@@ -181,7 +181,7 @@
                 clearCache: clearCache,
                 fetchTopoData: fetchTopoData,
                 createPathGenerator: createPathGenerator,
-                rescaleProjection: rescaleProjection,
+                rescaleProjection: rescaleProjection
             };
         }]);
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/fw/svg/glyph.js b/web/gui/src/main/webapp/app/fw/svg/glyph.js
index 0fa9902..77ff1f4b 100644
--- a/web/gui/src/main/webapp/app/fw/svg/glyph.js
+++ b/web/gui/src/main/webapp/app/fw/svg/glyph.js
@@ -29,8 +29,8 @@
 
     // constants
     var msgGS = 'GlyphService.',
-        rg = 'registerGlyphs(): ',
-        rgs = 'registerGlyphSet(): ';
+        rg = "registerGlyphs(): ",
+        rgs = "registerGlyphSet(): ";
 
     // ----------------------------------------------------------------------
 
@@ -42,7 +42,7 @@
         if (!overwrite && glyphs.get(key)) {
             dups.push(key);
         } else {
-            glyphs.set(key, { id: key, vb: vbox, d: value });
+            glyphs.set(key, {id: key, vb: vbox, d: value});
         }
     }
 
@@ -166,7 +166,7 @@
                 width: sz,
                 height: sz,
                 'class': 'glyph',
-                'xlink:href': '#' + glyphId,
+                'xlink:href': '#' + glyphId
             };
 
         if (xns) {
@@ -196,7 +196,7 @@
                 glyph: glyph,
                 glyphDefined: glyphDefined,
                 loadDefs: loadDefs,
-                addGlyph: addGlyph,
+                addGlyph: addGlyph
             };
             return api;
         }]
diff --git a/web/gui/src/main/webapp/app/fw/svg/glyphData.js b/web/gui/src/main/webapp/app/fw/svg/glyphData.js
index c3a0fe2..527957b 100644
--- a/web/gui/src/main/webapp/app/fw/svg/glyphData.js
+++ b/web/gui/src/main/webapp/app/fw/svg/glyphData.js
@@ -60,7 +60,7 @@
             'm-0.6,7.4a21.3,21.3,0,0,0,5.9,11.7l5.7,5.7' +
             'c3,3,9,4.1,11.9,1.3-3.3.9-5.9-1.2-7.9-3.2L34.3,88.1Z' +
             'm3.5-12.4a16.6,16.6,0,0,0-2.3,3.6L57,100.8' +
-            'c3,3,9,4.1,11.9,1.3-3.3.9-5.9-1.2-7.9-3.2Z',
+            'c3,3,9,4.1,11.9,1.3-3.3.9-5.9-1.2-7.9-3.2Z'
         },
 
 
@@ -509,7 +509,7 @@
             'L22,23.7z M97.9,46.5H77.2L88,23.7L97.9,46.5z',
 
             xClose: 'M20,8l35,35,35-35,12,12-35,35,35,35-12,12-35-35-35,35' +
-            '-12-12,35-35-35-35,12-12Z',
+            '-12-12,35-35-35-35,12-12Z'
         },
 
         badgeDataSet = {
@@ -533,7 +533,7 @@
 
             play: 'M3,1.5l3.5,3.5l-3.5,3.5z',
 
-            stop: 'M2.5,2.5h5v5h-5z',
+            stop: 'M2.5,2.5h5v5h-5z'
         },
 
         spriteData = {
@@ -548,7 +548,7 @@
             'M93.6,74.7c10.2-2,10.7-14,5.8-18.3' +
             'M71.1,79.3c11.2,7.6,24.6,6.4,22.1-11.7' +
             'M36.4,76.8c3.4,13.3,35.4,11.6,36.1-1.4' +
-            'M70.4,31c11.8-10.4,26.2-5.2,24.7,10.1',
+            'M70.4,31c11.8-10.4,26.2-5.2,24.7,10.1'
         },
 
 
@@ -1270,7 +1270,7 @@
             'M81.7,80.8H17.9a1.8,1.8,0,0,1-1.6-2.7l9.2-16.8' +
             'a1.8,1.8,0,0,1,1.6-1h9.5a1.8,1.8,0,1,1,0,3.7H28.2L21,77.1H78.6' +
             'L71.4,64H61.9a1.8,1.8,0,1,1,0-3.7H72.5a1.8,1.8,0,0,1,1.6,1' +
-            'l9.2,16.8A1.8,1.8,0,0,1,81.7,80.8Z',
+            'l9.2,16.8A1.8,1.8,0,0,1,81.7,80.8Z'
         },
 
         extraGlyphs = {
@@ -1283,7 +1283,7 @@
             'a175.5,175.5,0,0,0,58.6-10l3.9-1.4,3.9-1.5,3.9-1.7h0' +
             'l3.9-1.7,2.8-1.3,2.7-1.4a175.6,175.6,0,0,0,95.9-155.1' +
             'C372.4,226.7,358,290.1,286.5,289.9ZM110.1,237.7' +
-            'A33.6,33.6,0,1,1,143.7,204,33.6,33.6,0,0,1,110.1,237.7Z',
+            'A33.6,33.6,0,1,1,143.7,204,33.6,33.6,0,0,1,110.1,237.7Z'
         };
 
 
@@ -1305,7 +1305,7 @@
     .factory('GlyphDataService',
         [function () {
             return {
-                registerCoreGlyphs: registerCoreGlyphs,
+                registerCoreGlyphs: registerCoreGlyphs
             };
         }]
     );
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.js b/web/gui/src/main/webapp/app/fw/svg/icon.js
index b0435d5..659a5be 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -20,7 +20,7 @@
 (function () {
     'use strict';
 
-    var $log, gs, sus;
+    var $log, fs, gs, sus;
 
     var vboxSize = 50,
         cornerSize = vboxSize / 10,
@@ -36,7 +36,7 @@
         minus: 'minus',
         play: 'play',
         stop: 'stop',
-
+        
         close: 'xClose',
 
         topo: 'topo',
@@ -76,8 +76,8 @@
         nav_links: 'ports',
         nav_hosts: 'endstation',
         nav_intents: 'relatedIntents',
-        nav_tunnels: 'ports', // TODO: use tunnel glyph, when available
-        nav_yang: 'yang',
+        nav_tunnels: 'ports',  // TODO: use tunnel glyph, when available
+        nav_yang: 'yang'
     };
 
     function ensureIconLibDefs() {
@@ -112,24 +112,24 @@
             'class': svgCls,
             width: dim,
             height: dim,
-            viewBox: viewBox,
+            viewBox: viewBox
         });
 
         g = svg.append('g').attr({
-            'class': 'icon',
+            'class': 'icon'
         });
 
         g.append('rect').attr({
             width: vboxSize,
             height: vboxSize,
-            rx: cornerSize,
+            rx: cornerSize
         });
 
         g.append('use').attr({
             width: vboxSize,
             height: vboxSize,
             'class': 'glyph',
-            'xlink:href': '#' + gid,
+            'xlink:href': '#' + gid
         });
     }
 
@@ -148,7 +148,7 @@
     function loadEmbeddedIcon(div, iconCls, size) {
         loadIconByClass(div, iconCls, size, true);
     }
-
+    
     // Adds a device glyph to the specified element.
     // Returns the D3 selection of the glyph (use) element.
     function addDeviceIcon(elem, glyphId, iconDim) {
@@ -156,7 +156,7 @@
         return elem.append('use').attr({
             'xlink:href': '#' + gid,
             width: iconDim,
-            height: iconDim,
+            height: iconDim
         });
     }
 
@@ -172,7 +172,7 @@
             'xlink:href': '#' + glyphId,
             width: dim,
             height: dim,
-            transform: sus.translate(xlate, xlate),
+            transform: sus.translate(xlate,xlate)
         });
         return g;
     }
@@ -187,7 +187,7 @@
         return {
             asc: function (div) { _s(div, 'upArrow'); },
             desc: function (div) { _s(div, 'downArrow'); },
-            none: function (div) { div.remove(); },
+            none: function (div) { div.remove(); }
         };
     }
 
@@ -215,15 +215,16 @@
                         div.selectAll('*').remove();
                         is.loadEmbeddedIcon(div, attrs.iconId, attrs.iconSize);
                     });
-                },
+                }
             };
         }])
 
-        .factory('IconService', ['$log', 'GlyphService',
+        .factory('IconService', ['$log', 'FnService', 'GlyphService',
             'SvgUtilService',
 
-        function (_$log_, _gs_, _sus_) {
+        function (_$log_, _fs_, _gs_, _sus_) {
             $log = _$log_;
+            fs = _fs_;
             gs = _gs_;
             sus = _sus_;
 
@@ -234,7 +235,7 @@
                 addDeviceIcon: addDeviceIcon,
                 addHostIcon: addHostIcon,
                 sortIcons: sortIcons,
-                registerIconMapping: registerIconMapping,
+                registerIconMapping: registerIconMapping
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/svg/map.js b/web/gui/src/main/webapp/app/fw/svg/map.js
index 14b0e13a..78a33d1 100644
--- a/web/gui/src/main/webapp/app/fw/svg/map.js
+++ b/web/gui/src/main/webapp/app/fw/svg/map.js
@@ -35,7 +35,7 @@
     'use strict';
 
     // injected references
-    var $log, $q, gds;
+    var $log, $q, fs, gds;
 
     // NOTE: This method assumes the datafile has exactly the map data
     //       that you want to load; for example id="*continental_us"
@@ -87,7 +87,7 @@
     //     });
 
     function loadMapRegionInto(mapLayer, opts) {
-        var promise = gds.fetchTopoData('*countries'),
+        var promise = gds.fetchTopoData("*countries"),
             deferredProjection = $q.defer();
 
         if (!promise) {
@@ -105,7 +105,7 @@
                 country = features.filter(opts.countryFilter),
                 countryFeature = {
                     type: 'FeatureCollection',
-                    features: country,
+                    features: country
                 },
                 path = d3.geo.path().projection(proj);
 
@@ -137,7 +137,7 @@
             svg.style('background-color', bg);
             paths.attr({
                 stroke: stroke,
-                fill: fill,
+                fill: fill
             });
         } else {
             svg.style('background-color', null);
@@ -145,16 +145,17 @@
     }
 
     angular.module('onosSvg')
-        .factory('MapService', ['$log', '$q', 'GeoDataService',
-        function (_$log_, _$q_, _gds_) {
+        .factory('MapService', ['$log', '$q', 'FnService', 'GeoDataService',
+        function (_$log_, _$q_, _fs_, _gds_) {
             $log = _$log_;
             $q = _$q_;
+            fs = _fs_;
             gds = _gds_;
 
             return {
                 loadMapRegionInto: loadMapRegionInto,
                 loadMapInto: loadMapInto,
-                reshade: reshade,
+                reshade: reshade
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/svg/sprite.js b/web/gui/src/main/webapp/app/fw/svg/sprite.js
index 9a1111e..b64f58d 100644
--- a/web/gui/src/main/webapp/app/fw/svg/sprite.js
+++ b/web/gui/src/main/webapp/app/fw/svg/sprite.js
@@ -32,30 +32,30 @@
             },
             addRect: {
                 fill: 'gray1',
-                stroke: 'none',
+                stroke: 'none'
             },
             addPath: {
                 fill: 'none',
-                stroke: 'gray1',
-            },
+                stroke: 'gray1'
+            }
         },
         layout: {
             builder: {
-                grid: 10, // grid square size (in layout coord-space)
+                grid: 10            // grid square size (in layout coord-space)
             },
             addSprite: {
-                anchor: 'topleft', // topleft, center
+                anchor: 'topleft'       // topleft, center
             },
             addLabel: {
-                anchor: 'center', // center, left, right
-                fontStyle: 'normal', // normal, italic, bold
-            },
-        },
+                anchor: 'center',       // center, left, right
+                fontStyle: 'normal'     // normal, italic, bold
+            }
+        }
     };
 
     // internal state
-    var sprites, // sprite cache
-        layouts, // layout cache
+    var sprites,    // sprite cache
+        layouts,    // layout cache
         api;
 
     // ----------------------------------------------------------------------
@@ -81,7 +81,7 @@
             var o = angular.extend({}, optDefaults.sprite.addRect, opts);
 
             rects.push({
-                x: x, y: y, w: w, h: h, o: o,
+                x: x, y: y, w: w, h: h, o: o
             });
             return builder;
         }
@@ -90,9 +90,9 @@
             var o = angular.extend({}, optDefaults.sprite.addPath, opts);
 
             if (fs.isS(d)) {
-                paths.push({ d: d, o: o });
+                paths.push({d: d, o: o});
             } else if (fs.isA(d)) {
-                paths.push({ d: d.join(''), o: o });
+                paths.push({d: d.join(''), o: o});
             } else {
                 $log.warn('addPath: path not a string or array', d);
             }
@@ -110,7 +110,7 @@
                 id: id,
                 w: w,
                 h: h,
-                opts: o,
+                opts: o
             },
             paths: paths,
             rects: rects,
@@ -118,7 +118,7 @@
             // builder API
             addRect: addRect,
             addPath: addPath,
-            register: register,
+            register: register
         };
 
         return builder;
@@ -153,7 +153,7 @@
             }
 
             sprs.push({
-                sprite: s, x: x, y: y, w: w, anchor: o.anchor,
+                sprite: s, x: x, y: y, w: w, anchor: o.anchor
             });
             return builder;
         }
@@ -162,7 +162,7 @@
             var o = angular.extend({}, optDefaults.layout.addLabel, opts);
 
             labs.push({
-                text: text, x: x, y: y, anchor: o.anchor, style: o.fontStyle,
+                text: text, x: x, y: y, anchor: o.anchor, style: o.fontStyle
             });
             return builder;
         }
@@ -178,7 +178,7 @@
                 id: id,
                 w: w,
                 h: h,
-                opts: o,
+                opts: o
             },
             sprites: sprs,
             labels: labs,
@@ -186,7 +186,7 @@
             // builder API
             addSprite: addSprite,
             addLabel: addLabel,
-            register: register,
+            register: register
         };
 
         return builder;
@@ -246,7 +246,7 @@
     function count() {
         return {
             sprites: sprites.size(),
-            layouts: layouts.size(),
+            layouts: layouts.size()
         };
     }
 
@@ -278,7 +278,7 @@
                 sprite: sprite,
                 layout: layout,
                 count: count,
-                dump: dump,
+                dump: dump
             };
             return api;
         }]
diff --git a/web/gui/src/main/webapp/app/fw/svg/spriteData.js b/web/gui/src/main/webapp/app/fw/svg/spriteData.js
index f915cb2..d970af9 100644
--- a/web/gui/src/main/webapp/app/fw/svg/spriteData.js
+++ b/web/gui/src/main/webapp/app/fw/svg/spriteData.js
@@ -28,18 +28,18 @@
         // TODO: define cloud sprite...
         vbox: '0 0 305 186',
         d: [
-            'M91.2,48.4C121.2,6.3,187.9-13.4,219,45.6',
-            'M43.1,139.6C21.8,142.9-15.6,108.4,26.1,79',
-            'M103.7,150C89,205.2-11.2,167.4,30.5,138',
-            'M192.3,147.3c-33.5,48-82.1,32.3-94.5-8.2',
-            'M267.1,115c27.9,67.8-77.6,74.3-83.1,41',
-            'M34.3,89.9C10.8,79,59.5,10.7,97.2,39.6',
-            'M211.9,34.2c51.9-38.8,118,57.4,59,94.5',
+            "M91.2,48.4C121.2,6.3,187.9-13.4,219,45.6",
+            "M43.1,139.6C21.8,142.9-15.6,108.4,26.1,79",
+            "M103.7,150C89,205.2-11.2,167.4,30.5,138",
+            "M192.3,147.3c-33.5,48-82.1,32.3-94.5-8.2",
+            "M267.1,115c27.9,67.8-77.6,74.3-83.1,41",
+            "M34.3,89.9C10.8,79,59.5,10.7,97.2,39.6",
+            "M211.9,34.2c51.9-38.8,118,57.4,59,94.5"
         ],
         style: {
             fill: 'none',
-            'stroke-miterlimit': 10,
-        },
+            'stroke-miterlimit': 10
+        }
     };
 
     // TODO: define other core sprites here...
@@ -55,12 +55,12 @@
         // ----------------------------------------------------------$$$
         // This following code is for initial development of Topo2 sprite layer
         ssApi.createSprite('rack', 40, 50)
-            .addRect(0, 0, 40, 50, { fill: 'gold1' })
+            .addRect(0, 0, 40, 50, {fill: 'gold1'})
             .addPath([
                 'M5,20h30v5h-30z',
                 'M5,30h30v5h-30z',
-                'M5,40h30v5h-30z',
-            ], { stroke: 'gray1' })
+                'M5,40h30v5h-30z'
+            ], {stroke: 'gray1'})
             .register();
 
         ssApi.createLayout('segmentRouting', 130, 75)
@@ -68,13 +68,13 @@
             .addSprite('rack', 40, 40, 20)
             .addSprite('rack', 70, 40, 20)
             .addSprite('rack', 100, 40, 20)
-            .addLabel('Segment Routing', 120, 10, { anchor: 'right' })
+            .addLabel('Segment Routing', 120, 10, {anchor: 'right'})
             .register();
 
         ssApi.createLayout('segmentRoutingTwo', 70, 75)
             .addSprite('rack', 10, 40, 20)
             .addSprite('rack', 40, 40, 20)
-            .addLabel('Segment Routing 2', 120, 10, { anchor: 'right' })
+            .addLabel('Segment Routing 2', 120, 10, {anchor: 'right'})
             .register();
 
         ssApi.createLayout('plain', 80, 60)
@@ -90,9 +90,9 @@
         .factory('SpriteDataService', [
             function () {
                 return {
-                    registerCoreSprites: registerCoreSprites,
+                    registerCoreSprites: registerCoreSprites
                 };
-            },
+            }
         ]);
 
 }());
diff --git a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
index 90eb526..1d8dee3 100644
--- a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
+++ b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
@@ -82,8 +82,8 @@
         }
 
         drag = d3.behavior.drag()
-            .origin(function (d) { return d; })
-            .on('dragstart', function (d) {
+            .origin(function(d) { return d; })
+            .on('dragstart', function(d) {
                 if (clickEnabled() || dragEnabled()) {
                     d.oldX = d.x;
                     d.oldY = d.y;
@@ -92,7 +92,7 @@
                     d.dragStarted = true;
                 }
             })
-            .on('drag', function (d) {
+            .on('drag', function(d) {
                 if (dragEnabled()) {
                     d.px = d3.event.x;
                     d.py = d3.event.y;
@@ -103,7 +103,7 @@
                     }
                 }
             })
-            .on('dragend', function (d) {
+            .on('dragend', function(d) {
                 d3.event.sourceEvent.stopPropagation();
 
                 if (d.dragStarted) {
@@ -170,22 +170,22 @@
 
     // Colors per Mojo-Design's color palette.. (version two)
     //               blue       lt blue    red        green      brown      teal       lime
-    var lightNorm = ['#5b99d2', '#66cef6', '#d05a55', '#0f9d58', '#ba7941', '#3dc0bf', '#56af00'],
-        lightMute = ['#9ebedf', '#abdef5', '#d79a96', '#7cbe99', '#cdab8d', '#96d5d5', '#a0c96d'],
+    var lightNorm = ['#5b99d2', '#66cef6', '#d05a55', '#0f9d58', '#ba7941', '#3dc0bf', '#56af00' ],
+        lightMute = ['#9ebedf', '#abdef5', '#d79a96', '#7cbe99', '#cdab8d', '#96d5d5', '#a0c96d' ],
 
-        darkNorm = ['#5b99d2', '#66cef6', '#d05a55', '#0f9d58', '#ba7941', '#3dc0bf', '#56af00'],
-        darkMute = ['#9ebedf', '#abdef5', '#d79a96', '#7cbe99', '#cdab8d', '#96d5d5', '#a0c96d'];
+        darkNorm  = ['#5b99d2', '#66cef6', '#d05a55', '#0f9d58', '#ba7941', '#3dc0bf', '#56af00' ],
+        darkMute  = ['#9ebedf', '#abdef5', '#d79a96', '#7cbe99', '#cdab8d', '#96d5d5', '#a0c96d' ];
 
 
     var colors= {
         light: {
             norm: d3.scale.ordinal().range(lightNorm),
-            mute: d3.scale.ordinal().range(lightMute),
+            mute: d3.scale.ordinal().range(lightMute)
         },
         dark: {
             norm: d3.scale.ordinal().range(darkNorm),
-            mute: d3.scale.ordinal().range(darkMute),
-        },
+            mute: d3.scale.ordinal().range(darkMute)
+        }
     };
 
     function cat7() {
@@ -231,7 +231,7 @@
                             cx: x,
                             cy: y,
                             r: 5,
-                            fill: f,
+                            fill: f
                         });
                     });
                     g.append('rect').attr({
@@ -240,13 +240,13 @@
                         width: 32,
                         height: 10,
                         rx: 2,
-                        fill: '#888',
+                        fill: '#888'
                     });
                     g.append('text').text(theme + what)
                         .attr({
                             x: 142,
                             y: k * 20 + 2,
-                            fill: 'white',
+                            fill: 'white'
                         })
                         .style('font-size', '4pt');
                 }
@@ -255,7 +255,7 @@
 
         return {
             testCard: testCard,
-            getColor: getColor,
+            getColor: getColor
         };
     }
 
@@ -279,7 +279,7 @@
     }
 
     function stripPx(s) {
-        return s.replace(/px$/, '');
+        return s.replace(/px$/,'');
     }
 
     function safeId(s) {
@@ -318,7 +318,7 @@
                 rotate: rotate,
                 stripPx: stripPx,
                 safeId: safeId,
-                visible: visible,
+                visible: visible
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/svg/zoom.js b/web/gui/src/main/webapp/app/fw/svg/zoom.js
index 0686542..0effdc2 100644
--- a/web/gui/src/main/webapp/app/fw/svg/zoom.js
+++ b/web/gui/src/main/webapp/app/fw/svg/zoom.js
@@ -25,7 +25,7 @@
         zoomMin: 0.05,
         zoomMax: 50,
         zoomEnabled: function (ev) { return true; },
-        zoomCallback: function () {},
+        zoomCallback: function () {}
     };
 
     // injected references to services
@@ -95,7 +95,7 @@
 
                     settings.zoomLayer.transition()
                         .duration(transition || 0)
-                        .attr('transform',
+                        .attr("transform",
                             'translate(' + translate + ')scale(' + scale + ')');
 
                     settings.zoomCallback(translate, scale);
@@ -109,7 +109,7 @@
                     },
 
                     reset: function () {
-                        zoomer.panZoom([0, 0], 1);
+                        zoomer.panZoom([0,0], 1);
                     },
 
                     translate: function () {
@@ -122,7 +122,7 @@
 
                     scaleExtent: function () {
                         return zoom.scaleExtent();
-                    },
+                    }
                 };
 
                 // apply the zoom behavior to the SVG element
@@ -130,12 +130,12 @@
 
                 // Remove zoom on double click (prevents a
                 // false zoom navigating regions)
-                settings.svg.on('dblclick.zoom', null);
+                settings.svg.on("dblclick.zoom", null);
                 return zoomer;
             }
 
             return {
-                createZoomer: createZoomer,
+                createZoomer: createZoomer
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/util/ee.js b/web/gui/src/main/webapp/app/fw/util/ee.js
index 2c20fcb..2ead7c2 100644
--- a/web/gui/src/main/webapp/app/fw/util/ee.js
+++ b/web/gui/src/main/webapp/app/fw/util/ee.js
@@ -37,7 +37,7 @@
         'ias',
         'jweeidkpizn',
         'fmfv',
-        'hwdoc',
+        'hwdoc'
         // Add more beans...
     ];
 
@@ -54,7 +54,7 @@
             i;
 
         for (i = 0; i<n; i+=2)
-            { w.push(fcc(Number(d.slice(i, i+2)))); }
+            w.push(fcc(Number(d.slice(i, i+2))));
 
         return fs.eecode(h, w.join(''));
     }
@@ -96,7 +96,7 @@
 
             return {
                 genMap: genMap,
-                cluck: cluck,
-            };
+                cluck: cluck
+            }
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/util/fn.js b/web/gui/src/main/webapp/app/fw/util/fn.js
index 2d3d4ae..b30418a 100644
--- a/web/gui/src/main/webapp/app/fw/util/fn.js
+++ b/web/gui/src/main/webapp/app/fw/util/fn.js
@@ -31,7 +31,7 @@
         cca = String.prototype.charCodeAt;
 
     function _parseDebugFlags(dbgstr) {
-        var bits = dbgstr ? dbgstr.split(',') : [];
+        var bits = dbgstr ? dbgstr.split(",") : [];
         bits.forEach(function (key) {
             debugFlags[key] = true;
         });
@@ -114,7 +114,7 @@
             ow = offW || 0;
         return {
             height: $window.innerHeight - oh,
-            width: $window.innerWidth - ow,
+            width: $window.innerWidth - ow
         };
     }
 
@@ -129,10 +129,10 @@
     function isChrome() {
         var isChromium = $window.chrome,
             vendorName = $window.navigator.vendor,
-            isOpera = $window.navigator.userAgent.indexOf('OPR') > -1;
+            isOpera = $window.navigator.userAgent.indexOf("OPR") > -1;
         return (isChromium !== null &&
         isChromium !== undefined &&
-        vendorName === 'Google Inc.' &&
+        vendorName === "Google Inc." &&
         isOpera == false);
     }
 
@@ -247,7 +247,7 @@
         return {
             o: w,
             d: o.join(''),
-            e: fcc.apply(o, o),
+            e: fcc.apply(o, o)
         };
     }
 
@@ -301,7 +301,7 @@
                 np = c.p[q];
                 x = 1;
             }
-            return { p: np, s: c.s };
+            return { p: np, s: c.s }
         }
 
         function probe(c) {
@@ -309,12 +309,12 @@
                 k = Object.keys(c.p).length,
                 np = c.p[q];
 
-            t.push({ q: q, k: k, p: c.p });
+            t.push({ q:q, k:k, p:c.p });
             if (!np) {
                 t = [];
                 return { s: [] };
             }
-            return { p: np, s: c.s };
+            return { p: np, s: c.s }
         }
 
         function insert() {
@@ -382,7 +382,7 @@
 
     var hasOwn = {}.hasOwnProperty;
 
-    function classNames() {
+    function classNames () {
         var classes = [];
 
         for (var i = 0; i < arguments.length; i++) {
@@ -453,7 +453,7 @@
         while ((match = matcher.exec(html)) !== null) {
             matches.push({
                 full: match[0],
-                name: match[1],
+                name: match[1]
                 // NOTE: ignoring attributes {match[2].split(' ')} for now
             });
         }
@@ -527,7 +527,7 @@
                 trieLookup: trieLookup,
                 classNames: classNames,
                 extend: extend,
-                sanitize: sanitize,
+                sanitize: sanitize
             };
     }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/util/keys.js b/web/gui/src/main/webapp/app/fw/util/keys.js
index 1490c98..2e8900a 100644
--- a/web/gui/src/main/webapp/app/fw/util/keys.js
+++ b/web/gui/src/main/webapp/app/fw/util/keys.js
@@ -21,7 +21,7 @@
     'use strict';
 
     // references to injected services
-    var $log, fs, ts, ns, ee, qhs, ls;
+    var $log, $timeout, fs, ts, ns, ee, qhs, ls;
 
     // internal state
     var enabled = true,
@@ -32,7 +32,7 @@
             dialogKeys: {},
             viewKeys: {},
             viewFn: null,
-            viewGestures: [],
+            viewGestures: []
         },
         seq = {},
         matching = false,
@@ -96,7 +96,7 @@
 
     var textFieldDoesNotBlock = {
         enter: 1,
-        esc: 1,
+        esc: 1
     };
 
     function textFieldInput() {
@@ -134,7 +134,7 @@
             vk = kh.viewKeys[key],
             kl = fs.isF(kh.viewKeys._keyListener),
             vcb = fs.isF(vk) || (fs.isA(vk) && fs.isF(vk[0])) || fs.isF(kh.viewFn),
-            token = 'keyev'; // indicate this was a key-pressed event
+            token = 'keyev';    // indicate this was a key-pressed event
 
         event.stopPropagation();
 
@@ -185,7 +185,7 @@
                 backSlash: [quickHelp, qhlion_show_hide],
                 slash: [quickHelp, qhlion_show_hide],
                 esc: [escapeKey, qhlion_hint_esc],
-                T: [toggleTheme, qhlion_hint_t],
+                T: [toggleTheme, qhlion_hint_t]
             },
             globalFormat: ['backSlash', 'slash', 'esc', 'T'],
 
@@ -194,8 +194,8 @@
             maskedKeys: {
                 slash: 1,
                 backSlash: 1,
-                T: 1,
-            },
+                T: 1
+            }
         });
     }
 
@@ -244,7 +244,7 @@
     }
 
     function unexParam(fname, x) {
-        $log.warn(fname, ': unexpected parameter-- ', x);
+        $log.warn(fname, ": unexpected parameter-- ", x);
     }
 
     function setKeyBindings(keyArg) {
@@ -273,7 +273,7 @@
             globalKeys: gkeys,
             maskedKeys: masked,
             viewKeys: vkeys,
-            viewFunction: vfn,
+            viewFunction: vfn
         };
     }
 
@@ -318,11 +318,12 @@
 
     angular.module('onosUtil')
     .factory('KeyService',
-        ['$log', 'FnService', 'ThemeService', 'NavService',
+        ['$log', '$timeout', 'FnService', 'ThemeService', 'NavService',
             'EeService', 'LionService',
 
-        function (_$log_, _fs_, _ts_, _ns_, _ee_, _ls_) {
+        function (_$log_, _$timeout_, _fs_, _ts_, _ns_, _ee_, _ls_) {
             $log = _$log_;
+            $timeout = _$timeout_;
             fs = _fs_;
             ts = _ts_;
             ns = _ns_;
@@ -371,7 +372,7 @@
                 enableGlobalKeys: function (b) {
                     globalEnabled = b;
                 },
-                checkNotGlobal: checkNotGlobal,
+                checkNotGlobal: checkNotGlobal
             };
     }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/util/lion.js b/web/gui/src/main/webapp/app/fw/util/lion.js
index f1dd5ef..ec3531b 100644
--- a/web/gui/src/main/webapp/app/fw/util/lion.js
+++ b/web/gui/src/main/webapp/app/fw/util/lion.js
@@ -22,11 +22,11 @@
     'use strict';
 
     // injected services
-    var $log, wss;
+    var $log, fs, wss;
 
     // private state
     var handlers = {
-            uberlion: uberlion,
+            uberlion: uberlion
         },
         ubercache = {};
 
@@ -65,15 +65,16 @@
     }
 
     angular.module('onosUtil')
-        .factory('LionService', ['$log', 'WebSocketService',
+        .factory('LionService', ['$log', 'FnService', 'WebSocketService',
 
-        function (_$log_, _wss_) {
+        function (_$log_, _fs_, _wss_) {
             $log = _$log_;
+            fs = _fs_;
             wss = _wss_;
 
             return {
                 init: init,
-                bundle: bundle,
+                bundle: bundle
             };
         }]);
 }());
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 59a9929..1cf590b 100644
--- a/web/gui/src/main/webapp/app/fw/util/prefs.js
+++ b/web/gui/src/main/webapp/app/fw/util/prefs.js
@@ -21,10 +21,10 @@
     'use strict';
 
     // injected refs
-    var fs, wss;
+    var $log, fs, wss;
 
     // internal state
-    var cache = {},
+    var cache = {}, 
         listeners = [];
 
     // returns the preference settings for the specified key
@@ -98,25 +98,26 @@
     }
 
     function removeListener(listener) {
-        listeners = listeners.filter(function (obj) { return obj === listener; });
+        listeners = listeners.filter(function(obj) { return obj === listener; });
     }
 
     angular.module('onosUtil')
-    .factory('PrefsService', ['FnService', 'WebSocketService',
-        function (_fs_, _wss_) {
+    .factory('PrefsService', ['$log', 'FnService', 'WebSocketService',
+        function (_$log_, _fs_, _wss_) {
+            $log = _$log_;
             fs = _fs_;
             wss = _wss_;
 
             try {
                 cache = angular.isDefined(userPrefs) ? userPrefs : {};
             }
-            catch (e) {
+            catch(e){
                 // browser throws error for non-existing globals
-                cache = {};
+                cache = {}
             }
 
             wss.bindHandlers({
-                updatePrefs: updatePrefs,
+                updatePrefs: updatePrefs
             });
 
             return {
@@ -125,7 +126,7 @@
                 setPrefs: setPrefs,
                 mergePrefs: mergePrefs,
                 addListener: addListener,
-                removeListener: removeListener,
+                removeListener: removeListener
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/util/random.js b/web/gui/src/main/webapp/app/fw/util/random.js
index a4ed03b..92ec5f9 100644
--- a/web/gui/src/main/webapp/app/fw/util/random.js
+++ b/web/gui/src/main/webapp/app/fw/util/random.js
@@ -20,6 +20,8 @@
 (function () {
     'use strict';
 
+    var $log, fs;
+
     var halfRoot2 = 0.7071;
 
     // given some value, s, returns an integer between -s/2 and s/2
@@ -37,10 +39,13 @@
     angular.module('onosUtil')
         .factory('RandomService', ['$log', 'FnService',
 
-        function () {
+        function (_$log_, _fs_) {
+            $log = _$log_;
+            fs = _fs_;
+
             return {
                 spread: spread,
-                randDim: randDim,
+                randDim: randDim
             };
         }]);
 }());
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 b498458..42b5704 100644
--- a/web/gui/src/main/webapp/app/fw/util/theme.js
+++ b/web/gui/src/main/webapp/app/fw/util/theme.js
@@ -21,7 +21,7 @@
     'use strict';
 
     // injected refs
-    var $log, ps;
+    var $log, fs, ps;
 
     // configuration
     var themes = ['light', 'dark'],
@@ -36,33 +36,33 @@
         gray1: {
             fill: {
                 light: '#eeeeee',
-                dark: '#222222',
+                dark: '#222222'
             },
             stroke: {
                 light: '#cccccc',
-                dark: '#333333',
-            },
+                dark: '#333333'
+            }
         },
         gold1: {
             fill: {
                 light: '#eeddaa',
-                dark: '#544714',
+                dark: '#544714'
             },
             stroke: {
                 light: '#ffddaa',
-                dark: '#645724',
-            },
+                dark: '#645724'
+            }
         },
         blue1: {
             fill: {
                 light: '#a2b9ee',
-                dark: '#273059',
+                dark: '#273059'
             },
             stroke: {
                 light: '#92a9de',
-                dark: '#273a63',
-            },
-        },
+                dark: '#273a63'
+            }
+        }
     };
 
     function init() {
@@ -109,8 +109,8 @@
             m = 'Theme-Change-(' + w + '): ' + t;
         $log.debug(m);
 
-        listeners.forEach(function (lsnr) {
-            lsnr({ event: 'themeChange', value: t });
+        listeners.forEach(function (lsnr) { 
+            lsnr({event: 'themeChange', value: t}); 
         });
     }
 
@@ -119,7 +119,7 @@
     }
 
     function removeListener(lsnr) {
-        listeners = listeners.filter(function (obj) { return obj !== lsnr; });
+        listeners = listeners.filter(function(obj) { return obj !== lsnr; });
     }
 
     // color = logical color name
@@ -133,9 +133,10 @@
     }
 
     angular.module('onosUtil')
-        .factory('ThemeService', ['$log', 'PrefsService',
-        function (_$log_, _ps_) {
+        .factory('ThemeService', ['$log', 'FnService', 'PrefsService',
+        function (_$log_, _fs_, _ps_) {
             $log = _$log_;
+            fs = _fs_;
             ps = _ps_;
 
             ps.addListener(applyTheme);
@@ -152,7 +153,7 @@
                 toggleTheme: toggleTheme,
                 addListener: addListener,
                 removeListener: removeListener,
-                spriteColor: spriteColor,
+                spriteColor: spriteColor
             };
     }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/widget/button.js b/web/gui/src/main/webapp/app/fw/widget/button.js
index c0cf8ae..589b370 100644
--- a/web/gui/src/main/webapp/app/fw/widget/button.js
+++ b/web/gui/src/main/webapp/app/fw/widget/button.js
@@ -69,8 +69,8 @@
 
         return {
             id: id,
-            width: buttonWidth,
-        };
+            width: buttonWidth
+        }
     }
 
 
@@ -111,8 +111,8 @@
             width: buttonWidth,
             selected: function () { return sel; },
             toggle: _toggle,
-            toggleNoCb: toggleNoCb,
-        };
+            toggleNoCb: toggleNoCb
+        }
     }
 
 
@@ -186,7 +186,7 @@
                 el: rbdiv,
                 id: rid,
                 cb: fs.isF(btn.cb) || noop,
-                index: index,
+                index: index
             });
 
             if (btn.key) {
@@ -241,8 +241,8 @@
             width: rsetWidth,
             selected: selected,
             selectedIndex: selectedIndex,
-            size: function () { return rads.length; },
-        };
+            size: function () { return rads.length; }
+        }
     }
 
 
@@ -259,7 +259,7 @@
             return {
                 button: button,
                 toggle: toggle,
-                radioSet: radioSet,
+                radioSet: radioSet
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/widget/chartBuilder.js b/web/gui/src/main/webapp/app/fw/widget/chartBuilder.js
index 7a48563..e2f2959 100644
--- a/web/gui/src/main/webapp/app/fw/widget/chartBuilder.js
+++ b/web/gui/src/main/webapp/app/fw/widget/chartBuilder.js
@@ -24,7 +24,7 @@
     // fs -> FnService
     // wss -> WebSocketService
     // ls -> LoadingService
-    var $log, $interval, fs, wss, ls;
+    var $log, $interval, $timeout, fs, wss, ls;
 
     // constants
     var refreshInterval = 2000;
@@ -129,18 +129,19 @@
 
     angular.module('onosWidget')
         .factory('ChartBuilderService',
-        ['$log', '$interval', 'FnService', 'WebSocketService',
+        ['$log', '$interval', '$timeout', 'FnService', 'WebSocketService',
             'LoadingService',
 
-            function (_$log_, _$interval_, _fs_, _wss_, _ls_) {
+            function (_$log_, _$interval_, _$timeout_, _fs_, _wss_, _ls_) {
                 $log = _$log_;
                 $interval = _$interval_;
+                $timeout = _$timeout_;
                 fs = _fs_;
                 wss = _wss_;
                 ls = _ls_;
 
                 return {
-                    buildChart: buildChart,
+                    buildChart: buildChart
                 };
             }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/widget/listBuilder.js b/web/gui/src/main/webapp/app/fw/widget/listBuilder.js
index 0daa8f1..edc92e9 100644
--- a/web/gui/src/main/webapp/app/fw/widget/listBuilder.js
+++ b/web/gui/src/main/webapp/app/fw/widget/listBuilder.js
@@ -56,7 +56,7 @@
     .factory('ListService', [
         function () {
             return {
-                listProps: listProps,
+                listProps: listProps
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/widget/table.js b/web/gui/src/main/webapp/app/fw/widget/table.js
index 745585f..343f9ba 100644
--- a/web/gui/src/main/webapp/app/fw/widget/table.js
+++ b/web/gui/src/main/webapp/app/fw/widget/table.js
@@ -94,7 +94,7 @@
         s: {
             first: null,
             second: null,
-            touched: null,
+            touched: null
         },
 
         reset: function () {
@@ -132,7 +132,7 @@
                 s2 = s.second;
             api[s1.dir](s1.adiv);
             s2 && api.none(s2.adiv);
-        },
+        }
     };
 
     // Functions for sorting table rows by header
@@ -157,12 +157,12 @@
             firstCol: s1.id,
             firstDir: s1.dir,
             secondCol: id2,
-            secondDir: dir2,
+            secondDir: dir2
         };
     }
 
     angular.module('onosWidget')
-    .directive('onosTableResize', ['$log', '$window', 'FnService', 'MastService',
+    .directive('onosTableResize', ['$log','$window', 'FnService', 'MastService',
 
         function (_$log_, _$window_, _fs_, _mast_) {
         return function (scope, element) {
@@ -175,7 +175,7 @@
                 tableElems = {
                     table: table,
                     thead: table.select('.table-header').select('table'),
-                    tbody: table.select('.table-body').select('table'),
+                    tbody: table.select('.table-body').select('table')
                 },
                 wsz;
 
@@ -185,7 +185,7 @@
             scope.$watchCollection(function () {
                 return {
                     h: $window.innerHeight,
-                    w: $window.innerWidth,
+                    w: $window.innerWidth
                 };
             }, function () {
                 wsz = fs.windowSize(0, 30);
diff --git a/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js b/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js
index 9f1b0ab..b23bfd0 100644
--- a/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js
+++ b/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js
@@ -21,7 +21,7 @@
     'use strict';
 
     // injected refs
-    var $log, $interval, fs, wss, ls;
+    var $log, $interval, $timeout, fs, wss, ls;
 
     // constants
     var refreshInterval = 2000;
@@ -141,18 +141,19 @@
 
     angular.module('onosWidget')
         .factory('TableBuilderService',
-        ['$log', '$interval', 'FnService', 'WebSocketService',
+        ['$log', '$interval', '$timeout', 'FnService', 'WebSocketService',
             'LoadingService',
 
-            function (_$log_, _$interval_, _fs_, _wss_, _ls_) {
+            function (_$log_, _$interval_, _$timeout_, _fs_, _wss_, _ls_) {
                 $log = _$log_;
                 $interval = _$interval_;
+                $timeout = _$timeout_;
                 fs = _fs_;
                 wss = _wss_;
                 ls = _ls_;
 
                 return {
-                    buildTable: buildTable,
+                    buildTable: buildTable
                 };
             }]);
 
diff --git a/web/gui/src/main/webapp/app/fw/widget/tableDetail.js b/web/gui/src/main/webapp/app/fw/widget/tableDetail.js
index 31aac08..57f65a7 100644
--- a/web/gui/src/main/webapp/app/fw/widget/tableDetail.js
+++ b/web/gui/src/main/webapp/app/fw/widget/tableDetail.js
@@ -21,7 +21,7 @@
     'use strict';
 
     // injected refs
-    var $log, fs;
+    var $log, $interval, $timeout, fs, wss;
 
     // constants
     // var refreshInterval = 2000;
@@ -50,14 +50,17 @@
     // TODO: add ref to PanelService
     angular.module('onosWidget')
     .factory('TableDetailService',
-    ['$log', 'FnService',
+    ['$log', '$interval', '$timeout', 'FnService', 'WebSocketService',
 
-    function (_$log_, _fs_) {
+    function (_$log_, _$interval_, _$timeout_, _fs_, _wss_) {
         $log = _$log_;
+        $interval = _$interval_;
+        $timeout = _$timeout_;
         fs = _fs_;
+        wss = _wss_;
 
         return {
-            buildBasePanel: buildBasePanel,
+            buildBasePanel: buildBasePanel
         };
     }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/widget/toolbar.js b/web/gui/src/main/webapp/app/fw/widget/toolbar.js
index 6ac1847..b765208 100644
--- a/web/gui/src/main/webapp/app/fw/widget/toolbar.js
+++ b/web/gui/src/main/webapp/app/fw/widget/toolbar.js
@@ -38,7 +38,7 @@
             top: 'auto',
             bottom: '10px',
             fade: false,
-            shown: false,
+            shown: false
         };
 
     // internal state
@@ -81,8 +81,8 @@
             panel = ps.createPanel(tbid, settings),
             arrowDiv = createArrow(panel),
             currentRow = panel.append('div').classed('tbar-row', true),
-            rowButtonIds = [], // for removable buttons
-            tbWidth = arrowSize + 2, // empty toolbar width
+            rowButtonIds = [],          // for removable buttons
+            tbWidth = arrowSize + 2,    // empty toolbar width
             maxWidth = panel.width();
 
         arrowDiv.on('click', toggle);
@@ -92,7 +92,7 @@
             settings: settings,
             items: items,
             panel: panel,
-            panelId: tbid,
+            panelId: tbid
         };
 
         panel.classed('toolbar', true)
@@ -171,7 +171,7 @@
                     clear: rowClear,
                     setText: rowSetText,
                     addButton: rowAddButton,
-                    classed: rowClassed,
+                    classed: rowClassed
                 };
             }
         }
@@ -234,7 +234,7 @@
             show: show,
             hide: hide,
             toggle: toggle,
-            isVisible: isVisible,
+            isVisible: isVisible
         };
     }
 
@@ -268,7 +268,7 @@
             return {
                 init: init,
                 createToolbar: createToolbar,
-                destroyToolbar: destroyToolbar,
+                destroyToolbar: destroyToolbar
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/fw/widget/tooltip.js b/web/gui/src/main/webapp/app/fw/widget/tooltip.js
index 4d8169c..beca6f8 100644
--- a/web/gui/src/main/webapp/app/fw/widget/tooltip.js
+++ b/web/gui/src/main/webapp/app/fw/widget/tooltip.js
@@ -17,11 +17,12 @@
 /*
  ONOS GUI -- Widget -- Tooltip Service
  */
+
 (function () {
     'use strict';
 
     // injected references
-    var $rootScope, fs;
+    var $log, $rootScope, fs;
 
     // constants
     var hoverHeight = 35,
@@ -44,7 +45,7 @@
             style = {
                 display: 'inline-block',
                 left: 'auto',
-                right: 'auto',
+                right: 'auto'
             };
 
         if (mouseX <= (winWidth / 2)) {
@@ -105,7 +106,7 @@
             tooltip.transition()
                 .delay(exitDelay)
                 .style({
-                    display: 'none',
+                    display: 'none'
                 })
                 .text('');
         }
@@ -124,12 +125,13 @@
                     restrict: 'A',
                     link: function (scope, elem, attrs) {
                         addTooltip(d3.select(elem[0]), scope[attrs.ttMsg]);
-                    },
+                    }
                 };
         }])
 
-        .factory('TooltipService', ['$rootScope', 'FnService',
-            function (_$rootScope_, _fs_) {
+        .factory('TooltipService', ['$log', '$rootScope', 'FnService',
+            function (_$log_, _$rootScope_, _fs_) {
+                $log = _$log_;
                 $rootScope = _$rootScope_;
                 fs = _fs_;
 
@@ -138,7 +140,7 @@
                 return {
                     addTooltip: addTooltip,
                     showTooltip: showTooltip,
-                    cancelTooltip: cancelTooltip,
+                    cancelTooltip: cancelTooltip
                 };
             }]);
 }());
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 a35fc64..5fb55df 100644
--- a/web/gui/src/main/webapp/app/view/app/app.js
+++ b/web/gui/src/main/webapp/app/view/app/app.js
@@ -50,10 +50,10 @@
         dialogId = 'app-dialog',
         dialogOpts = {
             edge: 'right',
-            width: 400,
+            width: 400
         },
         strongWarning = {
-            'org.onosproject.drivers': true,
+            'org.onosproject.drivers': true
         },
         propOrder = ['id', 'state', 'category', 'version', 'origin', 'role'];
         // note: url is handled separately
@@ -72,7 +72,7 @@
 
         friendlyProps = [
             lion('app_id'), lion('state'), lion('category'), lion('version'),
-            lion('origin'), lion('role'),
+            lion('origin'), lion('role')
         ];
     }
 
@@ -80,11 +80,11 @@
         detailsPanel = ps.createPanel(pName, {
             width: wSize.width,
             margin: 0,
-            hideMargin: 0,
+            hideMargin: 0
         });
         detailsPanel.el().style({
             position: 'absolute',
-            top: pStartY + 'px',
+            top: pStartY + 'px'
         });
         $scope.hidePanel = function () { detailsPanel.hide(); };
         detailsPanel.hide();
@@ -119,7 +119,7 @@
         div = top.append('div').classed('top-content', true);
 
         function ndiv(cls, tcls) {
-            var d = div.append('div').classed(cls, true);
+            var  d = div.append('div').classed(cls, true);
             if (tcls) {
                 d.append('table').classed(tcls, true);
             }
@@ -262,7 +262,7 @@
             // $scope.selId is set by code in tableBuilder
             $scope.ctrlBtnState.selection = !!$scope.selId;
             refreshCtrls();
-            ds.closeDialog(); // don't want dialog from previous selection
+            ds.closeDialog();  // don't want dialog from previous selection
 
             if ($scope.selId) {
                 wss.sendEvent(detailsReq, { id: row.id });
@@ -295,18 +295,18 @@
                 firstCol: 'state',
                 firstDir: 'desc',
                 secondCol: 'title',
-                secondDir: 'asc',
+                secondDir: 'asc'
             },
-            lion_toggle_auto_refresh: lion('tt_ctl_auto_refresh'),
+            lion_toggle_auto_refresh: lion('tt_ctl_auto_refresh')
         });
 
         ks.keyBindings({
             esc: [$scope.selectCallback, lion('qh_hint_esc')],
-            _helpFormat: ['esc'],
+            _helpFormat: ['esc']
         });
         ks.gestureNotes([
             [lion('click_row'), lion('qh_hint_click_row')],
-            [lion('scroll_down'), lion('qh_hint_scroll_down')],
+            [lion('scroll_down'), lion('qh_hint_scroll_down')]
         ]);
 
         function createConfirmationText(action, itemId) {
@@ -332,12 +332,12 @@
                     action: action,
                     name: itemId,
                     sortCol: spar.sortCol,
-                    sortDir: spar.sortDir,
+                    sortDir: spar.sortDir
                 });
                 if (action === 'uninstall') {
                     detailsPanel.hide();
                 } else {
-                    wss.sendEvent(detailsReq, { id: itemId });
+                    wss.sendEvent(detailsReq, {id: itemId});
                 }
             }
 
@@ -370,8 +370,8 @@
                 $http.post(ufs.rsUrl(url), formData, {
                     transformRequest: angular.identity,
                     headers: {
-                        'Content-Type': undefined,
-                    },
+                        'Content-Type': undefined
+                    }
                 })
                 .finally(function () {
                     activateImmediately = '';
@@ -382,7 +382,7 @@
             }
         });
 
-        $scope.appDropped = function () {
+        $scope.appDropped = function() {
             activateImmediately = activateOption;
             $scope.$emit('FileChanged');
             $scope.appFile = null;
@@ -406,7 +406,7 @@
                     document.getElementById('uploadFile')
                         .dispatchEvent(new MouseEvent('click'));
                 });
-            },
+            }
         };
     })
 
@@ -426,13 +426,13 @@
                         });
                         scope.$emit('FileChanged');
                     });
-                },
+                }
             };
         }])
 
-    .directive('filedrop', ['$parse', '$document', function ($parse, $document) {
+    .directive("filedrop", ['$parse', '$document', function ($parse, $document) {
         return {
-            restrict: 'A',
+            restrict: "A",
             link: function (scope, element, attrs) {
                 var onAppDrop = $parse(attrs.onFileDrop);
 
@@ -455,16 +455,16 @@
                 };
 
                 // Dragging begins on the document
-                $document.bind('dragover', onDragOver);
+                $document.bind("dragover", onDragOver);
 
                 // Dragging ends on the overlay, which takes the whole window
-                element.bind('dragleave', onDragEnd)
-                    .bind('drop', function (e) {
+                element.bind("dragleave", onDragEnd)
+                    .bind("drop", function (e) {
                         $log.info('Drag leave', e);
                         loadFile(e.dataTransfer.files[0]);
                         onDragEnd(e);
                     });
-            },
+            }
         };
     }])
 
@@ -497,13 +497,13 @@
                 // create key bindings to handle panel
                 ks.keyBindings({
                     esc: [closePanel, lion('qh_hint_close_detail')],
-                    _helpFormat: ['esc'],
+                    _helpFormat: ['esc']
                 });
 
                 // TODO: Review - why are we doing this in the detail panel...?
                 ks.gestureNotes([
                     [lion('click_row'), lion('qh_hint_click_row')],
-                    [lion('scroll_down'), lion('qh_hint_scroll_down')],
+                    [lion('scroll_down'), lion('qh_hint_scroll_down')]
                 ]);
 
                 // if the panelData changes
@@ -519,7 +519,7 @@
                     function () {
                         return {
                             h: $window.innerHeight,
-                            w: $window.innerWidth,
+                            w: $window.innerWidth
                         };
                     }, function () {
                         if (!fs.isEmptyObject(scope.panelData)) {
diff --git a/web/gui/src/main/webapp/app/view/cluster/cluster.js b/web/gui/src/main/webapp/app/view/cluster/cluster.js
index 31a4f05..89cb8a2 100644
--- a/web/gui/src/main/webapp/app/view/cluster/cluster.js
+++ b/web/gui/src/main/webapp/app/view/cluster/cluster.js
@@ -22,7 +22,7 @@
     'use strict';
 
     // injected references
-    var $log, $scope, fs, mast, ps, is, wss;
+    var $log, $scope, fs, ns, mast, ps, is, wss;
 
     // internal state
     var detailsPanel,
@@ -44,11 +44,11 @@
         detailsReq = 'clusterDetailsRequest',
         detailsResp = 'clusterDetailsResponse',
         propOrder = [
-            'id', 'ip',
+            'id', 'ip'
         ],
         deviceCols = [
             'id', 'type', 'chassisid', 'mfr',
-            'hw', 'sw', 'protocol', 'serial',
+            'hw', 'sw', 'protocol', 'serial'
         ];
 
     // deferred fetching of user-visible strings, so that lion context is set
@@ -56,7 +56,7 @@
         var l = $scope.lion;
         return [
             l('node_id'),
-            l('ip_address'),
+            l('ip_address')
         ];
     }
 
@@ -70,7 +70,7 @@
             l('hw_version'),
             l('sw_version'),
             l('protocol'),
-            l('serial_number'),
+            l('serial_number')
         ];
     }
 
@@ -110,7 +110,7 @@
         bottom = container.append('div').classed('bottom', true);
         bottom.append('h2').classed('devices-title', true).text('Devices');
         bottom.append('table');
-        // TODO: add more details
+        //TODO: add more details
     }
 
     function addProp(tbody, label, value) {
@@ -169,7 +169,7 @@
             height: tbHeight + 'px',
             width: tbWidth + 'px',
             overflow: 'auto',
-            display: 'block',
+            display: 'block'
         });
 
         detailsPanel.width(tbWidth + ctnrPdg);
@@ -179,11 +179,11 @@
         detailsPanel = ps.createPanel(pName, {
             width: wSize.width,
             margin: 0,
-            hideMargin: 0,
+            hideMargin: 0
         });
         detailsPanel.el().style({
             position: 'absolute',
-            top: pStartY + 'px',
+            top: pStartY + 'px'
         });
         $scope.hidePanel = function () { detailsPanel.hide(); };
         detailsPanel.hide();
@@ -205,16 +205,17 @@
 
     angular.module('ovCluster', [])
         .controller('OvClusterCtrl',
-        ['$log', '$scope', 'FnService', 'MastService',
-        'PanelService', 'IconService', 'WebSocketService',
+        ['$log', '$scope', 'FnService', 'NavService', 'MastService',
+        'PanelService', 'IconService','WebSocketService',
         'LionService', 'TableBuilderService',
 
-    function (_$log_, _$scope_, _fs_, _mast_, _ps_, _is_, _wss_, lion, tbs) {
+    function (_$log_, _$scope_, _fs_, _ns_, _mast_, _ps_, _is_, _wss_, lion, tbs) {
             var handlers = {};
 
             $log = _$log_;
             $scope = _$scope_;
             fs = _fs_;
+            ns = _ns_;
             mast = _mast_;
             ps = _ps_;
             is = _is_;
@@ -226,7 +227,7 @@
             tbs.buildTable({
                 scope: $scope,
                 selCb: selCb,
-                tag: 'cluster',
+                tag: 'cluster'
             });
 
         // details panel handlers
@@ -235,7 +236,7 @@
 
         function selCb($event, row) {
             if ($scope.selId) {
-                wss.sendEvent(detailsReq, { id: row.id });
+                wss.sendEvent(detailsReq, {id: row.id});
             } else {
                 $scope.hidePanel();
             }
@@ -278,11 +279,11 @@
             // create key bindings to handle panel
             ks.keyBindings({
                 esc: [handleEscape, lion('qh_hint_close_detail')],
-                _helpFormat: ['esc'],
+                _helpFormat: ['esc']
             });
             ks.gestureNotes([
                 [lion('click'), lion('qh_hint_click')],
-                [lion('scroll_down'), lion('qh_hint_scroll_down')],
+                [lion('scroll_down'), lion('qh_hint_scroll_down')]
             ]);
             // if the panelData changes
             scope.$watch('panelData', function () {
@@ -297,7 +298,7 @@
                 function () {
                     return {
                         h: $window.innerHeight,
-                        w: $window.innerWidth,
+                        w: $window.innerWidth
                     };
                 }, function () {
                     if (!fs.isEmptyObject(scope.panelData)) {
diff --git a/web/gui/src/main/webapp/app/view/device/device.js b/web/gui/src/main/webapp/app/view/device/device.js
index 5e28158..f7ec45b 100644
--- a/web/gui/src/main/webapp/app/view/device/device.js
+++ b/web/gui/src/main/webapp/app/view/device/device.js
@@ -46,15 +46,21 @@
         detailsResp = 'deviceDetailsResponse',
         nameChangeReq = 'deviceNameChangeRequest',
         nameChangeResp = 'deviceNameChangeResponse',
+
+        propSplit = 4,
+        propOrder = [
+            'id', 'type', 'masterid', 'chassisid',
+            'mfr', 'hw', 'sw', 'protocol', 'serial'
+        ],
         friendlyProps = [
             'URI', 'Type', 'Master ID', 'Chassis ID',
-            'Vendor', 'H/W Version', 'S/W Version', 'Protocol', 'Serial #',
+            'Vendor', 'H/W Version', 'S/W Version', 'Protocol', 'Serial #'
         ],
         portCols = [
-            'enabled', 'id', 'speed', 'type', 'elinks_dest', 'name',
+            'enabled', 'id', 'speed', 'type', 'elinks_dest', 'name'
         ],
         friendlyPortCols = [
-            'Enabled', 'ID', 'Speed', 'Type', 'Egress Links', 'Name',
+            'Enabled', 'ID', 'Speed', 'Type', 'Egress Links', 'Name'
         ];
 
     function closePanel() {
@@ -169,15 +175,20 @@
         top.select('h2').text(details.name);
 
         // === demonstrate use of JsonCodec object see ONOS-5976
-        addProp(leftTbl, 0, device.id);
-        addProp(leftTbl, 1, device.type);
-        addProp(leftTbl, 2, details['masterid']);
-        addProp(leftTbl, 3, details['chassid']);
+        addProp(leftTbl,  0, device.id);
+        addProp(leftTbl,  1, device.type);
+        addProp(leftTbl,  2, details['masterid']);
+        addProp(leftTbl,  3, details['chassid']);
         addProp(rightTbl, 4, device.mfr);
         addProp(rightTbl, 5, device.hw);
         addProp(rightTbl, 6, device.sw);
         addProp(rightTbl, 7, details['protocol']);
         addProp(rightTbl, 8, device.serial);
+
+        // propOrder.forEach(function (prop, i) {
+        //     // properties are split into two tables
+        //     addProp(i < propSplit ? leftTbl : rightTbl, i, details[prop]);
+        // });
     }
 
     function addPortRow(tbody, port) {
@@ -212,7 +223,7 @@
             height: tbHeight + 'px',
             width: tbWidth + 'px',
             overflow: 'auto',
-            display: 'block',
+            display: 'block'
         });
 
         detailsPanel.width(tbWidth + ctnrPdg);
@@ -250,11 +261,11 @@
         detailsPanel = ps.createPanel(pName, {
             width: wSize.width,
             margin: 0,
-            hideMargin: 0,
+            hideMargin: 0
         });
         detailsPanel.el().style({
             position: 'absolute',
-            top: pStartY + 'px',
+            top: pStartY + 'px'
         });
         $scope.hidePanel = function () { detailsPanel.hide(); };
         detailsPanel.hide();
@@ -328,7 +339,7 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'device',
-                selCb: selCb,
+                selCb: selCb
             });
 
 
@@ -336,7 +347,7 @@
             // TODO: more than just an example
             tds.buildBasePanel({
                 popTop: popTop,
-                popMid: popMid,
+                popMid: popMid
             });
             // ==================== for testing for now ===============
 
@@ -383,11 +394,11 @@
             ks.keyBindings({
                 enter: editNameSave,
                 esc: [handleEscape, 'Close the details panel'],
-                _helpFormat: ['esc'],
+                _helpFormat: ['esc']
             });
             ks.gestureNotes([
                 ['click', 'Select a row to show device details'],
-                ['scroll down', 'See more devices'],
+                ['scroll down', 'See more devices']
             ]);
 
             // if the panelData changes
@@ -403,7 +414,7 @@
                 function () {
                     return {
                         h: $window.innerHeight,
-                        w: $window.innerWidth,
+                        w: $window.innerWidth
                     };
                 }, function () {
                     if (!fs.isEmptyObject(scope.panelData)) {
diff --git a/web/gui/src/main/webapp/app/view/flow/flow.js b/web/gui/src/main/webapp/app/view/flow/flow.js
index 1dd6a72..0e1cdd5 100644
--- a/web/gui/src/main/webapp/app/view/flow/flow.js
+++ b/web/gui/src/main/webapp/app/view/flow/flow.js
@@ -67,7 +67,7 @@
 
             'groupId',
             'timeout',
-            'permanent',
+            'permanent'
         ],
         friendlyProps = [
             'Flow ID',
@@ -84,7 +84,7 @@
 
             'Group ID',
             'Timeout',
-            'Permanent',
+            'Permanent'
         ];
 
     function closePanel() {
@@ -202,11 +202,11 @@
         detailsPanel = ps.createPanel(pName, {
             width: wSize.width,
             margin: 0,
-            hideMargin: 0,
+            hideMargin: 0
         });
         detailsPanel.el().style({
             position: 'absolute',
-            top: pStartY + 'px',
+            top: pStartY + 'px'
         });
         $scope.hidePanel = function () { detailsPanel.hide(); };
         detailsPanel.hide();
@@ -216,157 +216,157 @@
         setUpPanel();
         populateTop(details);
 
-        // ToDo add more details
+        //ToDo add more details
         detailsPanel.height(pHeight);
         detailsPanel.width(wtPdg);
     }
 
     function respDetailsCb(data) {
-        $log.debug('Got response from server :', data);
+        $log.debug("Got response from server :", data);
         $scope.panelData = data.details;
         $scope.$apply();
     }
 
     angular.module('ovFlow', [])
-        .controller('OvFlowCtrl',
-            ['$log', '$scope', '$location',
-                'FnService', 'TableBuilderService', 'NavService',
-                'MastService', 'PanelService', 'KeyService', 'IconService',
-                'WebSocketService',
+    .controller('OvFlowCtrl',
+        ['$log', '$scope', '$location',
+            'FnService', 'TableBuilderService', 'NavService',
+            'MastService', 'PanelService', 'KeyService', 'IconService',
+            'WebSocketService',
 
-                function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _ns_,
-                          _mast_, _ps_, _ks_, _is_, _wss_) {
-                    var params,
-                        handlers = {};
+        function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _ns_,
+                    _mast_, _ps_, _ks_, _is_, _wss_) {
+            var params,
+                handlers = {};
 
-                    $log = _$log_;
-                    $scope = _$scope_;
-                    $location = _$location_;
-                    fs = _fs_;
-                    tbs = _tbs_;
-                    ns = _ns_;
-                    is = _is_;
-                    wss = _wss_;
-                    mast = _mast_;
-                    ps = _ps_;
-                    $scope.deviceTip = 'Show device table';
-                    $scope.portTip = 'Show port view for this device';
-                    $scope.groupTip = 'Show group view for this device';
-                    $scope.meterTip = 'Show meter view for selected device';
-                    $scope.briefTip = 'Switch to brief view';
-                    $scope.detailTip = 'Switch to detailed view';
-                    $scope.brief = true;
-                    params = $location.search();
-                    if (params.hasOwnProperty('devId')) {
-                        $scope.devId = params['devId'];
+            $log = _$log_;
+            $scope = _$scope_;
+            $location = _$location_;
+            fs = _fs_;
+            tbs = _tbs_;
+            ns = _ns_;
+            is = _is_;
+            wss = _wss_;
+            mast = _mast_;
+            ps = _ps_;
+            $scope.deviceTip = 'Show device table';
+            $scope.portTip = 'Show port view for this device';
+            $scope.groupTip = 'Show group view for this device';
+            $scope.meterTip = 'Show meter view for selected device';
+            $scope.briefTip = 'Switch to brief view';
+            $scope.detailTip = 'Switch to detailed view';
+            $scope.brief = true;
+            params = $location.search();
+            if (params.hasOwnProperty('devId')) {
+                $scope.devId = params['devId'];
+            }
+
+            tbs.buildTable({
+                scope: $scope,
+                tag: 'flow',
+                selCb: selCb,
+                query: params
+            });
+
+            $scope.nav = function (path) {
+                if ($scope.devId) {
+                    ns.navTo(path, { devId: $scope.devId });
+                }
+            };
+
+            // details panel handlers
+            handlers[detailsResp] = respDetailsCb;
+            wss.bindHandlers(handlers);
+
+            function selCb($event, row) {
+                if ($scope.selId) {
+                    wss.sendEvent(detailsReq, {flowId: row.id, appId: row.appId});
+                } else {
+                    $scope.hidePanel();
+                }
+                $log.debug('Got a click on:', row);
+            }
+
+             $scope.$on('$destroy', function () {
+                 wss.unbindHandlers(handlers);
+             });
+
+            $scope.briefToggle = function () {
+                $scope.brief = !$scope.brief;
+            };
+
+            Object.defineProperty($scope, "queryFilter", {
+               get: function() {
+                   var out = {};
+                   out[$scope.queryBy || "$"] = $scope.queryTxt;
+                   return out;
+               }
+            });
+
+            $log.log('OvFlowCtrl has been created');
+        }])
+
+    .directive('flowDetailsPanel',
+    ['$rootScope', '$window', '$timeout', 'KeyService',
+    function ($rootScope, $window, $timeout, ks) {
+        return function (scope) {
+            var unbindWatch;
+
+            function heightCalc() {
+                pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
+                                        + mast.mastHeight() + topPdg;
+                wSize = fs.windowSize(pStartY);
+                pHeight = wSize.height;
+            }
+
+            function initPanel() {
+                heightCalc();
+                createDetailsPane();
+            }
+
+            // Safari has a bug where it renders the fixed-layout table wrong
+            // if you ask for the window's size too early
+            if (scope.onos.browser === 'safari') {
+                $timeout(initPanel);
+            } else {
+                initPanel();
+            }
+            // create key bindings to handle panel
+            ks.keyBindings({
+                esc: [handleEscape, 'Close the details panel'],
+                _helpFormat: ['esc']
+            });
+            ks.gestureNotes([
+                ['click', 'Select a row to show cluster node details'],
+                ['scroll down', 'See available cluster nodes']
+            ]);
+            // if the panelData changes
+            scope.$watch('panelData', function () {
+                if (!fs.isEmptyObject(scope.panelData)) {
+                    populateDetails(scope.panelData);
+                    detailsPanel.show();
+                }
+            });
+            // if the window size changes
+            unbindWatch = $rootScope.$watchCollection(
+                function () {
+                    return {
+                        h: $window.innerHeight,
+                        w: $window.innerWidth
+                    };
+                }, function () {
+                    if (!fs.isEmptyObject(scope.panelData)) {
+                        heightCalc();
+                        populateDetails(scope.panelData);
                     }
+                }
+            );
 
-                    tbs.buildTable({
-                        scope: $scope,
-                        tag: 'flow',
-                        selCb: selCb,
-                        query: params,
-                    });
-
-                    $scope.nav = function (path) {
-                        if ($scope.devId) {
-                            ns.navTo(path, { devId: $scope.devId });
-                        }
-                    };
-
-                    // details panel handlers
-                    handlers[detailsResp] = respDetailsCb;
-                    wss.bindHandlers(handlers);
-
-                    function selCb($event, row) {
-                        if ($scope.selId) {
-                            wss.sendEvent(detailsReq, { flowId: row.id, appId: row.appId });
-                        } else {
-                            $scope.hidePanel();
-                        }
-                        $log.debug('Got a click on:', row);
-                    }
-
-                    $scope.$on('$destroy', function () {
-                        wss.unbindHandlers(handlers);
-                    });
-
-                    $scope.briefToggle = function () {
-                        $scope.brief = !$scope.brief;
-                    };
-
-                    Object.defineProperty($scope, 'queryFilter', {
-                        get: function () {
-                            var out = {};
-                            out[$scope.queryBy || '$'] = $scope.queryTxt;
-                            return out;
-                        },
-                    });
-
-                    $log.log('OvFlowCtrl has been created');
-                }])
-
-        .directive('flowDetailsPanel',
-            ['$rootScope', '$window', '$timeout', 'KeyService',
-                function ($rootScope, $window, $timeout, ks) {
-                    return function (scope) {
-                        var unbindWatch;
-
-                        function heightCalc() {
-                            pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
-                                + mast.mastHeight() + topPdg;
-                            wSize = fs.windowSize(pStartY);
-                            pHeight = wSize.height;
-                        }
-
-                        function initPanel() {
-                            heightCalc();
-                            createDetailsPane();
-                        }
-
-                        // Safari has a bug where it renders the fixed-layout table wrong
-                        // if you ask for the window's size too early
-                        if (scope.onos.browser === 'safari') {
-                            $timeout(initPanel);
-                        } else {
-                            initPanel();
-                        }
-                        // create key bindings to handle panel
-                        ks.keyBindings({
-                            esc: [handleEscape, 'Close the details panel'],
-                            _helpFormat: ['esc'],
-                        });
-                        ks.gestureNotes([
-                            ['click', 'Select a row to show cluster node details'],
-                            ['scroll down', 'See available cluster nodes'],
-                        ]);
-                        // if the panelData changes
-                        scope.$watch('panelData', function () {
-                            if (!fs.isEmptyObject(scope.panelData)) {
-                                populateDetails(scope.panelData);
-                                detailsPanel.show();
-                            }
-                        });
-                        // if the window size changes
-                        unbindWatch = $rootScope.$watchCollection(
-                            function () {
-                                return {
-                                    h: $window.innerHeight,
-                                    w: $window.innerWidth,
-                                };
-                            }, function () {
-                                if (!fs.isEmptyObject(scope.panelData)) {
-                                    heightCalc();
-                                    populateDetails(scope.panelData);
-                                }
-                            }
-                        );
-
-                        scope.$on('$destroy', function () {
-                            unbindWatch();
-                            ps.destroyPanel(pName);
-                        });
-                    };
-                }]);
+            scope.$on('$destroy', function () {
+                unbindWatch();
+                ps.destroyPanel(pName);
+            });
+        };
+    }]);
 
 }());
diff --git a/web/gui/src/main/webapp/app/view/group/group.js b/web/gui/src/main/webapp/app/view/group/group.js
index 5190360..50a97c5 100644
--- a/web/gui/src/main/webapp/app/view/group/group.js
+++ b/web/gui/src/main/webapp/app/view/group/group.js
@@ -52,7 +52,7 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'group',
-                query: params,
+                query: params
             });
 
             $scope.$watch('tableData', function () {
@@ -72,12 +72,12 @@
                 $scope.brief = !$scope.brief;
             };
 
-            Object.defineProperty($scope, 'queryFilter', {
-                get: function () {
+            Object.defineProperty($scope, "queryFilter", {
+                get: function() {
                     var out = {};
-                    out[$scope.queryBy || '$'] = $scope.query;
+                    out[$scope.queryBy || "$"] = $scope.query;
                     return out;
-                },
+                }
             });
 
 
diff --git a/web/gui/src/main/webapp/app/view/host/host.js b/web/gui/src/main/webapp/app/view/host/host.js
index 7ccb243..4e8153c 100644
--- a/web/gui/src/main/webapp/app/view/host/host.js
+++ b/web/gui/src/main/webapp/app/view/host/host.js
@@ -31,7 +31,8 @@
         top,
         iconDiv,
         wSize,
-        editingName = false;
+        editingName = false,
+        host;
 
     // constants
     var topPdg = 28,
@@ -42,11 +43,11 @@
         nameChangeResp = 'hostNameChangeResponse';
 
     var propOrder = [
-            'id', 'ip', 'mac', 'vlan', 'configured', 'location',
+            'id', 'ip', 'mac', 'vlan', 'configured', 'location'
         ],
         friendlyProps = [
             'Host ID', 'IP Address', 'MAC Address', 'VLAN',
-            'Configured', 'Location',
+            'Configured', 'Location'
         ];
 
     function closePanel() {
@@ -164,6 +165,7 @@
 
     function respDetailsCb(data) {
         $scope.panelData = data.details;
+        host = data.host;
         $scope.$apply();
     }
 
@@ -178,11 +180,11 @@
         detailsPanel = ps.createPanel(pName, {
             width: wSize.width,
             margin: 0,
-            hideMargin: 0,
+            hideMargin: 0
         });
         detailsPanel.el().style({
             position: 'absolute',
-            top: pStartY + 'px',
+            top: pStartY + 'px'
         });
         $scope.hidePanel = function () { detailsPanel.hide(); };
         detailsPanel.hide();
@@ -244,7 +246,7 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'host',
-                selCb: selCb,
+                selCb: selCb
             });
 
             $scope.nav = function (path) {
@@ -289,11 +291,11 @@
             ks.keyBindings({
                 enter: editNameSave,
                 esc: [handleEscape, 'Close the details panel'],
-                _helpFormat: ['esc'],
+                _helpFormat: ['esc']
             });
             ks.gestureNotes([
                 ['click', 'Select a row to show device details'],
-                ['scroll down', 'See more devices'],
+                ['scroll down', 'See more devices']
             ]);
 
             // if the panelData changes
@@ -309,7 +311,7 @@
                 function () {
                     return {
                         h: $window.innerHeight,
-                        w: $window.innerWidth,
+                        w: $window.innerWidth
                     };
                 }, function () {
                     if (!fs.isEmptyObject(scope.panelData)) {
diff --git a/web/gui/src/main/webapp/app/view/intent/intent.js b/web/gui/src/main/webapp/app/view/intent/intent.js
index afd29b9..9567119 100644
--- a/web/gui/src/main/webapp/app/view/intent/intent.js
+++ b/web/gui/src/main/webapp/app/view/intent/intent.js
@@ -24,7 +24,7 @@
     // constants and configuration
     var dialogId = 'remove-intent-dialog',
         dialogOpts = {
-            edge: 'right',
+            edge: 'right'
         };
 
     // DOM elements
@@ -61,7 +61,7 @@
                 appId: id,
                 appName: name,
                 key: row.key,
-                intentType: row.type,
+                intentType: row.type
             } : null;
 
         $scope.intentState = row.state;
@@ -84,7 +84,7 @@
         dropdown.style('display', b ? 'block' : 'none');
     }
 
-    function showIntent() {
+    function showIntent () {
         var d = $scope.intentData,
             handlers,
             nh;
@@ -163,7 +163,7 @@
             // set up scope function references...
             $scope.showIntent = showIntent;
 
-            $scope.canShowIntent = function () {
+            $scope.canShowIntent = function() {
                 var d = $scope.intentData;
                 return d && tov.overlaysAcceptingIntents(d.intentType).length > 0;
             };
@@ -174,7 +174,7 @@
                 tag: 'intent',
                 selCb: selCb,
                 respCb: respCb,
-                idKey: 'key',
+                idKey: 'key'
             });
 
 
@@ -200,6 +200,7 @@
 
             function executeAction(action) {
                 var content = ds.createDiv(),
+                    txt,
                     bPurge = action === 'purge';
 
                 $scope.intentData.intentPurge = bPurge;
@@ -230,10 +231,10 @@
             }
 
             function executeActions(action) {
-                 var content = ds.createDiv();
-
-                 content.append('p')
-                    .text('Are you sure you want to purge all the withdrawn intents?');
+                 var content = ds.createDiv(),
+                     txt='purgeIntents';
+                     content.append('p').
+                     text('Are you sure you want to purge all the withdrawn intents?');
 
                  function dOk() {
                      tts.removeIntents();
@@ -254,15 +255,15 @@
             }
 
             $scope.deactivateIntent = function () {
-                executeAction('withdraw');
+                executeAction("withdraw");
             };
 
             $scope.resubmitIntent = function () {
-                executeAction('resubmit');
+                executeAction("resubmit");
             };
 
             $scope.purgeIntent = function () {
-                executeAction('purge');
+                executeAction("purge");
             };
 
             $scope.briefToggle = function () {
@@ -275,9 +276,8 @@
             });
 
             $scope.purgeIntents = function () {
-                executeActions('purgeIntents');
+                executeActions("purgeIntents");
             };
-
             $log.debug('OvIntentCtrl has been created');
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/link/link.js b/web/gui/src/main/webapp/app/view/link/link.js
index 558aeb9..30d485c 100644
--- a/web/gui/src/main/webapp/app/view/link/link.js
+++ b/web/gui/src/main/webapp/app/view/link/link.js
@@ -28,7 +28,7 @@
         function ($log, $scope, $sce, fs, tbs) {
             tbs.buildTable({
                 scope: $scope,
-                tag: 'link',
+                tag: 'link'
             });
 
             $scope.$watch('tableData', function () {
diff --git a/web/gui/src/main/webapp/app/view/meter/meter.js b/web/gui/src/main/webapp/app/view/meter/meter.js
index 8fabbb0..0635650 100644
--- a/web/gui/src/main/webapp/app/view/meter/meter.js
+++ b/web/gui/src/main/webapp/app/view/meter/meter.js
@@ -49,7 +49,7 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'meter',
-                query: params,
+                query: params
             });
 
             $scope.$watch('tableData', function () {
@@ -66,12 +66,12 @@
                 }
             };
 
-            Object.defineProperty($scope, 'queryFilter', {
-                get: function () {
+            Object.defineProperty($scope, "queryFilter", {
+                get: function() {
                     var out = {};
-                    out[$scope.queryBy || '$'] = $scope.query;
+                    out[$scope.queryBy || "$"] = $scope.query;
                     return out;
-                },
+                }
             });
 
 
diff --git a/web/gui/src/main/webapp/app/view/partition/partition.js b/web/gui/src/main/webapp/app/view/partition/partition.js
index fc2194d..11c9a85 100644
--- a/web/gui/src/main/webapp/app/view/partition/partition.js
+++ b/web/gui/src/main/webapp/app/view/partition/partition.js
@@ -28,7 +28,7 @@
                 function ($log, $scope, $sce, fs, tbs) {
                     tbs.buildTable({
                         scope: $scope,
-                        tag: 'partition',
+                        tag: 'partition'
                     });
 
                     $log.log('OvPartitionCtrl has been created');
diff --git a/web/gui/src/main/webapp/app/view/port/port.js b/web/gui/src/main/webapp/app/view/port/port.js
index a08933d..98a0cfb 100644
--- a/web/gui/src/main/webapp/app/view/port/port.js
+++ b/web/gui/src/main/webapp/app/view/port/port.js
@@ -22,17 +22,19 @@
     'use strict';
 
     // injected references
-    var $log, $scope, $location, tbs, ns;
+    var $log, $scope, $location, fs, tbs, ns;
 
     angular.module('ovPort', [])
     .controller('OvPortCtrl',
-        ['$log', '$scope', '$location', 'TableBuilderService', 'NavService',
+        ['$log', '$scope', '$location',
+            'FnService', 'TableBuilderService', 'NavService',
 
-        function (_$log_, _$scope_, _$location_, _tbs_, _ns_) {
+        function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _ns_) {
             var params;
             $log = _$log_;
             $scope = _$scope_;
             $location = _$location_;
+            fs = _fs_;
             tbs = _tbs_;
             ns = _ns_;
             $scope.deviceTip = 'Show device table';
@@ -48,7 +50,7 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'port',
-                query: params,
+                query: params
             });
 
             $scope.nav = function (path) {
@@ -57,12 +59,12 @@
                 }
             };
 
-             Object.defineProperty($scope, 'queryFilter', {
-                 get: function () {
+             Object.defineProperty($scope, "queryFilter", {
+                 get: function() {
                      var out = {};
-                     out[$scope.queryBy || '$'] = $scope.query;
+                     out[$scope.queryBy || "$"] = $scope.query;
                      return out;
-                 },
+                 }
              });
 
             $log.log('OvPortCtrl has been created');
diff --git a/web/gui/src/main/webapp/app/view/processor/processor.js b/web/gui/src/main/webapp/app/view/processor/processor.js
index ca2d0ea..706ccfc 100644
--- a/web/gui/src/main/webapp/app/view/processor/processor.js
+++ b/web/gui/src/main/webapp/app/view/processor/processor.js
@@ -22,17 +22,19 @@
     'use strict';
 
     // injected references
-    var $log, $scope, $location, tbs, ns;
+    var $log, $scope, $location, fs, tbs, ns;
 
     angular.module('ovProcessor', [])
     .controller('OvProcessorCtrl',
-        ['$log', '$scope', '$location', 'TableBuilderService', 'NavService',
+        ['$log', '$scope', '$location',
+            'FnService', 'TableBuilderService', 'NavService',
 
-        function (_$log_, _$scope_, _$location_, _tbs_, _ns_) {
+        function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _ns_) {
             var params;
             $log = _$log_;
             $scope = _$scope_;
             $location = _$location_;
+            fs = _fs_;
             tbs = _tbs_;
             ns = _ns_;
             $scope.requestTip = 'Show packet requests';
@@ -42,7 +44,7 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'processor',
-                query: params,
+                query: params
             });
 
             $scope.nav = function (path) {
diff --git a/web/gui/src/main/webapp/app/view/settings/settings.js b/web/gui/src/main/webapp/app/view/settings/settings.js
index bdc0e1f..ce3caa1 100644
--- a/web/gui/src/main/webapp/app/view/settings/settings.js
+++ b/web/gui/src/main/webapp/app/view/settings/settings.js
@@ -22,7 +22,7 @@
     'use strict';
 
     // injected refs
-    var $log, $scope, fs, ks, ps, is;
+    var $log, $scope, wss, fs, ks, ps, is;
 
     // internal state
     var detailsPanel,
@@ -39,19 +39,19 @@
         propOrder = ['fqComponent', 'prop', 'type', 'value', 'defValue', 'desc'],
         friendlyProps = [
             'Component', 'Property', 'Type', 'Value', 'Default Value',
-            'Description',
+            'Description'
         ];
 
     function createDetailsPanel() {
         detailsPanel = ps.createPanel(pName, {
             width: wSize.width,
             margin: 0,
-            hideMargin: 0,
+            hideMargin: 0
         });
 
         detailsPanel.el().style({
             position: 'absolute',
-            top: pStartY + 'px',
+            top: pStartY + 'px'
         });
 
         detailsPanel.hide();
@@ -87,7 +87,7 @@
         div = top.append('div').classed('top-content', true);
 
         function ndiv(cls, addTable) {
-            var d = div.append('div').classed(cls, true);
+            var  d = div.append('div').classed(cls, true);
             if (addTable) {
                 d.append('table');
             }
@@ -129,12 +129,13 @@
     angular.module('ovSettings', [])
         .controller('OvSettingsCtrl',
             ['$log', '$scope',
-            'FnService', 'KeyService', 'PanelService',
+            'WebSocketService', 'FnService', 'KeyService', 'PanelService',
             'IconService', 'TableBuilderService',
 
-        function (_$log_, _$scope_, _fs_, _ks_, _ps_, _is_, tbs) {
+        function (_$log_, _$scope_, _wss_, _fs_, _ks_, _ps_, _is_, tbs) {
             $log = _$log_;
             $scope = _$scope_;
+            wss = _wss_;
             fs = _fs_;
             ks = _ks_;
             ps = _ps_;
@@ -155,16 +156,16 @@
             tbs.buildTable({
                 scope: $scope,
                 tag: 'setting',
-                selCb: selCb,
+                selCb: selCb
             });
 
             ks.keyBindings({
                 esc: [$scope.selectCallback, 'Deselect property'],
-                _helpFormat: ['esc'],
+                _helpFormat: ['esc']
             });
             ks.gestureNotes([
                 ['click row', 'Select / deselect settings property'],
-                ['scroll down', 'See more settings'],
+                ['scroll down', 'See more settings']
             ]);
 
             $scope.$on('$destroy', function () {
@@ -203,11 +204,11 @@
                     // create key bindings to handle panel
                     ks.keyBindings({
                         esc: [closePanel, 'Close the details panel'],
-                        _helpFormat: ['esc'],
+                        _helpFormat: ['esc']
                     });
                     ks.gestureNotes([
                         ['click', 'Select a row to show property details'],
-                        ['scroll down', 'See more properties'],
+                        ['scroll down', 'See more properties']
                     ]);
 
                     // if the window size changes
@@ -215,7 +216,7 @@
                         function () {
                             return {
                                 h: $window.innerHeight,
-                                w: $window.innerWidth,
+                                w: $window.innerWidth
                             };
                         }, function () {
                             if (panelData) {
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 e495cb4..29f149f 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -25,13 +25,13 @@
         'ngCookies',
         'onosUtil',
         'onosSvg',
-        'onosRemote',
+        'onosRemote'
     ];
 
     // references to injected services
-    var $scope, $log, $loc, $timeout,
+    var $scope, $log, $loc, $timeout, $cookies,
         fs, ks, zs, gs, ms, sus, flash, wss, ps, th, tds, t3s, tes, tfs, tps,
-        tis, tms, tss, tls, tos, fltr, ttbs, tspr, tov;
+        tis, tms, tss, tls, tts, tos, fltr, ttbs, tspr, ttip, tov;
 
     // DOM elements
     var ovtopo, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
@@ -68,7 +68,7 @@
 
             E: [equalizeMasters, 'Equalize mastership roles'],
 
-            // -- instance color palette debug
+            //-- instance color palette debug
             // 9: function () { sus.cat7().testCard(svg); },
 
             // topology overlay selections
@@ -83,10 +83,10 @@
             _keyListener: ttbs.keyListener,
 
             _helpFormat: [
-                ['I', 'O', 'D', 'H', 'M', 'P', 'dash', 'B', 'G', 'S'],
+                ['I', 'O', 'D', 'H', 'M', 'P', 'dash', 'B', 'G', 'S' ],
                 ['X', 'Z', 'N', 'L', 'shift-L', 'U', 'R', '-', 'E', '-', 'dot'],
-                [], // this column reserved for overlay actions
-            ],
+                []   // this column reserved for overlay actions
+            ]
         };
 
         if (fs.isO(overlayKeys)) {
@@ -100,7 +100,7 @@
             ['shift-click', 'Toggle selection state'],
             ['drag', 'Reposition (and pin) device / host'],
             ['cmd-scroll', 'Zoom in / out'],
-            ['cmd-drag', 'Pan'],
+            ['cmd-drag', 'Pan']
         ]);
     }
 
@@ -183,7 +183,7 @@
     function handleEscape() {
         if (tis.showMaster()) {
             // if an instance is selected, cancel the affinity mapping
-            tis.cancelAffinity();
+            tis.cancelAffinity()
 
         } else if (tov.hooks.escape()) {
             // else if the overlay consumed the ESC event...
@@ -234,7 +234,7 @@
     function setUpToolbar() {
         ttbs.init({
             getActionEntry: getActionEntry,
-            setUpKeys: setUpKeys,
+            setUpKeys: setUpKeys
         });
         ttbs.createToolbar();
     }
@@ -259,7 +259,7 @@
         var sc = zoomer.scale(),
             tr = zoomer.translate();
 
-        ps.setPrefs('topo_zoom', { tx: tr[0], ty: tr[1], sc: sc });
+        ps.setPrefs('topo_zoom', {tx:tr[0], ty:tr[1], sc:sc});
 
         // keep the map lines constant width while zooming
         mapG.style('stroke-width', (2.0 / sc) + 'px');
@@ -273,7 +273,7 @@
             svg: svg,
             zoomLayer: zoomLayer,
             zoomEnabled: zoomEnabled,
-            zoomCallback: zoomCallback,
+            zoomCallback: zoomCallback
         });
     }
 
@@ -289,7 +289,7 @@
         var g, box;
         noDevsLayer = svg.append('g').attr({
             id: 'topo-noDevsLayer',
-            transform: sus.translate(500, 500),
+            transform: sus.translate(500,500)
         });
         // Note, SVG viewbox is '0 0 1000 1000', defined in topo.html.
         // We are translating this layer to have its origin at the center
@@ -297,7 +297,7 @@
         g = noDevsLayer.append('g');
         gs.addGlyph(g, 'bird', 100).attr('class', 'noDevsBird');
         g.append('text').text('No devices are connected')
-            .attr({ x: 120, y: 80 });
+            .attr({ x: 120, y: 80});
 
         box = g.node().getBBox();
         box.x -= box.width/2;
@@ -348,7 +348,7 @@
 
         australia: function (c) {
             return c.properties.adm0_a3 === 'AUS';
-        },
+        }
     };
 
     var tintOn = 0,
@@ -357,19 +357,19 @@
         light: {
             sea: 'aliceblue',
             land: 'white',
-            outline: '#ddd',
+            outline: '#ddd'
         },
         dark: {
             sea: '#001830',
             land: '#232331',
-            outline: '#3a3a3a',
-        },
+            outline: '#3a3a3a'
+        }
     };
 
     function shading() {
         return tintOn ? {
             palette: shadePalette[th.theme()],
-            flip: shadeFlip,
+            flip: shadeFlip
         } : '';
     }
 
@@ -386,7 +386,7 @@
                 mapid: 'usa',
                 mapscale: 1,
                 mapfilepath: '*continental_us',
-                tint: 'off',
+                tint: 'off'
             },
             $loc.search()
         );
@@ -410,7 +410,7 @@
         if (mapG.empty()) {
             mapG = zoomLayer.append('g').attr('id', 'topo-map');
         } else {
-            mapG.each(function (d, i) {
+            mapG.each(function(d,i) {
                 d3.selectAll(this.childNodes).remove();
             });
         }
@@ -422,13 +422,13 @@
             promise = ms.loadMapRegionInto(mapG, {
                 countryFilter: cfilter,
                 adjustScale: mapScale,
-                shading: shading(),
+                shading: shading()
             });
         } else {
 
             promise = ms.loadMapInto(mapG, mapFilePath, mapId, {
                 adjustScale: mapScale,
-                shading: shading(),
+                shading: shading()
             });
         }
 
@@ -437,7 +437,7 @@
     }
 
     function mapReshader() {
-        $log.debug('... Re-shading map ...');
+        $log.debug('... Re-shading map ...')
         ms.reshade(shading());
     }
 
@@ -460,7 +460,7 @@
         var prefs = ps.getPrefs('topo_sprites', { sprites: '' }, $loc.search()),
             sprId = prefs.sprites;
 
-        spriteG = zoomLayer.append('g').attr('id', 'topo-sprites');
+        spriteG = zoomLayer.append ('g').attr('id', 'topo-sprites');
         if (sprId) {
             ps.setPrefs('topo_sprites', prefs);
             tspr.loadSprites(spriteG, defs, sprId);
@@ -536,21 +536,21 @@
 
     angular.module('ovTopo', moduleDependencies)
         .controller('OvTopoCtrl', ['$scope', '$log', '$location', '$timeout',
-            'FnService', 'MastService', 'KeyService', 'ZoomService',
+            '$cookies', 'FnService', 'MastService', 'KeyService', 'ZoomService',
             'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
             'WebSocketService', 'PrefsService', 'ThemeService',
             'TopoDialogService', 'TopoD3Service',
             'TopoEventService', 'TopoForceService', 'TopoPanelService',
             'TopoInstService', 'TopoSelectService', 'TopoLinkService',
-            'TopoObliqueService', 'TopoFilterService',
+            'TopoTrafficService', 'TopoObliqueService', 'TopoFilterService',
             'TopoToolbarService', 'TopoMapService', 'TopoSpriteService',
-            'TopoOverlayService',
+            'TooltipService', 'TopoOverlayService',
 
-        function (_$scope_, _$log_, _$loc_, _$timeout_, _fs_, mast, _ks_,
+        function (_$scope_, _$log_, _$loc_, _$timeout_, _$cookies_, _fs_, mast, _ks_,
                   _zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _ps_, _th_,
                   _tds_, _t3s_, _tes_,
-                  _tfs_, _tps_, _tis_, _tss_, _tls_, _tos_, _fltr_,
-                  _ttbs_, _tms_, _tspr_, _tov_) {
+                  _tfs_, _tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_,
+                  _ttbs_, _tms_, _tspr_, _ttip_, _tov_) {
 
             var params = _$loc_.search(),
                 selOverlay = params.overlayId,
@@ -563,13 +563,14 @@
                     zoomLayer: function () { return zoomLayer; },
                     zoomer: function () { return zoomer; },
                     opacifyMap: opacifyMap,
-                    topoStartDone: topoStartDone,
+                    topoStartDone: topoStartDone
                 };
 
             $scope = _$scope_;
             $log = _$log_;
             $loc = _$loc_;
             $timeout = _$timeout_;
+            $cookies = _$cookies_;
             fs = _fs_;
             ks = _ks_;
             zs = _zs_;
@@ -590,18 +591,20 @@
             tps = _tps_;
             tis = _tis_;
             tms = _tms_;
+            tss = _tss_;
             tls = _tls_;
+            tts = _tts_;
             tos = _tos_;
             fltr = _fltr_;
             ttbs = _ttbs_;
             tspr = _tspr_;
+            ttip = _ttip_;
             tov = _tov_;
-            tss = _tss_;
 
             tms.start({
                 toggleMap: toggleMap,
                 currentMap: currentMap,
-                setMap: setMap,
+                setMap: setMap
             });
 
             // pull intent data from the query string...
@@ -610,7 +613,7 @@
                     key: params.key,
                     appId: params.appId,
                     appName: params.appName,
-                    intentType: params.intentType,
+                    intentType: params.intentType
                 };
             }
 
@@ -646,7 +649,7 @@
             setUpNoDevs();
             setUpMap().then(
                 function (proj) {
-                    var z = ps.getPrefs('topo_zoom', { tx: 0, ty: 0, sc: 1 });
+                    var z = ps.getPrefs('topo_zoom', { tx:0, ty:0, sc:1 });
                     zoomer.panZoom([z.tx, z.ty], z.sc);
                     $log.debug('** Zoom restored:', z);
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoD3.js b/web/gui/src/main/webapp/app/view/topo/topoD3.js
index c5c3b1f..3d232ee 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoD3.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoD3.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected refs
-    var sus, is, ts, ps, ttbs;
+    var $log, fs, sus, is, ts, ps, ttbs;
 
     // api to topoForce
     var zoomer, api;
@@ -46,7 +46,7 @@
         badgeConfig = {
             radius: 12,
             yoff: 5,
-            gdelta: 10,
+            gdelta: 10
         },
         halfDevIcon = devIconDim / 2,
         devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
@@ -55,7 +55,7 @@
         status = {
             i: 'badgeInfo',
             w: 'badgeWarn',
-            e: 'badgeError',
+            e: 'badgeError'
         };
 
     // NOTE: this type of hack should go away once we have implemented
@@ -77,7 +77,7 @@
     var remappedHostTypes = {
         router: 'm_router',
         endstation: 'm_endstation',
-        bgpSpeaker: 'm_bgpSpeaker',
+        bgpSpeaker: 'm_bgpSpeaker'
     };
 
     function mapDeviceTypeToGlyph(type) {
@@ -100,13 +100,13 @@
     var dColTheme = {
         light: {
             online: '#444444',
-            offline: '#cccccc',
+            offline: '#cccccc'
         },
         dark: {
             // TODO: theme
             online: '#444444',
-            offline: '#cccccc',
-        },
+            offline: '#cccccc'
+        }
     };
 
     function devGlyphColor(d) {
@@ -119,13 +119,13 @@
 
     function setDeviceColor(d) {
         // want to color the square rectangle (no longer the 'use' glyph)
-        d.el.selectAll('rect').filter(function (d, i) { return i === 1; })
+        d.el.selectAll('rect').filter(function (d, i) {return i === 1;})
             .style('fill', devGlyphColor(d));
     }
 
     function incDevLabIndex() {
         setDevLabIndex(deviceLabelIndex+1);
-        switch (deviceLabelIndex) {
+        switch(deviceLabelIndex) {
             case 0: return 'Hide device labels';
             case 1: return 'Show friendly device labels';
             case 2: return 'Show device ID labels';
@@ -141,7 +141,7 @@
 
     function incHostLabIndex() {
         setHostLabIndex(hostLabelIndex+1);
-        switch (hostLabelIndex) {
+        switch(hostLabelIndex) {
             case 0: return 'Show friendly host labels';
             case 1: return 'Show host IP Addresses';
             case 2: return 'Show host MAC Addresses';
@@ -180,8 +180,8 @@
             x: -dim/2,
             y: -dim/2,
             width: dim + labelWidth,
-            height: dim,
-        };
+            height: dim
+        }
     }
 
     function updateDeviceRendering(d) {
@@ -239,7 +239,7 @@
                     width: bcgd * 2,
                     height: bcgd * 2,
                     transform: sus.translate(-bcgd, -bcgd),
-                    'xlink:href': '#' + bdg.gid,
+                    'xlink:href': '#' + bdg.gid
                 });
         }
     }
@@ -279,14 +279,14 @@
         var node = d3.select(this),
             glyphId = mapDeviceTypeToGlyph(d.type),
             label = trimLabel(deviceLabel(d)),
-            rect, crect, glyph, labelWidth;
+            rect, crect, text, glyph, labelWidth;
 
         d.el = node;
 
         rect = node.append('rect');
         crect = node.append('rect');
 
-        node.append('text').text(label)
+        text = node.append('text').text(label)
             .attr('text-anchor', 'left')
             .attr('y', '0.3em')
             .attr('x', halfDevIcon + labelPad);
@@ -462,13 +462,13 @@
             });
 
             if (idx === -1) {
-                labels.push({ id: newId, x: newX, y: newY });
+                labels.push({id: newId, x: newX, y: newY});
             } else {
-                labels[idx] = { id: newId, x: newX, y: newY };
+                labels[idx] = {id: newId, x: newX, y: newY};
             }
 
-            return { x: newX, y: newY };
-        };
+            return {x: newX, y: newY};
+        }
     }
 
     var getLabelPos = generateLabelFunction();
@@ -518,7 +518,7 @@
 
         return {
             x: movedX,
-            y: movedY,
+            y: movedY
         };
     }
 
@@ -545,7 +545,7 @@
             x2: mid.x + moveAmtX,
             y2: mid.y + moveAmtY,
             stroke: api.linkConfig()[ts.theme()].baseColor,
-            transform: 'rotate(' + angle + ',' + mid.x + ',' + mid.y + ')',
+            transform: 'rotate(' + angle + ',' + mid.x + ',' + mid.y + ')'
         };
     }
 
@@ -554,7 +554,7 @@
             dist = 20;
         return {
             x: point.x + dist,
-            y: point.y + dist,
+            y: point.y + dist
         };
     }
 
@@ -568,7 +568,7 @@
             var el = d3.select(this);
 
             el.attr({
-                transform: function (d) { return calcGroupPos(d.linkCoords); },
+                transform: function (d) { return calcGroupPos(d.linkCoords); }
             });
             el.select('line')
                 .attr(hashAttrs(d.linkCoords));
@@ -583,7 +583,7 @@
             .append('g')
             .attr({
                 transform: function (d) { return calcGroupPos(d.linkCoords); },
-                id: function (d) { return 'pair-' + d.id; },
+                id: function (d) { return 'pair-' + d.id; }
             })
             .classed('numLinkLabel', true);
 
@@ -608,10 +608,12 @@
 
     angular.module('ovTopo')
     .factory('TopoD3Service',
-        ['SvgUtilService', 'IconService', 'ThemeService',
+        ['$log', 'FnService', 'SvgUtilService', 'IconService', 'ThemeService',
             'PrefsService', 'TopoToolbarService',
 
-        function (_sus_, _is_, _ts_, _ps_, _ttbs_) {
+        function (_$log_, _fs_, _sus_, _is_, _ts_, _ps_, _ttbs_) {
+            $log = _$log_;
+            fs = _fs_;
             sus = _sus_;
             is = _is_;
             ts = _ts_;
@@ -652,7 +654,7 @@
                 applyLinkLabels: applyLinkLabels,
                 transformLabel: transformLabel,
                 applyPortLabels: applyPortLabels,
-                applyNumLinkLabels: applyNumLinkLabels,
+                applyNumLinkLabels: applyNumLinkLabels
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoDialog.js b/web/gui/src/main/webapp/app/view/topo/topoDialog.js
index 18c83e9..425dad0 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoDialog.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoDialog.js
@@ -25,7 +25,7 @@
     // constants
     var idDialog = 'topo-p-dialog',
         opts = {
-            cssCls: 'topo-p',
+            cssCls: 'topo-p'
         };
 
     // ==========================
@@ -38,7 +38,7 @@
             return {
                 openDialog: function () { return ds.openDialog(idDialog, opts); },
                 closeDialog: ds.closeDialog,
-                createDiv: ds.createDiv,
+                createDiv: ds.createDiv
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoEvent.js b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
index 01b2891..2a93895 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoEvent.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
@@ -27,7 +27,7 @@
     'use strict';
 
     // injected refs
-    var $log, wss, tps, tis, tfs, tss, tov, tspr;
+    var $log, $interval, wss, tps, tis, tfs, tss, tov, tspr;
 
     // internal state
     var handlerMap,
@@ -61,7 +61,7 @@
             topoStartDone: tfs,
 
             spriteListResponse: tspr,
-            spriteDataResponse: tspr,
+            spriteDataResponse: tspr
         };
     }
 
@@ -74,13 +74,14 @@
 
     angular.module('ovTopo')
     .factory('TopoEventService',
-        ['$log', 'WebSocketService',
+        ['$log', '$interval', 'WebSocketService',
             'TopoPanelService', 'TopoInstService', 'TopoForceService',
             'TopoSelectService', 'TopoOverlayService', 'TopoSpriteService',
 
-        function (_$log_, _wss_,
+        function (_$log_,  _$interval_, _wss_,
                   _tps_, _tis_, _tfs_, _tss_, _tov_, _tspr_) {
             $log = _$log_;
+            $interval = _$interval_;
             wss = _wss_;
             tps = _tps_;
             tis = _tis_;
@@ -114,7 +115,7 @@
             return {
                 bindHandlers: bindHandlers,
                 start: start,
-                stop: stop,
+                stop: stop
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoFilter.js b/web/gui/src/main/webapp/app/view/topo/topoFilter.js
index db5b3c3..b877fce 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoFilter.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoFilter.js
@@ -24,7 +24,7 @@
     'use strict';
 
     // injected refs
-    var flash;
+    var $log, fs, flash, tps, tts;
 
     // api to topoForce
     var api;
@@ -39,40 +39,40 @@
     var layerLookup = {
             host: {
                 endstation: 'pkt', // default, if host event does not define type
-                router: 'pkt',
-                bgpSpeaker: 'pkt',
+                router:     'pkt',
+                bgpSpeaker: 'pkt'
             },
             device: {
                 switch: 'pkt',
                 router: 'pkt',
                 roadm: 'opt',
-                otn: 'opt',
+                otn: 'opt'
             },
             link: {
                 hostLink: 'pkt',
                 direct: 'pkt',
                 indirect: '',
                 tunnel: '',
-                optical: 'opt',
-            },
+                optical: 'opt'
+            }
         },
         // order of layer cycling in button
         dispatch = [
             {
                 type: 'all',
                 action: function () { suppressLayers(false); },
-                msg: 'All Layers Shown',
+                msg: 'All Layers Shown'
             },
             {
                 type: 'pkt',
                 action: function () { showLayer('pkt'); },
-                msg: 'Packet Layer Shown',
+                msg: 'Packet Layer Shown'
             },
             {
                 type: 'opt',
                 action: function () { showLayer('opt'); },
-                msg: 'Optical Layer Shown',
-            },
+                msg: 'Optical Layer Shown'
+            }
         ],
         layer = 0;
 
@@ -123,9 +123,18 @@
     // === MODULE DEFINITION ===
 
     angular.module('ovTopo')
-        .factory('TopoFilterService', ['FlashService',
-            function (_flash_) {
+        .factory('TopoFilterService',
+        ['$log', 'FnService',
+            'FlashService',
+            'TopoPanelService',
+            'TopoTrafficService',
+
+            function (_$log_, _fs_, _flash_, _tps_, _tts_) {
+                $log = _$log_;
+                fs = _fs_;
                 flash = _flash_;
+                tps = _tps_;
+                tts = _tts_;
 
                 function initFilter(_api_) {
                     api = _api_;
@@ -136,8 +145,7 @@
 
                     clickAction: clickAction,
                     selected: selected,
-                    inLayer: inLayer,
+                    inLayer: inLayer
                 };
-            },
-        ]);
+            }]);
 }());
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 c149f7b..f38fa56 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -31,42 +31,42 @@
         light: {
             baseColor: '#939598',
             inColor: '#66f',
-            outColor: '#f00',
+            outColor: '#f00'
         },
         dark: {
             // TODO : theme
             baseColor: '#939598',
             inColor: '#66f',
-            outColor: '#f00',
+            outColor: '#f00'
         },
         inWidth: 12,
-        outWidth: 10,
+        outWidth: 10
     };
 
     // internal state
-    var settings, // merged default settings and options
-        force, // force layout object
-        drag, // drag behavior handler
+    var settings,   // merged default settings and options
+        force,      // force layout object
+        drag,       // drag behavior handler
         network = {
             nodes: [],
             links: [],
             linksByDevice: {},
             lookup: {},
-            revLinkToKey: {},
+            revLinkToKey: {}
         },
-        lu, // shorthand for lookup
-        rlk, // shorthand for revLinktoKey
-        showHosts = false, // whether hosts are displayed
-        showOffline = true, // whether offline devices are displayed
-        nodeLock = false, // whether nodes can be dragged or not (locked)
-        fTimer, // timer for delayed force layout
-        fNodesTimer, // timer for delayed nodes update
-        fLinksTimer, // timer for delayed links update
-        dim, // the dimensions of the force layout [w,h]
-        linkNums = [], // array of link number labels
-        devIconDim = 36, // node target dimension
-        devIconDimMin = 20, // node minimum dimension when zoomed out
-        devIconDimMax = 40, // node maximum dimension when zoomed in
+        lu,                     // shorthand for lookup
+        rlk,                    // shorthand for revLinktoKey
+        showHosts = false,      // whether hosts are displayed
+        showOffline = true,     // whether offline devices are displayed
+        nodeLock = false,       // whether nodes can be dragged or not (locked)
+        fTimer,                 // timer for delayed force layout
+        fNodesTimer,            // timer for delayed nodes update
+        fLinksTimer,            // timer for delayed links update
+        dim,                    // the dimensions of the force layout [w,h]
+        linkNums = [],          // array of link number labels
+        devIconDim = 36,        // node target dimension
+        devIconDimMin = 20,     // node minimum dimension when zoomed out
+        devIconDimMax = 40,     // node maximum dimension when zoomed in
         portLabelDim = 30;
 
     // SVG elements;
@@ -83,23 +83,23 @@
             // note: key is node.class
             device: -8000,
             host: -5000,
-            _def_: -12000,
+            _def_: -12000
         },
         linkDistance: {
             // note: key is link.type
             direct: 100,
             optical: 120,
             hostLink: 3,
-            _def_: 50,
+            _def_: 50
         },
         linkStrength: {
             // note: key is link.type
             // range: {0.0 ... 1.0}
-            // direct: 1.0,
-            // optical: 1.0,
-            // hostLink: 1.0,
-            _def_: 1.0,
-        },
+            //direct: 1.0,
+            //optical: 1.0,
+            //hostLink: 1.0,
+            _def_: 1.0
+        }
     };
 
 
@@ -171,7 +171,7 @@
 
         lnk = tms.createHostLink(data);
         if (lnk) {
-            d.linkData = lnk; // cache ref on its host
+            d.linkData = lnk;    // cache ref on its host
             network.links.push(lnk);
             lu[d.ingress] = lnk;
             lu[d.egress] = lnk;
@@ -308,7 +308,7 @@
             network.linksByDevice[found].push(ldata);
             ldata.devicePair = found;
         } else {
-            network.linksByDevice[key] = [ldata];
+            network.linksByDevice[key] = [ ldata ];
             ldata.devicePair = key;
         }
     }
@@ -318,7 +318,7 @@
         ldata.fromTarget = link;
         rlk[link.id] = ldata.key;
         // possible solution to el being undefined in restyleLinkElement:
-        // _updateLinks();
+        //_updateLinks();
         restyleLinkElement(ldata);
     }
 
@@ -468,15 +468,15 @@
                 y: d.y,
                 equivLoc: {
                     lng: ll[0],
-                    lat: ll[1],
-                },
+                    lat: ll[1]
+                }
             };
         }
         d.metaUi = metaUi;
         wss.sendEvent('updateMeta', {
             id: d.id,
             class: d.class,
-            memento: metaUi,
+            memento: metaUi
         });
     }
 
@@ -557,7 +557,7 @@
     }
 
     function supAmt(less) {
-        return less ? 'suppressed' : 'suppressedmax';
+        return less ? "suppressed" : "suppressedmax";
     }
 
     function suppressLayers(b, less) {
@@ -665,6 +665,8 @@
     // IMPLEMENTATION NOTE: _updateNodes() should NOT stop, start, or resume
     //  the force layout; that needs to be determined and implemented elsewhere
     function _updateNodes() {
+
+        var scale = uplink.zoomer().scale();
         // select all the nodes in the layout:
         node = nodeG.selectAll('.node')
             .data(network.nodes, function (d) { return d.id; });
@@ -683,7 +685,7 @@
                     // Need to guard against NaN here ??
                     return sus.translate(d.x, d.y);
                 },
-                opacity: 0,
+                opacity: 0
             })
             .call(drag)
             .on('mouseover', tss.nodeMouseOver)
@@ -719,7 +721,7 @@
             x1: link.source.x,
             y1: link.source.y,
             x2: link.target.x,
-            y2: link.target.y,
+            y2: link.target.y
         };
     }
 
@@ -740,7 +742,7 @@
             x1: pos.x1 + (mult * dy / length),
             y1: pos.y1 + (mult * -dx / length),
             x2: pos.x2 + (mult * dy / length),
-            y2: pos.y2 + (mult * -dx / length),
+            y2: pos.y2 + (mult * -dx / length)
         };
     }
 
@@ -783,7 +785,7 @@
                 linkNums.push({
                     id: key,
                     num: numLinks,
-                    linkCoords: linkArr[0].position,
+                    linkCoords: linkArr[0].position
                 });
             } else {
                 linkSrcId = null;
@@ -832,14 +834,14 @@
                 x2: function (d) { return d.position.x2; },
                 y2: function (d) { return d.position.y2; },
                 stroke: linkConfig[th].inColor,
-                'stroke-width': linkConfig.inWidth,
+                'stroke-width': linkConfig.inWidth
             });
 
         // augment links
         entering.each(td3.linkEntering);
 
         // operate on both existing and new links:
-        // link.each(...)
+        //link.each(...)
 
         // add labels for how many links are in a thick line
         td3.applyNumLinkLabels(linkNums, numLinkLblsG);
@@ -856,7 +858,7 @@
             .duration(1500)
             .attr({
                 'stroke-dasharray': '3 12',
-                'stroke-width': linkConfig.outWidth,
+                'stroke-width': linkConfig.outWidth
             })
             .style('opacity', 0.0)
             .remove();
@@ -878,7 +880,7 @@
                 $timeout.cancel(fTimer);
             }
             fTimer = $timeout(function () {
-                $log.debug('Starting force-layout');
+                $log.debug("Starting force-layout");
                 force.start();
             }, 200);
         }
@@ -890,13 +892,13 @@
                 var dx = isNaN(d.x) ? 0 : d.x,
                     dy = isNaN(d.y) ? 0 : d.y;
                 return sus.translate(dx, dy);
-            },
+            }
         },
         linkAttr: {
             x1: function (d) { return d.position.x1; },
             y1: function (d) { return d.position.y1; },
             x2: function (d) { return d.position.x2; },
-            y2: function (d) { return d.position.y2; },
+            y2: function (d) { return d.position.y2; }
         },
         linkLabelAttr: {
             transform: function (d) {
@@ -904,8 +906,8 @@
                 if (lnk) {
                     return td3.transformLabel(lnk.position, d.key);
                 }
-            },
-        },
+            }
+        }
     };
 
     function tick() {
@@ -989,7 +991,7 @@
                     id: 'lab-' + d.key,
                     key: d.key,
                     label: d.label,
-                    ldata: d,
+                    ldata: d
                 });
             }
         });
@@ -1006,7 +1008,7 @@
             projection: uplink.projection,
             network: network,
             restyleLinkElement: restyleLinkElement,
-            removeLinkElement: removeLinkElement,
+            removeLinkElement: removeLinkElement
         };
     }
 
@@ -1022,7 +1024,7 @@
             updateLinkLabelModel: updateLinkLabelModel,
             linkConfig: function () { return linkConfig; },
             deviceScale: deviceScale,
-            linkWidthScale: linkWidthScale,
+            linkWidthScale: linkWidthScale
         };
     }
 
@@ -1031,7 +1033,7 @@
             node: function () { return node; },
             zoomingOrPanning: zoomingOrPanning,
             updateDeviceColors: td3.updateDeviceColors,
-            deselectAllLinks: tls.deselectAllLinks,
+            deselectAllLinks: tls.deselectAllLinks
         };
     }
 
@@ -1039,7 +1041,7 @@
         return {
             hovered: tss.hovered,
             somethingSelected: tss.somethingSelected,
-            selectOrder: tss.selectOrder,
+            selectOrder: tss.selectOrder
         };
     }
 
@@ -1055,15 +1057,15 @@
             updateNodes: updateNodes,
             supLayers: suppressLayers,
             unsupNode: unsuppressNode,
-            unsupLink: unsuppressLink,
+            unsupLink: unsuppressLink
         };
     }
 
     function mkObliqueApi(uplink, fltr) {
         return {
-            force: function () { return force; },
+            force: function() { return force; },
             zoomLayer: uplink.zoomLayer,
-            nodeGBBox: function () { return nodeG.node().getBBox(); },
+            nodeGBBox: function() { return nodeG.node().getBBox(); },
             node: function () { return node; },
             link: function () { return link; },
             linkLabel: function () { return linkLabel; },
@@ -1079,14 +1081,14 @@
             calcLinkPos: calcPosition,
             applyNumLinkLabels: function () {
                 td3.applyNumLinkLabels(linkNums, numLinkLblsG);
-            },
+            }
         };
     }
 
     function mkFilterApi() {
         return {
             node: function () { return node; },
-            link: function () { return link; },
+            link: function () { return link; }
         };
     }
 
@@ -1096,7 +1098,7 @@
             zoomer: uplink.zoomer(),
             network: network,
             portLabelG: function () { return portLabelG; },
-            showHosts: function () { return showHosts; },
+            showHosts: function () { return showHosts; }
         };
     }
 
@@ -1262,7 +1264,7 @@
                 addLink: addLink,
                 updateLink: updateLink,
                 removeLink: removeLink,
-                topoStartDone: topoStartDone,
+                topoStartDone: topoStartDone
             };
         }]);
 }());
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 7a51b2b..4146407 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoInst.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoInst.js
@@ -36,7 +36,7 @@
         idIns = 'topo-p-instance',
         instOpts = {
             edge: 'left',
-            width: 20,
+            width: 20
         };
 
     // internal state
@@ -141,24 +141,24 @@
             instSvg = {
                 width: 170,
                 height: 85,
-                viewBox: '0 0 170 85',
+                viewBox: '0 0 170 85'
             },
             headRect = {
                 x: rox,
                 y: roy,
                 width: rw,
-                height: rhh,
+                height: rhh
             },
             bodyRect = {
                 x: rox,
                 y: roy + rhh,
                 width: rw,
-                height: rbh,
+                height: rbh
             },
             titleAttr = {
                 class: 'instTitle',
                 x: tx,
-                y: 27,
+                y: 27
             };
 
         var onoses = oiBox.el().selectAll('.onosInst')
@@ -225,7 +225,7 @@
                 svg.append('text').attr({
                     class: 'instLabel ' + id,
                     x: tx,
-                    y: ty,
+                    y: ty
                 }).text(label);
                 ty += 18;
             }
@@ -342,7 +342,7 @@
                 show: showInsts,
                 hide: hideInsts,
                 toggle: toggleInsts,
-                showMaster: function () { return oiShowMaster; },
+                showMaster: function () { return oiShowMaster; }
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoLink.js b/web/gui/src/main/webapp/app/view/topo/topoLink.js
index 2bccbe4..a7b5bc7 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoLink.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoLink.js
@@ -23,15 +23,15 @@
     'use strict';
 
     // injected refs
-    var $log, fs, flash, tss, tps, tov;
+    var $log, fs, sus, ts, flash, tss, tps, tov;
 
     // internal state
     var api,
         td3,
         network,
-        showPorts = true, // enable port highlighting by default
-        enhancedLink = null, // the link over which the mouse is hovering
-        selectedLinks = {}; // the links which are already selected
+        showPorts = true,       // enable port highlighting by default
+        enhancedLink = null,    // the link over which the mouse is hovering
+        selectedLinks = {};     // the links which are already selected
 
     // SVG elements;
     var svg;
@@ -45,7 +45,7 @@
             tr = api.zoomer.translate(),
             mx = (m[0] - tr[0]) / sc,
             my = (m[1] - tr[1]) / sc;
-        return { x: mx, y: my };
+        return {x: mx, y: my};
     }
 
 
@@ -74,7 +74,7 @@
                     return; // skip hidden hosts
                 }
 
-                dist = mdist({ x: d.x, y: d.y }, mouse);
+                dist = mdist({x: d.x, y: d.y}, mouse);
                 if (dist < minDist && dist < proximity) {
                     minDist = dist;
                     nearest = d;
@@ -101,7 +101,7 @@
                     (sq(y2-y1) + sq(x2-x1)),
                 x4 = x3 - k * (y2-y1),
                 y4 = y3 + k * (x2-x1);
-            return { x: x4, y: y4 };
+            return {x:x4, y:y4};
         }
 
         function lineHit(line, p, m) {
@@ -179,7 +179,7 @@
         point = locatePortLabel(d);
         angular.extend(point, {
             id: 'topo-port-tgt',
-            num: d.tgtPort,
+            num: d.tgtPort
         });
         data.push(point);
 
@@ -187,7 +187,7 @@
             point = locatePortLabel(d, 1);
             angular.extend(point, {
                 id: 'topo-port-src',
-                num: d.srcPort,
+                num: d.srcPort
             });
             data.push(point);
         }
@@ -209,7 +209,7 @@
             dy = farY - nearY,
             k = offset / dist(dx, dy);
 
-        return { x: k * dx + nearX, y: k * dy + nearY };
+        return {x: k * dx + nearX, y: k * dy + nearY};
     }
 
     function selectLink(ldata) {
@@ -248,7 +248,7 @@
         if (!d.el) return;
 
         d.el.classed('selected', true);
-        selectedLinks[d.key] = { key: d };
+        selectedLinks[d.key] = {key : d};
 
         tps.displayLink(d, tov.hooks.modifyLinkData);
         tps.displaySomething();
@@ -317,12 +317,14 @@
 
     angular.module('ovTopo')
         .factory('TopoLinkService',
-        ['$log', 'FnService', 'FlashService', 'TopoSelectService',
-        'TopoPanelService', 'TopoOverlayService',
+        ['$log', 'FnService', 'SvgUtilService', 'ThemeService', 'FlashService',
+            'TopoSelectService', 'TopoPanelService', 'TopoOverlayService',
 
-        function (_$log_, _fs_, _flash_, _tss_, _tps_, _tov_) {
+        function (_$log_, _fs_, _sus_, _ts_, _flash_, _tss_, _tps_, _tov_) {
             $log = _$log_;
             fs = _fs_;
+            sus = _sus_;
+            ts = _ts_;
             flash = _flash_;
             tss = _tss_;
             tps = _tps_;
@@ -349,7 +351,7 @@
                 initLink: initLink,
                 destroyLink: destroyLink,
                 togglePorts: togglePorts,
-                deselectAllLinks: deselectAllLinks,
+                deselectAllLinks: deselectAllLinks
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoMap.js b/web/gui/src/main/webapp/app/view/topo/topoMap.js
index 2095f0d..9418d17 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoMap.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoMap.js
@@ -23,13 +23,13 @@
     'use strict';
 
     // injected refs
-    var $log, wss, tds, delegate;
+    var $log, $loc, fs, flash, wss, tds, delegate;
 
     // constants
     var mapRequest = 'mapSelectorRequest';
 
     // internal state
-    var order, maps, map, mapItems, msgHandlers;
+    var order, maps, map, mapItems, tintCheck, msgHandlers;
 
     // === ---------------------------
     // === Helper functions
@@ -60,7 +60,7 @@
             mapid: map.id,
             mapscale: map.scale,
             mapfilepath: map.filePath,
-            tint: 'off',
+            tint: 'off'
             // tint: tintCheck.property('checked') ? 'on' : 'off'
         };
         setMap(p);
@@ -98,7 +98,7 @@
         }
         p.append('span').text('Enable map tint');
 */
-
+        
         return content;
     }
 
@@ -131,15 +131,19 @@
 
     angular.module('ovTopo')
     .factory('TopoMapService',
-        ['$log', 'WebSocketService', 'TopoDialogService',
+        ['$log', '$location', 'FnService', 'FlashService', 'WebSocketService',
+            'TopoDialogService',
 
-        function (_$log_, _wss_, _tds_) {
+        function (_$log_, _$loc_, _fs_, _flash_, _wss_, _tds_) {
             $log = _$log_;
+            $loc = _$loc_;
+            fs = _fs_;
+            flash = _flash_;
             wss = _wss_;
             tds = _tds_;
 
             msgHandlers = {
-                mapSelectorResponse: handleMapResponse,
+                mapSelectorResponse: handleMapResponse
             };
 
             return {
@@ -150,7 +154,7 @@
                 openMapSelection: openMapSelection,
                 closeMapSelection: closeMapSelection,
                 start: start,
-                stop: stop,
+                stop: stop
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoModel.js b/web/gui/src/main/webapp/app/view/topo/topoModel.js
index eadbb43..e841907 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoModel.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoModel.js
@@ -38,7 +38,7 @@
     // shorthand
     var lu, rlk, nodes, links, linksByDevice;
 
-    var dim; // dimensions of layout [w,h]
+    var dim;    // dimensions of layout [w,h]
 
     // configuration 'constants'
     var defaultLinkType = 'direct',
@@ -90,14 +90,14 @@
         function rand() {
             return {
                 x: rnd.randDim(dim[0]),
-                y: rnd.randDim(dim[1]),
+                y: rnd.randDim(dim[1])
             };
         }
 
         function near(node) {
             return {
                 x: node.x + nearDist + rnd.spread(nearDist),
-                y: node.y + nearDist + rnd.spread(nearDist),
+                y: node.y + nearDist + rnd.spread(nearDist)
             };
         }
 
@@ -181,7 +181,7 @@
                 // hostlink target is edge switch
                 return lnk.target.online;
             },
-            linkWidth: function () { return 1; },
+            linkWidth: function () { return 1; }
         });
         return lnk;
     }
@@ -203,7 +203,7 @@
                 x1: 0,
                 y1: 0,
                 x2: 0,
-                y2: 0,
+                y2: 0
             },
 
             // functions to aggregate dual link state
@@ -230,7 +230,7 @@
                     wt = (t && t.linkWidth) || 0;
                 return lnk.position.multiLink ? 5 : Math.max(ws, wt);
             },
-            extra: link.extra,
+            extra: link.extra
         });
         return lnk;
     }
@@ -244,13 +244,13 @@
 
         if (sMiss || dMiss) {
             $log.error('Node(s) not on map for link:' + sMiss + dMiss);
-            // logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
+            //logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
             return null;
         }
 
         return {
             source: srcNode,
-            target: dstNode,
+            target: dstNode
         };
     }
 
@@ -306,7 +306,7 @@
                 result.updateWith = function (data) {
                     angular.extend(rawLink, data);
                     api.restyleLinkElement(ldata);
-                };
+                }
             }
         } else if (op === 'remove') {
             if (!ldata) {
@@ -349,7 +349,7 @@
                         } else {
                             api.removeLinkElement(ldata);
                         }
-                    };
+                    }
                 }
             }
         }
@@ -466,7 +466,7 @@
                 findHosts: findHosts,
                 findAttachedHosts: findAttachedHosts,
                 findAttachedLinks: findAttachedLinks,
-                findBadLinks: findBadLinks,
-            };
+                findBadLinks: findBadLinks
+            }
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoOblique.js b/web/gui/src/main/webapp/app/view/topo/topoOblique.js
index 63027db..f3ac25b 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoOblique.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoOblique.js
@@ -24,7 +24,7 @@
     'use strict';
 
     // injected refs
-    var sus, flash;
+    var $log, fs, sus, flash;
 
     // api to topoForce
     var api;
@@ -43,14 +43,14 @@
      */
 
     // configuration
-    var xsky = -.7, // x skew y factor
-        xsk = -35, // x skew angle
-        ysc = .5, // y scale
+    var xsky = -.7,     // x skew y factor
+        xsk = -35,      // x skew angle
+        ysc = .5,       // y scale
         pad = 50,
         time = 1500,
         fill = {
-            pkt: 'rgba(130,130,170,0.3)', // blue-ish
-            opt: 'rgba(170,130,170,0.3)', // magenta-ish
+            pkt: 'rgba(130,130,170,0.3)',   // blue-ish
+            opt: 'rgba(170,130,170,0.3)'    // magenta-ish
         };
 
     // internal state
@@ -74,7 +74,7 @@
     }
 
     function noXform() {
-        return sus.skewX(0) + sus.translate(0, 0) + sus.scale(1, 1);
+        return sus.skewX(0) + sus.translate(0,0) + sus.scale(1,1);
     }
 
     function padBox(box, p) {
@@ -105,7 +105,7 @@
                 ay = xy.y - oy,
                 x = ax + ay * xsky,
                 y = (ay + yt) * ysc;
-            return { x: ox + x, y: oy + y };
+            return {x: ox + x, y: oy + y};
         };
 
         showPlane('pkt', box, -1);
@@ -136,7 +136,7 @@
 
         if (xffn) {
             api.nodes().forEach(function (d) {
-                var oldxy = { x: d.x, y: d.y },
+                var oldxy = {x: d.x, y: d.y},
                     coords = xffn(oldxy, dir(d));
                 d.oldxy = oldxy;
                 d.px = d.x = coords.x;
@@ -144,7 +144,7 @@
             });
         } else {
             api.nodes().forEach(function (d) {
-                var old = d.oldxy || { x: d.x, y: d.y };
+                var old = d.oldxy || {x: d.x, y: d.y};
                 d.px = d.x = old.x;
                 d.py = d.y = old.y;
                 delete d.oldxy;
@@ -191,7 +191,7 @@
             var id = planeId(tag),
                 g = api.zoomLayer().insert('g', '#topo-G')
                     .attr('id', id)
-                    .attr('transform', sus.translate(ox, oy));
+                    .attr('transform', sus.translate(ox,oy));
             g.append('rect')
                 .attr('fill', fill[tag])
                 .attr('opacity', 0);
@@ -220,9 +220,11 @@
 
 angular.module('ovTopo')
     .factory('TopoObliqueService',
-    ['SvgUtilService', 'FlashService',
+    ['$log', 'FnService', 'SvgUtilService', 'FlashService',
 
-    function (_sus_, _flash_) {
+    function (_$log_, _fs_, _sus_, _flash_) {
+        $log = _$log_;
+        fs = _fs_;
         sus = _sus_;
         flash = _flash_;
 
@@ -249,7 +251,7 @@
             destroyOblique: destroyOblique,
 
             isOblique: function () { return oblique; },
-            toggleOblique: toggleOblique,
+            toggleOblique: toggleOblique
         };
     }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
index d86af89..f953911 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -126,7 +126,7 @@
             if (sicb && aicb && aicb(intentType)) {
                 result.push({
                     id: ovid,
-                    tt: ov.tooltip || '%' + ovid + '%',
+                    tt: ov.tooltip || '%' + ovid + '%'
                 });
             }
         });
@@ -145,7 +145,7 @@
                 tooltip: (ov.tooltip || '(no tooltip)'),
                 cb: function () {
                     tbSelection(ov.overlayId, switchFn);
-                },
+                }
             });
             map[ov.overlayId] = idx++;
         });
@@ -185,28 +185,28 @@
         showDeviceView: {
             gid: 'switch',
             tt: 'Show Device View',
-            path: 'device',
+            path: 'device'
         },
         showFlowView: {
             gid: 'flowTable',
             tt: 'Show Flow View for this Device',
-            path: 'flow',
+            path: 'flow'
         },
         showPortView: {
             gid: 'portTable',
             tt: 'Show Port View for this Device',
-            path: 'port',
+            path: 'port'
         },
         showGroupView: {
             gid: 'groupTable',
             tt: 'Show Group View for this Device',
-            path: 'group',
+            path: 'group'
         },
         showMeterView: {
             gid: 'meterTable',
             tt: 'Show Meter View for this Device',
-            path: 'meter',
-        },
+            path: 'meter'
+        }
     };
 
     // retrieves a button definition from the current overlay and generates
@@ -221,7 +221,7 @@
             id: current.mkId(id),
             gid: current.mkGid(b.gid),
             tt: b.tt,
-            cb: f,
+            cb: f
         } : null;
     }
 
@@ -238,7 +238,7 @@
                     id: 'core-' + id,
                     gid: gid,
                     tt: tt,
-                    cb: function () { ns.navTo(path, { devId: devId }); },
+                    cb: function () { ns.navTo(path, {devId: devId }); }
                 });
             } else if (btn = _getButtonDef(id, data)) {
                 tps.addAction(btn);
@@ -253,7 +253,7 @@
                 id: current.mkId(id),
                 gid: current.mkGid(b.gid),
                 cb: b.cb,
-                tt: b.tt,
+                tt: b.tt
             });
         }
     }
@@ -318,7 +318,7 @@
         tss = _tss_;
     }
 
-    // process highlight event with optional delay
+    //process highlight event with optional delay
     function showHighlights(data) {
         function doHighlight() {
             _showHighlights(data);
@@ -446,11 +446,11 @@
                     mouseOver: mouseOverHook,
                     mouseOut: mouseOutHook,
                     modifyLinkData: modifyLinkDataHook,
-                    showIntent: showIntentHook,
+                    showIntent: showIntentHook
                 },
 
-                showHighlights: showHighlights,
-            };
+                showHighlights: showHighlights
+            }
         }]);
 
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo/topoPanel.js b/web/gui/src/main/webapp/app/view/topo/topoPanel.js
index 18af617..8f8eef5 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoPanel.js
@@ -30,17 +30,17 @@
         idSum = 'topo-p-summary',
         idDet = 'topo-p-detail',
         panelOpts = {
-            width: 260, // summary and detail panel width
+            width: 260          // summary and detail panel width
         },
-        sumMax = 226, // summary panel max height
-        padTop = 16, // summary panel padding below masthead
-        padding = 16, // panel internal padding
+        sumMax = 226,           // summary panel max height
+        padTop = 16,            // summary panel padding below masthead
+        padding = 16,           // panel internal padding
         padFudge = padTop + 2 * padding;
 
     // internal state
-    var useDetails = true, // should we show details if we have 'em?
-        haveDetails = false, // do we have details that we could show?
-        sumFromTop, // summary panel distance from top of screen
+    var useDetails = true,      // should we show details if we have 'em?
+        haveDetails = false,    // do we have details that we could show?
+        sumFromTop,             // summary panel distance from top of screen
         unbindWatch;
 
     // panels
@@ -140,7 +140,7 @@
             appendHeader: hAppend,
             appendBody: bAppend,
             appendFooter: fAppend,
-            adjustHeight: adjustHeight,
+            adjustHeight: adjustHeight
         };
     }
 
@@ -195,7 +195,7 @@
             function () {
                 return {
                     h: $window.innerHeight,
-                    w: $window.innerWidth,
+                    w: $window.innerWidth
                 };
             }, function () {
                 var h = summary.adjustHeight(sumFromTop, sumMax),
@@ -220,7 +220,7 @@
             table = summary.appendBody('table'),
             tbody = table.append('tbody');
 
-        gs.addGlyph(svg, 'bird', 24, 0, [1, 1]);
+        gs.addGlyph(svg, 'bird', 24, 0, [1,1]);
 
         title.text(data.title);
         listProps(tbody, data);
@@ -231,7 +231,7 @@
 
     var navPathIdKey = {
         device: 'devId',
-        host: 'hostId',
+        host: 'hostId'
     };
 
     function displaySingle(data) {
@@ -291,7 +291,7 @@
 
     var friendlyIndex = {
         device: 1,
-        host: 0,
+        host: 0
     };
 
     function friendly(d) {
@@ -306,7 +306,7 @@
 
     // provided to change presentation of internal type name
     var linkTypePres = {
-        hostLink: 'edge link',
+        hostLink: 'edge link'
     };
 
     function linkType(d) {
@@ -320,12 +320,12 @@
     var coreOrder = [
             'Type', 'Expected', '-',
             'A_type', 'A_id', 'A_label', 'A_port', '-',
-            'B_type', 'B_id', 'B_label', 'B_port',
+            'B_type', 'B_id', 'B_label', 'B_port'
         ],
         edgeOrder = [
             'Type', '-',
             'A_type', 'A_id', 'A_label', '-',
-            'B_type', 'B_id', 'B_label', 'B_port',
+            'B_type', 'B_id', 'B_label', 'B_port'
         ];
 
     function displayLink(data, modifyCb) {
@@ -344,7 +344,7 @@
         title.text('Link');
 
         var linkData = {
-            propOrder: order.slice(0), // makes a copy of the array
+            propOrder: order.slice(0),      // makes a copy of the array
             props: {
                 Type: linkType(data),
                 Expected: linkExpected(data),
@@ -357,8 +357,8 @@
                 B_type: data.target.class,
                 B_id: data.target.id,
                 B_label: friendly(data.target),
-                B_port: data.tgtPort,
-            },
+                B_port: data.tgtPort
+            }
         };
         listProps(tbody, modifyCb(linkData, data.extra));
 
@@ -422,7 +422,7 @@
 
     function hideSummaryPanel() {
         // instruct server to stop sending summary data
-        wss.sendEvent('cancelSummary');
+        wss.sendEvent("cancelSummary");
         summary.panel().hide(detail.up);
     }
 
@@ -443,7 +443,7 @@
     function augmentDetailPanel() {
         var d = detail,
             downPos = sumFromTop + sumMax + padFudge;
-        d.ypos = { up: sumFromTop, down: downPos, current: downPos };
+        d.ypos = { up: sumFromTop, down: downPos, current: downPos};
 
         d._move = function (y, cb) {
             var yp = d.ypos,
@@ -453,11 +453,11 @@
                 endCb = function () {
                     cb();
                     d.adjustHeight(d.ypos.current);
-                };
+                }
             } else {
                 endCb = function () {
                     d.adjustHeight(d.ypos.current);
-                };
+                }
             }
             if (yp.current !== y) {
                 yp.current = y;
@@ -552,7 +552,7 @@
                 addAction: addAction,
 
                 detailVisible: function () { return detail.panel().isVisible(); },
-                summaryVisible: function () { return summary.panel().isVisible(); },
+                summaryVisible: function () { return summary.panel().isVisible(); }
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoProtectedIntent.js b/web/gui/src/main/webapp/app/view/topo/topoProtectedIntent.js
index 8625dec..20193dd 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoProtectedIntent.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoProtectedIntent.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected refs
-    var flash, wss;
+    var $log, fs, flash, wss, api;
 
     // internal state
     var showingProtectedIntent = null;
@@ -54,20 +54,21 @@
 
     angular.module('ovTopo')
     .factory('TopoProtectedIntentsService',
-        ['FlashService', 'WebSocketService',
+        ['$log', 'FnService', 'FlashService', 'WebSocketService',
 
-        function (_flash_, _wss_) {
+        function (_$log_, _fs_, _flash_, _wss_) {
+            $log = _$log_;
+            fs = _fs_;
             flash = _flash_;
             wss = _wss_;
 
             return {
-                // TODO: Remove references
-                initProtectedIntents: function (_api_) {},
+                initProtectedIntents: function (_api_) { api = _api_; },
                 destroyProtectedIntents: function () { },
 
                 // invoked from toolbar overlay buttons or keystrokes
                 cancelHighlights: cancelHighlights,
-                showProtectedIntent: showProtectedIntent,
+                showProtectedIntent: showProtectedIntent
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoProtectedIntentOverlay.js b/web/gui/src/main/webapp/app/view/topo/topoProtectedIntentOverlay.js
index bfe9afd..ab9114f 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoProtectedIntentOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoProtectedIntentOverlay.js
@@ -38,12 +38,12 @@
         tooltip: 'Protected Intents Overlay',
 
         activate: function () {
-            $log.debug('Protected Intent overlay ACTIVATED');
+            $log.debug("Protected Intent overlay ACTIVATED");
         },
 
         deactivate: function () {
             tpis.cancelHighlights();
-            $log.debug('Protected Intent DEACTIVATED');
+            $log.debug("Protected Intent DEACTIVATED");
         },
 
         hooks: {
@@ -60,8 +60,8 @@
             showIntent: function (info) {
                 $log.debug('^^ topoProtectedIntentsOverlay.showintent() ^^', info);
                 tpis.showProtectedIntent(info);
-            },
-        },
+            }
+        }
     };
 
     // invoke code to register with the overlay service
diff --git a/web/gui/src/main/webapp/app/view/topo/topoSelect.js b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
index 9693755..724b43c 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSelect.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected refs
-    var fs, wss, tov, tps, tts, sus;
+    var $log, fs, wss, tov, tps, tts, ns, sus, tpis;
 
     // api to topoForce
     var api;
@@ -37,11 +37,11 @@
     // internal state
     var hovered, selections, selectOrder, consumeClick;
 
-    function setInitialState() {
-        hovered = null; // the node over which the mouse is hovering
-        selections = {}; // currently selected nodes (by id)
-        selectOrder = []; // the order in which we made selections
-        consumeClick = false; // used to coordinate with SVG click handler
+    function setInitialState () {
+        hovered = null;         // the node over which the mouse is hovering
+        selections = {};        // currently selected nodes (by id)
+        selectOrder = [];       // the order in which we made selections
+        consumeClick = false;   // used to coordinate with SVG click handler
     }
 
     // ==========================
@@ -70,7 +70,7 @@
                 tov.hooks.mouseOver({
                     id: m.id,
                     class: m.class,
-                    type: m.type,
+                    type: m.type
                 });
             }
         }
@@ -185,7 +185,7 @@
     function requestDetails(data) {
         wss.sendEvent('requestDetails', {
             id: data.id,
-            class: data.class,
+            class: data.class
         });
     }
 
@@ -210,7 +210,7 @@
     function singleSelect() {
         var data = getSel(0).obj;
 
-        // the link details are already taken care of in topoLink.js
+        //the link details are already taken care of in topoLink.js
         if (data.class === 'link') {
             return;
         }
@@ -235,14 +235,14 @@
                     id: 'host-flow-btn',
                     gid: 'endstation',
                     cb: tts.addHostIntent,
-                    tt: 'Create Host-to-Host Flow',
+                    tt: 'Create Host-to-Host Flow'
                 });
             } else if (nSel() >= 2) {
                 tps.addAction({
                     id: 'mult-src-flow-btn',
                     gid: 'flows',
                     cb: tts.addMultiSourceIntent,
-                    tt: 'Create Multi-Source Flow',
+                    tt: 'Create Multi-Source Flow'
                 });
             }
         }
@@ -295,7 +295,7 @@
         return {
             devices: devices,
             hosts: hosts,
-            types: types,
+            types: types
         };
     }
 
@@ -304,16 +304,20 @@
 
     angular.module('ovTopo')
     .factory('TopoSelectService',
-        ['FnService', 'WebSocketService', 'TopoOverlayService',
-        'TopoPanelService', 'TopoTrafficService', 'SvgUtilService',
+        ['$log', 'FnService', 'WebSocketService', 'TopoOverlayService',
+            'TopoPanelService', 'TopoTrafficService', 'NavService',
+            'SvgUtilService', 'TopoProtectedIntentsService',
 
-        function (_fs_, _wss_, _tov_, _tps_, _tts_, _sus_) {
+        function (_$log_, _fs_, _wss_, _tov_, _tps_, _tts_, _ns_, _sus_, _tpis_) {
+            $log = _$log_;
             fs = _fs_;
             wss = _wss_;
             tov = _tov_;
             tps = _tps_;
             tts = _tts_;
+            ns = _ns_;
             sus = _sus_;
+            tpis= _tpis_;
 
             function initSelect(_api_) {
                 api = _api_;
@@ -343,7 +347,7 @@
 
                 clickConsumed: clickConsumed,
                 selectionContext: selectionContext,
-                reselect: reselect,
+                reselect: reselect
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoSprite.js b/web/gui/src/main/webapp/app/view/topo/topoSprite.js
index 7c63bfa..0a4785f 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSprite.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSprite.js
@@ -23,11 +23,11 @@
     'use strict';
 
     // injected refs
-    var $log, fs, gs, sus, wss;
+    var $log, $http, fs, gs, sus, wss;
 
     // constants
     var tssid = 'TopoSpriteService: ',
-        fontsize = 20; // default font size 20pt.
+        fontsize = 20;  // default font size 20pt.
 
     // internal state
     var spriteLayer, defsElement;
@@ -76,9 +76,9 @@
     function doSprite(spr, def, pathmeta) {
         var pmeta = pathmeta[def.path],
             c = spr.class || 'gray1',
-            p = spr.pos || [0, 0],
+            p = spr.pos || [0,0],
             lab = spr.label,
-            dim = def.dim || [40, 40],
+            dim = def.dim || [40,40],
             w = dim[0],
             h = dim[1],
             dy = def.labelyoff || 1,
@@ -97,7 +97,7 @@
         attr = {
             width: w,
             height: h,
-            'xlink:href': '#' + pmeta.u,
+            'xlink:href': '#' + pmeta.u
         };
 
         use = g.append('use').attr(attr);
@@ -113,7 +113,7 @@
                     width: w,
                     height: h,
                     'xlink:href': '#' + pmeta.u,
-                    transform: sus.translate(v.pos),
+                    transform: sus.translate(v.pos)
                 };
                 use = g.append('use').attr(attr);
                 applyStrokeStyle(pmeta.s, use);
@@ -130,10 +130,9 @@
 
     function doLabel(label) {
         var c = label.class || 'gray1',
-            p = label.pos || [0, 0],
-            sz = label.size || 1.0;
-
-            spriteLayer.append('g')
+            p = label.pos || [0,0],
+            sz = label.size || 1.0,
+            g = spriteLayer.append('g')
                 .classed(c, true)
                 .attr('transform', sus.translate(p))
                 .append('text')
@@ -175,7 +174,7 @@
         load = data.load;
         pfx = tssid + '[' + name + ']: ';
 
-        $log.debug('Loading sprites...[' + name + ']', desc);
+        $log.debug("Loading sprites...[" + name + "]", desc);
 
         function no(what) {
             warn.push(pfx + 'No ' + what + ' property defined');
@@ -196,7 +195,7 @@
         paths.forEach(function (p) {
             pathmeta[p.tag] = {
                 s: p.stroke,
-                u: p.glyph || 'spr_' + p.tag,
+                u: p.glyph || 'spr_' + p.tag
             };
         });
 
@@ -234,7 +233,7 @@
         $log.info(tssid + 'Requesting sprite definition ['+name+']...');
 
         wss.sendEvent('spriteListRequest');
-        wss.sendEvent('spriteDataRequest', { name: name });
+        wss.sendEvent('spriteDataRequest', {name: name});
     }
 
     // === -----------------------------------------------------
@@ -242,11 +241,12 @@
 
     angular.module('ovTopo')
     .factory('TopoSpriteService',
-        ['$log', 'FnService', 'GlyphService',
+        ['$log', '$http', 'FnService', 'GlyphService',
             'SvgUtilService', 'WebSocketService',
 
-        function (_$log_, _fs_, _gs_, _sus_, _wss_) {
+        function (_$log_, _$http_, _fs_, _gs_, _sus_, _wss_) {
             $log = _$log_;
+            $http = _$http_;
             fs = _fs_;
             gs = _gs_;
             sus = _sus_;
@@ -255,7 +255,7 @@
             return {
                 loadSprites: loadSprites,
                 spriteListResponse: inList,
-                spriteDataResponse: inData,
+                spriteDataResponse: inData
             };
         }]);
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
index 505dabf..82d14ac 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
@@ -42,7 +42,7 @@
 
     // key to button mapping data
     var k2b = {
-        O: { id: 'summary-tog', gid: 'm_summary', isel: true },
+        O: { id: 'summary-tog', gid: 'm_summary', isel: true},
         I: { id: 'instance-tog', gid: 'm_uiAttached', isel: true },
         D: { id: 'details-tog', gid: 'm_details', isel: true },
         H: { id: 'hosts-tog', gid: 'm_endstation', isel: false },
@@ -57,12 +57,12 @@
         L: { id: 'cycleLabels-btn', gid: 'm_cycleLabels' },
         R: { id: 'resetZoom-btn', gid: 'm_resetZoom' },
 
-        E: { id: 'eqMaster-btn', gid: 'm_eqMaster' },
+        E: { id: 'eqMaster-btn', gid: 'm_eqMaster' }
     };
 
     var prohibited = [
         'T', 'backSlash', 'slash',
-        'X', // needed until we re-instate X above.
+        'X' // needed until we re-instate X above.
     ];
     prohibited = prohibited.concat(d3.map(k2b).keys());
 
@@ -79,8 +79,8 @@
             porthl: 1,
             bg: 0,
             spr: 0,
-            ovid: 'traffic', // default to traffic overlay
-            toolbar: 0,
+            ovid: 'traffic',   // default to traffic overlay
+            toolbar: 0
         },
         prefsMap = {
             summary: 'O',
@@ -90,7 +90,7 @@
             offdev: 'M',
             porthl: 'P',
             bg: 'B',
-            spr: 'S',
+            spr: 'S'
             // NOTE: toolbar state is handled separately
         };
 
@@ -125,10 +125,10 @@
     function initKeyData() {
         // TODO: use angular forEach instead of d3.map
         keyData = d3.map(k2b);
-        keyData.forEach(function (key, value) {
+        keyData.forEach(function(key, value) {
             var data = api.getActionEntry(key);
-            value.cb = data[0]; // on-click callback
-            value.tt = data[1] + ' (' + key + ')'; // tooltip
+            value.cb = data[0];                     // on-click callback
+            value.tt = data[1] + ' (' + key + ')';  // tooltip
         });
     }
 
@@ -158,7 +158,7 @@
     }
 
     function addSecondRow() {
-        // addToggle('X');
+        //addToggle('X');
         addToggle('Z');
         addButton('N');
         addButton('L');
@@ -176,7 +176,7 @@
                 tooltip: 'No Overlay',
                 cb: function () {
                     tov.tbSelection(null, switchOverlayActions);
-                },
+                }
             }];
         ovIndex = tov.augmentRbset(rset, switchOverlayActions);
         ovRset = toolbar.addRadioSet('topo-overlays', rset);
@@ -317,7 +317,7 @@
                 toggleToolbar: toggleToolbar,
                 selectOverlay: selectOverlay,
                 defaultPrefs: defaultPrefsState,
-                fnkey: fnkey,
+                fnkey: fnkey
             };
         }]);
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTraffic.js b/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
index 6bde992..11a4dba 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected refs
-    var $log, flash, wss, api;
+    var $log, fs, flash, wss, api;
 
     /*
        API to topoForce
@@ -35,12 +35,12 @@
     var allTrafficTypes = [
             'flowStatsBytes',
             'portStatsBitSec',
-            'portStatsPktSec',
+            'portStatsPktSec'
         ],
         allTrafficMsgs = [
             'Flow Stats (bytes)',
             'Port Stats (bits / second)',
-            'Port Stats (packets / second)',
+            'Port Stats (packets / second)'
         ];
 
     // internal state
@@ -49,6 +49,7 @@
         allTrafficIndex = 0;
 
 
+
     // === -----------------------------------------------------
     //  Helper functions
 
@@ -77,7 +78,7 @@
         if (api.somethingSelected()) {
             wss.sendEvent('requestDeviceLinkFlows', {
                 ids: api.selectOrder(),
-                hover: hoverValid() ? hov.id : '',
+                hover: hoverValid() ? hov.id : ''
             });
         }
     }
@@ -96,7 +97,7 @@
         if (api.somethingSelected()) {
             wss.sendEvent('requestRelatedIntents', {
                 ids: api.selectOrder(),
-                hover: hoverValid() ? hov.id : '',
+                hover: hoverValid() ? hov.id : ''
             });
         }
     }
@@ -120,19 +121,19 @@
         trafficMode = 'allFlowPort';
         hoverMode = null;
         wss.sendEvent('requestAllTraffic', {
-            trafficType: allTrafficTypes[allTrafficIndex],
+            trafficType: allTrafficTypes[allTrafficIndex]
         });
         flash.flash(allTrafficMsgs[allTrafficIndex]);
         allTrafficIndex = (allTrafficIndex + 1) % 3;
     }
 
-    function showDeviceLinkFlows() {
+    function showDeviceLinkFlows () {
         trafficMode = hoverMode = 'flows';
         requestDeviceLinkFlows();
         flash.flash('Device Flows');
     }
 
-    function showRelatedIntents() {
+    function showRelatedIntents () {
         trafficMode = hoverMode = 'intents';
         requestRelatedIntents();
         flash.flash('Related Paths');
@@ -174,25 +175,25 @@
     // === ------------------------------------------------------
     // action buttons on detail panel (multiple selection)
 
-    function addHostIntent() {
+    function addHostIntent () {
         var so = api.selectOrder();
         wss.sendEvent('addHostIntent', {
             one: so[0],
             two: so[1],
-            ids: so,
+            ids: so
         });
         trafficMode = 'intents';
         hoverMode = null;
         flash.flash('Host-to-Host flow added');
     }
 
-    function removeIntent(d) {
+    function removeIntent (d) {
         $log.debug('Entering removeIntent');
         wss.sendEvent('removeIntent', {
             appId: d.appId,
             appName: d.appName,
             key: d.key,
-            purge: d.intentPurge,
+            purge: d.intentPurge
         });
         trafficMode = 'intents';
         hoverMode = null;
@@ -200,32 +201,32 @@
         flash.flash('Intent ' + txt);
     }
 
-    function resubmitIntent(d) {
+    function resubmitIntent (d) {
         $log.debug('Entering resubmitIntent');
         wss.sendEvent('resubmitIntent', {
             appId: d.appId,
             appName: d.appName,
             key: d.key,
-            purge: d.intentPurge,
+            purge: d.intentPurge
         });
         trafficMode = 'intents';
         hoverMode = null;
         flash.flash('Intent resubmitted');
     }
 
-    function addMultiSourceIntent() {
+    function addMultiSourceIntent () {
         var so = api.selectOrder();
         wss.sendEvent('addMultiSourceIntent', {
             src: so.slice(0, so.length - 1),
             dst: so[so.length - 1],
-            ids: so,
+            ids: so
         });
         trafficMode = 'intents';
         hoverMode = null;
         flash.flash('Multi-Source flow added');
     }
 
-    function removeIntents() {
+    function removeIntents () {
         $log.debug('Entering removeIntents');
         wss.sendEvent('removeIntents', {});
         trafficMode = 'intents';
@@ -239,10 +240,11 @@
 
     angular.module('ovTopo')
     .factory('TopoTrafficService',
-        ['$log', 'FnService', 'WebSocketService',
+        ['$log', 'FnService', 'FlashService', 'WebSocketService',
 
-        function (_$log_, _flash_, _wss_) {
+        function (_$log_, _fs_, _flash_, _wss_) {
             $log = _$log_;
+            fs = _fs_;
             flash = _flash_;
             wss = _wss_;
 
@@ -269,7 +271,7 @@
                 addMultiSourceIntent: addMultiSourceIntent,
                 removeIntent: removeIntent,
                 resubmitIntent: resubmitIntent,
-                removeIntents: removeIntents,
+                removeIntents: removeIntents
             };
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
index c395e04..7877e93 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
@@ -41,12 +41,12 @@
         // NOTE: Traffic glyphs already installed as part of the base ONOS set.
 
         activate: function () {
-            $log.debug('Traffic overlay ACTIVATED');
+            $log.debug("Traffic overlay ACTIVATED");
         },
 
         deactivate: function () {
             tts.cancelTraffic(true);
-            $log.debug('Traffic overlay DEACTIVATED');
+            $log.debug("Traffic overlay DEACTIVATED");
         },
 
         // detail panel button definitions
@@ -55,14 +55,14 @@
             showDeviceFlows: {
                 gid: 'm_flows',
                 tt: 'Show Device Flows',
-                cb: function (data) { tts.showDeviceLinkFlows(); },
+                cb: function (data) { tts.showDeviceLinkFlows(); }
             },
 
             showRelatedTraffic: {
                 gid: 'm_relatedIntents',
                 tt: 'Show Related Traffic',
-                cb: function (data) { tts.showRelatedIntents(); },
-            },
+                cb: function (data) { tts.showRelatedIntents(); }
+            }
         },
 
         // key bindings for traffic overlay toolbar buttons
@@ -71,43 +71,43 @@
             0: {
                 cb: function () { tts.cancelTraffic(true); },
                 tt: 'Cancel traffic monitoring',
-                gid: 'm_xMark',
+                gid: 'm_xMark'
             },
 
             A: {
                 cb: function () { tts.showAllTraffic(); },
                 tt: 'Monitor all traffic',
-                gid: 'm_allTraffic',
+                gid: 'm_allTraffic'
             },
             F: {
                 cb: function () { tts.showDeviceLinkFlows(); },
                 tt: 'Show device link flows',
-                gid: 'm_flows',
+                gid: 'm_flows'
             },
             V: {
                 cb: function () { tts.showRelatedIntents(); },
                 tt: 'Show all related intents',
-                gid: 'm_relatedIntents',
+                gid: 'm_relatedIntents'
             },
             leftArrow: {
                 cb: function () { tts.showPrevIntent(); },
                 tt: 'Show previous related intent',
-                gid: 'm_prev',
+                gid: 'm_prev'
             },
             rightArrow: {
                 cb: function () { tts.showNextIntent(); },
                 tt: 'Show next related intent',
-                gid: 'm_next',
+                gid: 'm_next'
             },
             W: {
                 cb: function () { tts.showSelectedIntentTraffic(); },
                 tt: 'Monitor traffic of selected intent',
-                gid: 'm_intentTraffic',
+                gid: 'm_intentTraffic'
             },
 
             _keyOrder: [
-                '0', 'A', 'F', 'V', 'leftArrow', 'rightArrow', 'W',
-            ],
+                '0', 'A', 'F', 'V', 'leftArrow', 'rightArrow', 'W'
+            ]
         },
 
         hooks: {
@@ -146,8 +146,8 @@
             showIntent: function (info) {
                 $log.debug('^^ trafficOverlay.showintent() ^^', info);
                 tts.selectIntent(info);
-            },
-        },
+            }
+        }
     };
 
     // invoke code to register with the overlay service
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2.js b/web/gui/src/main/webapp/app/view/topo2/topo2.js
index 95082f1..db64e14 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.js
@@ -22,10 +22,10 @@
 
 (function () {
     'use strict';
-
+    
     // references to injected services
     var $scope, $log, fs, mast, ks, wss,
-        gs, sus, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms, t2zs;
+        gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms, t2mcs, t2zs;
 
     // DOM elements
     var ovtopo2, svg, defs, zoomLayer, forceG;
@@ -59,11 +59,11 @@
         var sc = zoomer.scale(),
             tr = zoomer.translate(),
             metaUi = isNaN(sc) ? {
-                useCfg: 1,
+                useCfg: 1
             } : {
                 scale: sc,
                 offsetX: tr[0],
-                offsetY: tr[1],
+                offsetY: tr[1]
             };
 
         // Allow map service to react to change in zoom parameters
@@ -74,7 +74,7 @@
 
         wss.sendEvent('updateMeta2', {
             id: 'layoutZoom',
-            memento: metaUi,
+            memento: metaUi
         });
     }
 
@@ -85,7 +85,7 @@
             svg: svg,
             zoomLayer: zoomLayer,
             zoomEnabled: zoomEnabled,
-            zoomCallback: zoomCallback,
+            zoomCallback: zoomCallback
         });
     }
 
@@ -95,20 +95,22 @@
     .controller('OvTopo2Ctrl', [
         '$scope', '$log', '$location',
         'FnService', 'MastService', 'KeyService', 'GlyphService', 'MapService',
-        'SvgUtilService', 'FlashService', 'WebSocketService', 'ThemeService',
+        'SvgUtilService', 'FlashService', 'WebSocketService',
+        'PrefsService', 'ThemeService',
         'Topo2EventService', 'Topo2ForceService', 'Topo2InstanceService',
         'Topo2BreadcrumbService', 'Topo2KeyCommandService', 'Topo2MapService',
-        'Topo2ZoomService', 'Topo2SpriteLayerService',
+        'Topo2MapConfigService', 'Topo2ZoomService', 'Topo2SpriteLayerService',
         'Topo2SummaryPanelService', 'Topo2DeviceDetailsPanel', 'Topo2ToolbarService',
         'Topo2NoDevicesConnectedService', 'Topo2OverlayService',
 
         function (
             _$scope_, _$log_, _$loc_,
             _fs_, _mast_, _ks_, _gs_, _ms_,
-            _sus_, _flash_, _wss_, _th_,
+            _sus_, _flash_, _wss_,
+            _ps_, _th_,
             _t2es_, _t2fs_, _t2is_,
             _t2bcs_, _t2kcs_, _t2ms_,
-            _t2zs_, t2sls,
+            _t2mcs_, _t2zs_, t2sls,
             summaryPanel, detailsPanel, t2tbs, t2ndcs, t2os
         ) {
             var params = _$loc_.search(),
@@ -116,7 +118,7 @@
                 wh,
                 uplink = {
                     zoomLayer: function () { return zoomLayer; },
-                    zoomer: function () { return zoomer; },
+                    zoomer: function () { return zoomer; }
                 };
 
             $scope = _$scope_;
@@ -128,6 +130,7 @@
             wss = _wss_;
             gs = _gs_;
             sus = _sus_;
+            ps = _ps_;
 
             t2es = _t2es_;
             t2fs = _t2fs_;
@@ -135,6 +138,7 @@
             t2bcs = _t2bcs_;
             t2kcs = _t2kcs_;
             t2ms = _t2ms_;
+            t2mcs = _t2mcs_;
             t2zs = _t2zs_;
 
             // capture selected intent parameters (if they are set in the
@@ -148,7 +152,7 @@
                     key: params.intentKey,
                     appId: params.intentAppId,
                     appName: params.intentAppName,
-                    intentType: params.intentType,
+                    intentType: params.intentType
                 };
             }
 
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Background.js b/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
index 127ba86..902ebdc 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
@@ -116,10 +116,10 @@
                     resetZoom: function () {
                         var pan = zoomPan(this.zoomData, true);
                         t2zs.panAndZoom(pan, zoomScale(this.zoomData, true), 1000);
-                    },
+                    }
                 });
 
                 return instance || new BackgroundView();
-            },
+            }
         ]);
-})();
+})();
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Badge.js b/web/gui/src/main/webapp/app/view/topo2/topo2Badge.js
index e602aab..429627e 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Badge.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Badge.js
@@ -20,4 +20,4 @@
  usage: new NodeBadge({text, icon}, DOM Element, Node);
  */
 
-// TODO: Create a badge class
+// TODO: Create a badge class
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js b/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js
index 3ff7932..d2a1391 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js
@@ -23,11 +23,12 @@
 
     'use strict';
 
-    var t2rns;
+    var $log, $loc, wss, t2rns;
 
     // Internal
     var breadcrumbContainer,
-        breadcrumbs;
+        breadcrumbs,
+        layout;
 
     function init() {
         breadcrumbs = [];
@@ -95,21 +96,27 @@
             });
     }
 
-    // TODO: Remove references
-    function addLayout(_layout_) {}
+    function addLayout(_layout_) {
+        layout = _layout_;
+    }
 
     angular.module('ovTopo2')
     .factory('Topo2BreadcrumbService', [
+        '$log', '$location', 'WebSocketService',
         'Topo2RegionNavigationService',
-        function (_t2rns_) {
+        function (_$log_, _$loc_, _wss_, _t2rns_) {
+
+            $log = _$log_;
+            $loc = _$loc_;
+            wss = _wss_;
             t2rns = _t2rns_;
 
             return {
                 init: init,
                 addBreadcrumb: addBreadcrumb,
                 addLayout: addLayout,
-                hide: hide,
+                hide: hide
             };
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js b/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js
index f4790bd..3218988 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js
@@ -116,7 +116,7 @@
             return this.models.map(function (model) {
                 return model.toJSON(options);
             });
-        },
+        }
     };
 
     angular.module('ovTopo2')
@@ -126,7 +126,7 @@
                 Collection.extend = fn.extend;
                 Model = _Model_;
                 return Collection;
-            },
+            }
         ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2DetailsPanel.js b/web/gui/src/main/webapp/app/view/topo2/topo2DetailsPanel.js
index 9ed6a0e..fd55a08 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2DetailsPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2DetailsPanel.js
@@ -43,7 +43,7 @@
         panelPadding = 64,
         panelSpacing = 20,
         panelOpts = {
-            width: 260, // summary and detail panel width
+            width: 260          // summary and detail panel width
         };
 
     function getInstance(_summaryPanel_) {
@@ -54,7 +54,7 @@
         summaryPanel = _summaryPanel_;
 
         var options = angular.extend({}, panelOpts, {
-            class: className,
+            class: className
         });
 
         Panel = Panel.extend({
@@ -84,7 +84,7 @@
                 detailsPanel.el.el()
                     .style('top', panelPadding + position + 'px');
                 detailsPanel.el.show();
-            },
+            }
         });
 
         detailsPanel = new Panel(id, options);
@@ -94,6 +94,7 @@
     }
 
 
+
     angular.module('ovTopo2')
     .factory('Topo2DetailsPanelService', [
         'Topo2PanelService',
@@ -101,6 +102,6 @@
             Panel = _ps_;
 
             return getInstance;
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Device.js b/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
index ae8ebd9..8f7edd9 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
@@ -26,13 +26,13 @@
 
     var remappedDeviceTypes = {
         switch: 'm_switch',
-        virtual: 'cord',
+        virtual: 'cord'
     };
 
     function createDeviceCollection(data) {
 
         var DeviceCollection = Collection.extend({
-            model: Model,
+            model: Model
         });
 
         var devices = [];
@@ -58,7 +58,7 @@
                     nodeType: 'device',
                     multiSelectEnabled: true,
                     events: {
-                        'click': 'onClick',
+                        'click': 'onClick'
                     },
 
                     initialize: function () {
@@ -88,7 +88,7 @@
                         var id = this.mastershipService.mastership(),
                             suppress = id ? this.get('master') !== id : false;
 
-                        this.set({ mastership: suppress });
+                        this.set({mastership: suppress});
                     },
                     setOfflineVisibility: function () {
                         var showOffline = ps.getPrefs('topo2_prefs')['offline_devices'],
@@ -107,13 +107,13 @@
                             .style('stroke-fill', '#555')
                             .style('fill', '#888')
                             .style('opacity', 0.5);
-                    },
+                    }
                 });
 
                 return {
-                    createDeviceCollection: createDeviceCollection,
+                    createDeviceCollection: createDeviceCollection
                 };
-            },
+            }
         ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2DeviceDetailsPanel.js b/web/gui/src/main/webapp/app/view/topo2/topo2DeviceDetailsPanel.js
index 1ff054c..3cacf8b 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2DeviceDetailsPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2DeviceDetailsPanel.js
@@ -32,35 +32,35 @@
     var id = 'topo2-p-detail',
         devicePath = 'device',
         handlerMap = {
-            'showDetails': showDetails,
+            'showDetails': showDetails
         };
 
     var coreButtons = {
         showDeviceView: {
             gid: 'switch',
             tt: 'Show Device View',
-            path: 'device',
+            path: 'device'
         },
         showFlowView: {
             gid: 'flowTable',
             tt: 'Show Flow View for this Device',
-            path: 'flow',
+            path: 'flow'
         },
         showPortView: {
             gid: 'portTable',
             tt: 'Show Port View for this Device',
-            path: 'port',
+            path: 'port'
         },
         showGroupView: {
             gid: 'groupTable',
             tt: 'Show Group View for this Device',
-            path: 'group',
+            path: 'group'
         },
         showMeterView: {
             gid: 'meterTable',
             tt: 'Show Meter View for this Device',
-            path: 'meter',
-        },
+            path: 'meter'
+        }
     };
 
     function init(summaryPanel) {
@@ -94,7 +94,7 @@
                     id: 'core-' + id,
                     gid: gid,
                     tt: tt,
-                    cb: function () { ns.navTo(path, { devId: devId }); },
+                    cb: function () { ns.navTo(path, { devId: devId }); }
                 });
             }
         });
@@ -168,7 +168,7 @@
     function updateDetails(id, nodeType) {
         wss.sendEvent('requestDetails', {
             id: id,
-            class: nodeType,
+            class: nodeType
         });
     }
 
@@ -223,8 +223,8 @@
                 hide: hide,
                 destroy: destroy,
                 isVisible: function () { return detailsPanel.isVisible(); },
-                getInstance: function () { return detailsPanel; },
+                getInstance: function () { return detailsPanel; }
             };
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Event.js b/web/gui/src/main/webapp/app/view/topo2/topo2Event.js
index fc245f4..e8b8eac 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Event.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Event.js
@@ -98,7 +98,7 @@
             return {
                 bindHandlers: bindHandlers,
                 start: start,
-                stop: stop,
+                stop: stop
             };
         }]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Force.js b/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
index c75935e..b18ff32 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
@@ -26,7 +26,10 @@
     var $log, $loc, wss;
 
     var t2is, t2rs, t2ls, t2vs, t2bcs, t2ss, t2bgs, t2tbs, t2mss;
-    var svg, uplink, dim, opts, zoomer;
+    var svg, forceG, uplink, dim, opts, zoomer;
+
+    // D3 Selections
+    var node;
 
     // ========================== Helper Functions
 
@@ -60,7 +63,7 @@
         $log.debug('navToBookmarkedRegion:', regionId);
         if (regionId) {
             wss.sendEvent('topo2navRegion', {
-                rid: regionId,
+                rid: regionId
             });
 
             t2ls.createForceElements();
@@ -220,7 +223,7 @@
                 updateNodes: updateNodes,
                 updateLinks: updateLinks,
                 resetNodeLocation: resetNodeLocation,
-                unpin: unpin,
+                unpin: unpin
             };
         }]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Host.js b/web/gui/src/main/webapp/app/view/topo2/topo2Host.js
index a1eff3d..ed3a981 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Host.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Host.js
@@ -32,7 +32,7 @@
     function createHostCollection(data, region) {
 
         var HostCollection = Collection.extend({
-            model: Model,
+            model: Model
         });
 
         var hosts = [];
@@ -57,7 +57,7 @@
 
                 nodeType: 'host',
                 events: {
-                    'click': 'onClick',
+                    'click': 'onClick'
                 },
                 initialize: function () {
                     this.super = this.constructor.__super__;
@@ -69,7 +69,7 @@
                         this.el.attr('class', this.svgClassName());
                     }
                 },
-                showDetails: function () {
+                showDetails: function() {
                     t2hds.displayPanel(this);
                 },
                 icon: function () {
@@ -118,7 +118,7 @@
                         width: glyphSize,
                         height: glyphSize,
                         x: -glyphSize / 2,
-                        y: -glyphSize / 2,
+                        y: -glyphSize / 2
                     });
 
                     var labelText = this.label();
@@ -132,13 +132,13 @@
                     this.setScale();
                     this.setUpEvents();
                     this.setVisibility();
-                },
+                }
             });
 
             return {
-                createHostCollection: createHostCollection,
+                createHostCollection: createHostCollection
             };
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2HostsPanel.js b/web/gui/src/main/webapp/app/view/topo2/topo2HostsPanel.js
index 410c9ee..fcc3f31 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2HostsPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2HostsPanel.js
@@ -40,8 +40,8 @@
                 '-': '',
                 'MAC': data.get('id'),
                 'IP': data.get('ips')[0],
-                'VLAN': 'None', // TODO: VLAN is not currently in the data received from backend
-            },
+                'VLAN': 'None' // TODO: VLAN is not currently in the data received from backend
+            }
         };
 
         if (data.get('location')) {
@@ -111,9 +111,9 @@
                 hide: hide,
                 toggle: toggle,
                 destroy: destroy,
-                isVisible: function () { return hostPanel.isVisible(); },
+                isVisible: function () { return hostPanel.isVisible(); }
             };
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Instance.js b/web/gui/src/main/webapp/app/view/topo2/topo2Instance.js
index de7c09e..044e3d6 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Instance.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Instance.js
@@ -4,12 +4,15 @@
     // injected refs
     var $log, ps, sus, gs, flash, ts, t2mss;
 
+    // api from topo
+    var api;
+
     // configuration
     var showLogicErrors = true,
         idIns = 'topo2-p-instance',
         instOpts = {
             edge: 'left',
-            width: 20,
+            width: 20
         };
 
     // internal state
@@ -94,24 +97,24 @@
             instSvg = {
                 width: 170,
                 height: 85,
-                viewBox: '0 0 170 85',
+                viewBox: '0 0 170 85'
             },
             headRect = {
                 x: rox,
                 y: roy,
                 width: rw,
-                height: rhh,
+                height: rhh
             },
             bodyRect = {
                 x: rox,
                 y: roy + rhh,
                 width: rw,
-                height: rbh,
+                height: rbh
             },
             titleAttr = {
                 class: 'instTitle',
                 x: tx,
-                y: 27,
+                y: 27
             };
 
         var onoses = oiBox.el().selectAll('.onosInst')
@@ -177,7 +180,7 @@
                 svg.append('text').attr({
                     class: 'instLabel ' + id,
                     x: tx,
-                    y: ty,
+                    y: ty
                 }).text(label);
                 ty += 18;
             }
@@ -212,7 +215,8 @@
         }
     }
 
-    function initInst() {
+    function initInst(_api_) {
+        api = _api_;
         oiBox = ps.createPanel(idIns, instOpts);
         oiBox.show();
 
@@ -282,9 +286,9 @@
                     allInstances: allInstances,
                     destroy: destroy,
                     toggle: toggle,
-                    isVisible: function () { return oiBox.isVisible(); },
+                    isVisible: function () { return oiBox.isVisible(); }
                 };
-            },
+            }
         ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
index 554ee06..939b9d2 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
@@ -18,7 +18,7 @@
 
     // Injected Services
     var $log, fs, ks, flash, wss, t2ps, t2bgs, ps, t2is, t2sp, t2vs, t2rs,
-        t2fs, t2tbs;
+        t2fs, t2sls, t2tbs;
 
     // Commmands
     function actionMap() {
@@ -38,8 +38,8 @@
 
             esc: handleEscape,
 
-            _keyListener: t2tbs.keyListener.bind(t2tbs),
-        };
+            _keyListener: t2tbs.keyListener.bind(t2tbs)
+        }
     }
 
     function init(_t2fs_, _t2tbs_) {
@@ -74,7 +74,7 @@
             ['shift-click', 'Toggle selection state'],
             ['drag', 'Reposition (and pin) device / host'],
             ['cmd-scroll', 'Zoom in / out'],
-            ['cmd-drag', 'Pan'],
+            ['cmd-drag', 'Pan']
         ]);
     }
 
@@ -170,12 +170,12 @@
 
     function toggleHosts() {
         var on = t2rs.toggleHosts();
-        actionedFlashed(on ? 'Show': 'Hide', 'Hosts');
+        actionedFlashed(on ? 'Show': 'Hide', 'Hosts')
     }
 
     function toggleOfflineDevices() {
         var on = t2rs.toggleOfflineDevices();
-        actionedFlashed(on ? 'Show': 'Hide', 'offline devices');
+        actionedFlashed(on ? 'Show': 'Hide', 'offline devices')
     }
 
     function notValid(what) {
@@ -204,10 +204,10 @@
         '$log', 'FnService', 'KeyService', 'FlashService', 'WebSocketService',
         'Topo2PrefsService', 'Topo2BackgroundService', 'PrefsService',
         'Topo2InstanceService', 'Topo2SummaryPanelService', 'Topo2ViewService',
-        'Topo2RegionService',
+        'Topo2RegionService', 'Topo2SpriteLayerService',
 
         function (_$log_, _fs_, _ks_, _flash_, _wss_, _t2ps_, _t2bgs_, _ps_,
-                  _t2is_, _t2sp_, _t2vs_, _t2rs_) {
+                  _t2is_, _t2sp_, _t2vs_, _t2rs_, _t2sls_) {
 
             $log = _$log_;
             fs = _fs_;
@@ -221,12 +221,13 @@
             t2sp = _t2sp_;
             t2vs = _t2vs_;
             t2rs = _t2rs_;
+            t2sls = _t2sls_;
 
             return {
                 init: init,
                 bindCommands: bindCommands,
-                getActionEntry: getActionEntry,
+                getActionEntry: getActionEntry
             };
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Label.js b/web/gui/src/main/webapp/app/view/topo2/topo2Label.js
index e00febd..28f134c 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Label.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Label.js
@@ -25,20 +25,20 @@
     var defaultStyles = {
         label: {
             text: {
-                fill: '#000000',
+                fill: '#000000'
             },
             rect: {
-                fill: '#ffffff',
-            },
+                fill: '#ffffff'
+            }
         },
         icon: {
             glyph: {
-                fill: '#000000',
+                fill: '#000000'
             },
             rect: {
-                fill: '#ffffff',
-            },
-        },
+                fill: '#ffffff'
+            }
+        }
     };
 
     angular.module('ovTopo2')
@@ -69,9 +69,9 @@
                             this._labelG.text.text(this.get('label'));
                             this._labelG.rect.attr({
                                 width: width,
-                                height: height,
+                                height: height
                             }).style({
-                                transform: sus.translate(-(width/2) + 'px', -(height/2) + 'px'),
+                                transform: sus.translate(-(width/2) + 'px', -(height/2) + 'px')
                             });
                         }
                     },
@@ -108,9 +108,9 @@
 
                         this._labelG.rect.attr({
                             width: this._labelG.text.node().getBBox().width + 20,
-                            height: this._labelG.text.node().getBBox().height + 10,
+                            height: this._labelG.text.node().getBBox().height + 10
                         }).style({
-                            transform: sus.translate('-50%', '-50%'),
+                            transform: sus.translate('-50%', '-50%')
                         });
                     },
                     renderIcon: function () {
@@ -123,7 +123,7 @@
                         this._iconG.rect = this._iconG.el.append('rect')
                             .attr({
                                 width: this.iconSize,
-                                height: this.iconSize,
+                                height: this.iconSize
                             });
 
                         this._iconG.glyph = is.addDeviceIcon(this._iconG.el,
@@ -131,9 +131,9 @@
 
 
                         var iconX = (-bbox.width / 2) - this.iconSize + 'px',
-                            iconY = -this.iconSize /2 + 'px';
+                            iconY = -this.iconSize /2  + 'px';
                         this._iconG.el.style({
-                            transform: sus.translate(iconX, iconY),
+                            transform: sus.translate(iconX, iconY)
                         });
                     },
                     beforeRender: function () {},
@@ -141,7 +141,7 @@
                         this.el = this.parent.append('g')
                             .attr('class', 'topo2-label')
                             .style({
-                                transform: 'translate(300px, 300px)',
+                                transform: 'translate(300px, 300px)'
                             });
 
                         this.content = this.el.append('g')
@@ -160,8 +160,8 @@
                     afterRender: function () {},
                     remove: function () {
                         this.el.remove();
-                    },
+                    }
                 });
-            },
+            }
         ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2LabelCollection.js b/web/gui/src/main/webapp/app/view/topo2/topo2LabelCollection.js
index 64c5a55..ba05bb5 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2LabelCollection.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2LabelCollection.js
@@ -36,13 +36,13 @@
                         if (this._byId[label.id]) {
                             this.get(label.id).set(label);
                         } else {
-                            var lab = new Model(label, targetNode, options);
+                            var lab = new Model(label, targetNode, options)
                             this.add(lab);
                         }
-                    },
+                    }
                 });
 
                 return instance || new LabelCollection();
-            },
+            }
         ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
index 7be4c6a..a64a75b 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
@@ -34,20 +34,20 @@
             device: -8000,
             host: -20000,
             region: -8000,
-            _def_: -12000,
+            _def_: -12000
         },
         linkDistance: {
             // note: key is link.type
             direct: 100,
             optical: 120,
             UiEdgeLink: 100,
-            _def_: 50,
+            _def_: 50
         },
         linkStrength: {
             // note: key is link.type
             // range: {0.0 ... 1.0}
-            _def_: 1.0,
-        },
+            _def_: 1.0
+        }
     };
 
     // configuration
@@ -55,20 +55,20 @@
         light: {
             baseColor: '#939598',
             inColor: '#66f',
-            outColor: '#f00',
+            outColor: '#f00'
         },
         dark: {
             // TODO : theme
             baseColor: '#939598',
             inColor: '#66f',
-            outColor: '#f00',
+            outColor: '#f00'
         },
         inWidth: 12,
-        outWidth: 10,
+        outWidth: 10
     };
 
     // internal state
-    var nodeLock = false; // whether nodes can be dragged or not (locked)
+    var nodeLock = false;       // whether nodes can be dragged or not (locked)
 
     // predicate that indicates when clicking is active
     function clickEnabled() {
@@ -117,7 +117,7 @@
                             linkLabelG: this.addElement(this.forceG, 'topo2-linkLabels'),
                             numLinksLabels: this.addElement(this.forceG, 'topo2-numLinkLabels'),
                             nodeG: this.addElement(this.forceG, 'topo2-nodes'),
-                            portLabels: this.addElement(this.forceG, 'topo2-portLabels'),
+                            portLabels: this.addElement(this.forceG, 'topo2-portLabels')
                         };
                     },
                     addElement: function (parent, className) {
@@ -138,7 +138,7 @@
                             .linkStrength(this.settingOrDefault.bind(this, 'linkStrength'))
                             .nodes([])
                             .links([])
-                            .on('tick', this.tick.bind(this))
+                            .on("tick", this.tick.bind(this))
                             .start();
 
                         this.drag = sus.createDragBehavior(this.force,
@@ -173,15 +173,15 @@
                                     var dx = isNaN(d.x) ? 0 : d.x,
                                         dy = isNaN(d.y) ? 0 : d.y;
                                     return sus.translate(dx, dy);
-                                },
+                                }
                             });
 
                         this.link
                             .each(this.setLinkPosition)
-                            .attr('x1', function (d) { return d.get('position').x1; })
-                            .attr('y1', function (d) { return d.get('position').y1; })
-                            .attr('x2', function (d) { return d.get('position').x2; })
-                            .attr('y2', function (d) { return d.get('position').y2; });
+                            .attr("x1", function (d) { return d.get('position').x1; })
+                            .attr("y1", function (d) { return d.get('position').y1; })
+                            .attr("x2", function (d) { return d.get('position').x2; })
+                            .attr("y2", function (d) { return d.get('position').y2; });
                     },
 
                     start: function () {
@@ -215,13 +215,13 @@
                                     // Need to guard against NaN here ??
                                     return sus.translate(d.node.x, d.node.y);
                                 },
-                                opacity: 0,
+                                opacity: 0
                             })
                             .call(this.drag)
                             .transition()
                             .attr('opacity', 1);
 
-                        entering.each(function (d) { d.onEnter(this, d); });
+                        entering.each(function (d) { d.onEnter(this, d) });
 
                         this.force.nodes(regionNodes);
                     },
@@ -242,10 +242,10 @@
                                 x2: function (d) { return d.get('position').x2; },
                                 y2: function (d) { return d.get('position').y2; },
                                 stroke: linkConfig.light.inColor,
-                                'stroke-width': linkConfig.inWidth,
+                                'stroke-width': linkConfig.inWidth
                             });
 
-                        entering.each(function (d) { d.onEnter(this, d); });
+                        entering.each(function (d) { d.onEnter(this, d) });
 
                         // operate on exiting links:
                         this.link.exit()
@@ -280,15 +280,15 @@
                                 y: d.y,
                                 equivLoc: {
                                     lng: ll[0],
-                                    lat: ll[1],
-                                },
+                                    lat: ll[1]
+                                }
                             };
                         }
                         d.metaUi = metaUi;
                         wss.sendEvent('updateMeta2', {
                             id: d.get('id'),
                             class: d.get('class'),
-                            memento: metaUi,
+                            memento: metaUi
                         });
                     },
                     setDimensions: function () {
@@ -341,12 +341,12 @@
                             .style('opacity', 1)
                             .each('end', function () {
                                 t2rns.navigateToRegionComplete();
-                            }); ;
+                            });;
                     },
                     navigateToRegionHandler: function () {
                         this.createForceElements();
                         this.transitionDownRegion();
-                    },
+                    }
                 });
 
                 function getInstance(svg, forceG, uplink, dim, zoomer, opts) {
@@ -354,7 +354,7 @@
                 }
 
                 return getInstance();
-            },
+            }
         ]
     );
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
index 9a25894..6954920 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
@@ -39,16 +39,16 @@
         light: {
             baseColor: '#939598',
             inColor: '#66f',
-            outColor: '#f00',
+            outColor: '#f00'
         },
         dark: {
             // TODO : theme
             baseColor: '#939598',
             inColor: '#66f',
-            outColor: '#f00',
+            outColor: '#f00'
         },
         inWidth: 12,
-        outWidth: 10,
+        outWidth: 10
     };
 
     function createLink() {
@@ -62,8 +62,8 @@
                 x1: 0,
                 y1: 0,
                 x2: 0,
-                y2: 0,
-            },
+                y2: 0
+            }
             // functions to aggregate dual link state
             // extra: link.extra
         });
@@ -109,7 +109,7 @@
 
         return {
             source: sourceNode,
-            target: targetNode,
+            target: targetNode
         };
     }
 
@@ -134,7 +134,7 @@
                     {
                         enhanced: this.get('enhanced'),
                         selected: this.get('selected'),
-                        suppressedmax: this.get('mastership'),
+                        suppressedmax: this.get('mastership')
                     },
                     (this.linkLabel) ? this.linkLabel.linkLabelCSSClass() : null
                 );
@@ -168,7 +168,7 @@
                     point = this.locatePortLabel();
                     angular.extend(point, {
                         id: 'topo2-port-tgt',
-                        num: this.get('portB'),
+                        num: this.get('portB')
                     });
                     data.push(point);
 
@@ -176,7 +176,7 @@
                         point = this.locatePortLabel(1);
                         angular.extend(point, {
                             id: 'topo2-port-src',
-                            num: this.get('portA'),
+                            num: this.get('portA')
                         });
                         data.push(point);
                     }
@@ -224,8 +224,8 @@
                     x1: this.get('source').x,
                     y1: this.get('source').y,
                     x2: this.get('target').x,
-                    y2: this.get('target').y,
-                };
+                    y2: this.get('target').y
+                }
             },
             calcMovement: function (amt, flipped) {
                 var pos = this.defaultPosition(),
@@ -238,7 +238,7 @@
                     x1: pos.x1 + (mult * dy / length),
                     y1: pos.y1 + (mult * -dx / length),
                     x2: pos.x2 + (mult * dy / length),
-                    y2: pos.y2 + (mult * -dx / length),
+                    y2: pos.y2 + (mult * -dx / length)
                 };
             },
             setPosition: function () {
@@ -282,7 +282,7 @@
             deselect: function () {
                 this.set({
                     'selected': false,
-                    'enhanced': false,
+                    'enhanced': false
                 });
             },
             showDetails: function () {
@@ -394,7 +394,7 @@
                 this.el.style('visibility', visible ? 'visible' : 'hidden');
             },
             displayMastership: function () {
-                this.set({ mastership: t2mss.mastership() !== null });
+                this.set({ mastership: t2mss.mastership() !== null});
             },
             remove: function () {
 
@@ -407,11 +407,11 @@
                     .transition()
                     .delay(1000)
                     .style('opacity', 0);
-            },
+            }
         });
 
         var LinkCollection = Collection.extend({
-            model: LinkModel,
+            model: LinkModel
         });
 
         return new LinkCollection(data);
@@ -444,8 +444,8 @@
             t2ts = _t2ts_;
 
             return {
-                createLinkCollection: createLinkCollection,
+                createLinkCollection: createLinkCollection
             };
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2LinkLabel.js b/web/gui/src/main/webapp/app/view/topo2/topo2LinkLabel.js
index 162eb2c..66b06e5 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2LinkLabel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2LinkLabel.js
@@ -47,7 +47,7 @@
                         var link = this.link;
                         this.set({
                             x: (link.source.x + link.target.x) / 2,
-                            y: (link.source.y + link.target.y) / 2,
+                            y: (link.source.y + link.target.y) / 2
                         });
                     },
                     setScale: function () {
@@ -61,8 +61,8 @@
                         this.link.linkLabel = null;
                         this.link.onChange();
                         this.constructor.__super__.remove.apply(this, arguments);
-                    },
+                    }
                 });
-            },
+            }
         ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2LinkPanel.js b/web/gui/src/main/webapp/app/view/topo2/topo2LinkPanel.js
index a5b570d..b3a7a5b 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2LinkPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2LinkPanel.js
@@ -42,7 +42,7 @@
             propOrder: [
                 'Type', '-',
                 'A Type', 'A Id', 'A Label', 'A Port', '-',
-                'B Type', 'B Id', 'B Label', 'B Port',
+                'B Type', 'B Id', 'B Label', 'B Port'
             ],
             props: {
                 '-': '',
@@ -54,8 +54,8 @@
                 'B Type': target.get('nodeType'),
                 'B Id': target.get('id'),
                 'B Label': target.get('props').name,
-                'B Port': data.get('portB') || 'N/A',
-            },
+                'B Port': data.get('portB') || 'N/A'
+            }
         };
     }
 
@@ -117,9 +117,9 @@
                 hide: hide,
                 toggle: toggle,
                 destroy: destroy,
-                isVisible: function () { return linkPanel.isVisible(); },
+                isVisible: function () { return linkPanel.isVisible(); }
             };
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
index 202a1cf..002ca69 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
@@ -23,13 +23,14 @@
     'use strict';
 
     // Injected Services
-    var t2zs, countryFilters, ms;
+    var $log, $loc, ps, ms, flash, sus, t2zs, countryFilters;
 
     // internal state
-    var instance, zoomer, currentMap;
+    var instance, mapG, zoomLayer, zoomer, currentMap;
 
     function init() {
         this.appendElement('#topo2-background', 'g');
+        zoomLayer = d3.select('#topo2-zoomlayer');
         zoomer = t2zs.getZoomer();
         currentMap = null;
     }
@@ -37,7 +38,7 @@
     function setUpMap(mapId, mapFilePath, mapScale) {
 
         if (currentMap === mapId) {
-            return new Promise(function (resolve) {
+            return new Promise(function(resolve) {
                 resolve();
             });
         }
@@ -47,7 +48,7 @@
         var loadMap = ms.loadMapInto,
             promise, cfilter;
 
-        this.node().selectAll('*').remove();
+        this.node().selectAll("*").remove();
 
         if (mapFilePath === '*countries') {
             cfilter = countryFilters[mapId] || countryFilters.uk;
@@ -57,7 +58,7 @@
         promise = loadMap(this.node(), mapFilePath, mapId, {
             countryFilters: cfilter,
             adjustScale: mapScale || 1,
-            shading: '',
+            shading: ''
         });
 
         return promise;
@@ -79,11 +80,19 @@
 
     angular.module('ovTopo2')
     .factory('Topo2MapService', [
-        'Topo2ZoomService', 'MapService', 'Topo2ViewController',
+        '$log', '$location', 'Topo2ViewController', 'PrefsService',
+        'MapService', 'FlashService', 'SvgUtilService', 'Topo2ZoomService',
 
-        function (_t2zs_, _ms_, ViewController) {
-            t2zs = _t2zs_;
+        function (_$log_, _$loc_, ViewController, _ps_,
+                  _ms_, _flash_, _sus_, _t2zs_) {
+
+            $log = _$log_;
+            $loc = _$loc_;
+            ps = _ps_;
             ms = _ms_;
+            flash = _flash_;
+            sus = _sus_;
+            t2zs = _t2zs_;
 
             var MapLayer = ViewController.extend({
 
@@ -94,10 +103,10 @@
                 setUpMap: setUpMap,
                 resetZoom: resetZoom,
                 zoomCallback: zoomCallback,
-                getCurrentMap: getCurrentMap,
+                getCurrentMap: getCurrentMap
             });
 
             return instance || new MapLayer();
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js b/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js
index 9ffa8f7..ffb7f86 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2MapConfig.js
@@ -31,7 +31,7 @@
     function projection(x) {
         if (x) {
             proj = x;
-            $log.debug('Set the projection');
+            $log.debug("Set the projection");
         }
         return proj;
     }
@@ -44,9 +44,9 @@
                 $log = _$log_;
 
                 return {
-                    projection: projection,
+                    projection: projection
                 };
-            },
+            }
         ]
     );
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Mastership.js b/web/gui/src/main/webapp/app/view/topo2/topo2Mastership.js
index 1fef792..7b1735f 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Mastership.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Mastership.js
@@ -49,10 +49,10 @@
                     setMastership: function (id) {
                         this.currentMastership = id;
                         this.displayMastership();
-                    },
-                };
+                    }
+                }
 
                 return instance || new MastershipController();
-            },
+            }
         ]);
-})();
+})();
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Model.js b/web/gui/src/main/webapp/app/view/topo2/topo2Model.js
index 56941f4..6da29c4 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Model.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Model.js
@@ -117,7 +117,7 @@
             if (this.collection) {
                 this.collection.remove(this);
             }
-        },
+        }
     };
 
     angular.module('ovTopo2')
@@ -127,6 +127,6 @@
             Model.extend = fn.extend;
 
             return Model;
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NoDevicesConnected.js b/web/gui/src/main/webapp/app/view/topo2/topo2NoDevicesConnected.js
index 0d9e670..d0c08d3 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NoDevicesConnected.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NoDevicesConnected.js
@@ -36,7 +36,7 @@
                         instance = this;
                         this.appendElement('#topo2', 'g')
                             .attr({
-                                transform: sus.translate(500, 500),
+                                transform: sus.translate(500, 500)
                             });
 
                         this.render();
@@ -49,16 +49,16 @@
                         g = this.node().append('g');
                         gs.addGlyph(g, 'bird', 100).attr('class', 'noDevsBird');
                         g.append('text').text('No devices are connected')
-                            .attr({ x: 120, y: 80 });
+                            .attr({ x: 120, y: 80});
 
                         box = g.node().getBBox();
                         box.x -= box.width/2;
                         box.y -= box.height/2;
                         g.attr('transform', sus.translate(box.x, box.y));
-                    },
+                    }
                 });
 
                 return instance || new NoDevicesConnected();
-            },
+            }
         ]);
-})();
+})();
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
index 9b275c9..7498696 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -35,18 +35,18 @@
     var dColTheme = {
             light: {
                 online: '#444444',
-                offline: '#cccccc',
+                offline: '#cccccc'
             },
             dark: {
                 // TODO: theme
                 online: '#444444',
-                offline: '#cccccc',
-            },
+                offline: '#cccccc'
+            }
         },
         // and here are the stroke colors of the glyph, per theme
         dUseTheme = {
             light: 'white',
-            dark: 'black',
+            dark: 'black'
         };
 
     angular.module('ovTopo2')
@@ -72,7 +72,7 @@
                     this.mastershipService = t2mss;
                     this._events = {
                         'mouseover': 'mouseoverHandler',
-                        'mouseout': 'mouseoutHandler',
+                        'mouseout': 'mouseoutHandler'
                     };
                 },
                 select: function () {
@@ -162,7 +162,7 @@
                         x: -dim / 2 - labelPad,
                         y: -dim / 2 - labelPad,
                         width: dim + labelWidth + (labelPad * 2) + _textPad,
-                        height: dim + (labelPad * 2),
+                        height: dim + (labelPad * 2)
                     };
                 },
                 iconBox: function (dim, labelWidth) {
@@ -170,7 +170,7 @@
                         x: -dim / 2,
                         y: -dim / 2,
                         width: dim + labelWidth,
-                        height: dim,
+                        height: dim
                     };
                 },
                 svgClassName: function () {
@@ -182,7 +182,7 @@
                             selected: this.get('selected'),
                             hovered: this.get('hovered'),
                             fixed: this.get('fixed'),
-                            suppressedmax: this.get('mastership'),
+                            suppressedmax: this.get('mastership')
                         }
                     );
                 },
@@ -194,7 +194,7 @@
                     t2nps.setLongLat(this);
                 },
                 displayMastership: function () {
-                    this.set({ mastership: t2mss.mastership() !== null });
+                    this.set({ mastership: t2mss.mastership() !== null});
                 },
                 update: function () {
                     this.updateLabel();
@@ -247,7 +247,7 @@
 
                     return {
                         rect: rect,
-                        text: text,
+                        text: text
                     };
                 },
                 addIconElements: function (el) {
@@ -256,7 +256,7 @@
                         glyph;
 
                     var iconG = el.append('g')
-                        .attr('class', 'icon');
+                        .attr('class', 'icon')
 
                     iconG.append('rect')
                         .attr('class', 'icon-rect')
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js
index 1b7a88c..8889168 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js
@@ -72,7 +72,7 @@
             if (!loc.latOrY && !loc.longOrX) {
                 loc = {
                     longOrX: -20,
-                    latOrY: 10 * node.index(),
+                    latOrY: 10 * node.index()
                 };
             }
 
@@ -101,14 +101,14 @@
         function rand() {
             return {
                 x: rs.randDim(dim[0]),
-                y: rs.randDim(dim[1]),
+                y: rs.randDim(dim[1])
             };
         }
 
         function near(node) {
             return {
                 x: node.x + nearDist + rs.spread(nearDist),
-                y: node.y + nearDist + rs.spread(nearDist),
+                y: node.y + nearDist + rs.spread(nearDist)
             };
         }
 
@@ -176,8 +176,8 @@
 
                 return {
                     positionNode: positionNode,
-                    setLongLat: setLongLat,
+                    setLongLat: setLongLat
                 };
-            },
+            }
         ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js b/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js
index d16417e..de85acf 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js
@@ -22,11 +22,12 @@
     var t2os = 'Topo2OverlayService: ';
 
     // injected refs
-    var $log, fs, t2kcs, t2rs, t2lc, LinkLabel;
+    var $log, $timeout, fs, gs, wss, t2kcs, t2rs, t2lc, api, LinkLabel;
 
     // internal state
     var overlays = {},
-        current = null;
+        current = null,
+        reset = true;
 
     function error(fn, msg) {
         $log.error(t2os + fn + '(): ' + msg);
@@ -118,6 +119,10 @@
     // === -----------------------------------------------------
     //  Event Handlers (events from server)
 
+    function setApi(_api_) {
+        api = _api_;
+    }
+
     function setOverlay(ovid) {
         var ov = overlays[ovid];
         if (!ov) {
@@ -138,7 +143,7 @@
                 nodeLink = t2rs.getLink(id);
                 if (nodeLink) {
                     t2lc.addLabel(LinkLabel, link, linkLabelsDOM, {
-                        link: nodeLink,
+                        link: nodeLink
                     });
                 }
         });
@@ -148,13 +153,17 @@
 
     angular.module('ovTopo2')
     .factory('Topo2OverlayService', [
-        '$log', 'FnService', 'Topo2KeyCommandService',
-        'Topo2RegionService', 'Topo2LabelCollection', 'Topo2LinkLabel',
+        '$log', '$timeout', 'FnService', 'GlyphService', 'WebSocketService',
+        'Topo2KeyCommandService', 'Topo2RegionService', 'Topo2LabelCollection',
+        'Topo2LinkLabel',
 
-        function (_$log_, _fs_, _t2kcs_, _t2rs_,
+        function (_$log_, _$timeout_, _fs_, _gs_, _wss_, _t2kcs_, _t2rs_,
             _t2lc_, _t2ll_) {
             $log = _$log_;
+            $timeout = _$timeout_;
             fs = _fs_;
+            gs = _gs_;
+            wss = _wss_;
             t2kcs = _t2kcs_;
             t2rs = _t2rs_;
             t2lc = _t2lc_;
@@ -162,6 +171,7 @@
 
             return {
                 register: register,
+                setApi: setApi,
                 setOverlay: setOverlay,
 
                 hooks: {
@@ -170,10 +180,11 @@
                     singleSelect: singleSelectHook,
                     multiSelect: multiSelectHook,
                     mouseOver: mouseOverHook,
-                    mouseOut: mouseOutHook,
+                    mouseOut: mouseOutHook
                 },
-                showHighlights: showHighlights,
-            };
-        },
+                showHighlights: showHighlights
+            }
+        }
     ]);
-}());
+
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Panel.js b/web/gui/src/main/webapp/app/view/topo2/topo2Panel.js
index dd7722b..88ba678 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Panel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Panel.js
@@ -51,16 +51,16 @@
             return this.footer.append(x);
         },
         emptyRegions: function () {
-            this.header.selectAll('*').remove();
-            this.body.selectAll('*').remove();
-            this.footer.selectAll('*').remove();
+            this.header.selectAll("*").remove();
+            this.body.selectAll("*").remove();
+            this.footer.selectAll("*").remove();
         },
         destroy: function () {
             ps.destroyPanel(this.id);
         },
         isVisible: function () {
             return this.el.isVisible();
-        },
+        }
     };
 
     angular.module('ovTopo2')
@@ -71,7 +71,7 @@
             ps = _ps_;
 
             return View.extend(panel);
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2PeerRegion.js b/web/gui/src/main/webapp/app/view/topo2/topo2PeerRegion.js
index 738ce08..9e8ad31 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2PeerRegion.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2PeerRegion.js
@@ -25,14 +25,14 @@
     var Collection, Model;
 
     var remappedDeviceTypes = {
-        virtual: 'cord',
+        virtual: 'cord'
     };
 
     function createCollection(data, region) {
 
         var PeerRegionCollection = Collection.extend({
             model: Model,
-            region: region,
+            region: region
         });
 
         return new PeerRegionCollection(data);
@@ -52,7 +52,7 @@
                     nodeType: 'peer-region',
                     events: {
                         'dblclick': 'navigateToRegion',
-                        'click': 'onClick',
+                        'click': 'onClick'
                     },
 
                     initialize: function () {
@@ -76,13 +76,13 @@
                         if (d3.event.defaultPrevented) return;
                         t2rns.navigateToRegion(this.get('id'));
                         t2srp.hide();
-                    },
+                    }
                 });
 
                 return {
-                    createCollection: createCollection,
+                    createCollection: createCollection
                 };
-            },
+            }
         ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js b/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js
index 2f69f7b..9d822c8 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js
@@ -30,8 +30,8 @@
         porthl: 1,
         bg: 0,
         spr: 0,
-        ovid: 'traffic', // default to traffic overlay
-        toolbar: 0,
+        ovid: 'traffic',   // default to traffic overlay
+        toolbar: 0
     };
 
     function topo2Prefs() {
@@ -59,8 +59,8 @@
 
             return {
                 get: get,
-                set: set,
+                set: set
             };
-        },
+        }
     ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
index bba3f39..cd4a75b 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
@@ -53,7 +53,7 @@
 
                     var RegionModel = Model.extend({
                         findNodeById: this.findNodeById,
-                        nodes: this.regionNodes.bind(this),
+                        nodes: this.regionNodes.bind(this)
                     });
 
                     this.model = new RegionModel();
@@ -67,7 +67,7 @@
                     this.model.set({ peerRegions: t2pr.createCollection([], this) });
                     this.model.set({ links: t2ls.createLinkCollection([], this) });
                 },
-                isLoadComplete: function () {
+                isLoadComplete: function() {
                     return this.bgRendered && this.regionData && this.peers;
                 },
                 loaded: function (key, value) {
@@ -80,7 +80,7 @@
 
                     this.model.set({
                         id: this.regionData.id,
-                        layerOrder: this.regionData.layerOrder,
+                        layerOrder: this.regionData.layerOrder
                     });
 
                     this.sortMultiLinks();
@@ -117,7 +117,7 @@
                             if (peer.id === id) {
                                 peer.location = location;
                             }
-                        });
+                        })
                     });
                 },
                 sortMultiLinks: function () {
@@ -147,11 +147,12 @@
                             _.each(collection, function (link, index) {
                                 link.multiline = {
                                     deviceLinks: collection.length,
-                                    index: index,
-                                };
+                                    index: index
+                                }
                             });
                         }
-                    });
+                    })
+
                 },
                 isRootRegion: function () {
                     return this.model.get('id') === ROOT;
@@ -247,17 +248,17 @@
                 },
                 update: function (event) {
 
-                    if (!this.isLoadComplete()) {
+                    if (!this.isLoadComplete()){
                         this.layout.createForceLayout();
                     }
 
                     if (this[event.type]) {
                         this[event.type](event);
                     } else {
-                        $log.error('Unhanded topology update', event);
+                        $log.error("Unhanded topology update", event);
                     }
 
-                    this.layout.update();
+                    this.layout.update()
                     this.displayNoDevs();
                 },
                 displayNoDevs: function () {
@@ -271,10 +272,11 @@
                 // Topology update event handlers
                 LINK_ADDED_OR_UPDATED: function (event) {
 
-                    var regionLinks = this.model.get('links');
+                    var regionLinks = this.model.get('links'),
+                        device;
 
                     if (!regionLinks) {
-                        this.model.set({ links: t2ls.createLinkCollection([], this) });
+                        this.model.set({ links: t2ls.createLinkCollection([], this) })
                     }
 
                     if (event.memo === 'added') {
@@ -294,7 +296,7 @@
                         device;
 
                     if (!regionDevices) {
-                        this.model.set({ devices: t2ds.createDeviceCollection([], this) });
+                        this.model.set({ devices: t2ds.createDeviceCollection([], this) })
                     }
 
                     if (event.memo === 'added') {
@@ -313,7 +315,7 @@
                         host;
 
                     if (!regionHosts) {
-                        this.model.set({ hosts: t2hs.createHostCollection([], this) });
+                        this.model.set({ hosts: t2hs.createHostCollection([], this) })
                     }
 
                     if (event.memo === 'added') {
@@ -326,14 +328,14 @@
                         region;
 
                     if (!regionSubRegions) {
-                        this.model.set({ subregions: t2sr.createSubRegionCollection([], this) });
+                        this.model.set({ subregions: t2sr.createSubRegionCollection([], this) })
                     }
 
                     if (event.memo === 'added') {
                         region = this.model.get('subregions').add(event.data);
                         $log.debug('Added region', region);
                     }
-                },
+                }
             });
 
             function getInstance() {
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2RegionNavigation.js b/web/gui/src/main/webapp/app/view/topo2/topo2RegionNavigation.js
index 9cf78e3..092ec2c 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2RegionNavigation.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2RegionNavigation.js
@@ -50,7 +50,7 @@
         navigateToRegion: function (id) {
             $loc.search('regionId', id);
             wss.sendEvent('topo2navRegion', {
-                rid: id,
+                rid: id
             });
             this.notifyListeners('region:navigation-start', id);
         },
@@ -60,7 +60,7 @@
 
         destory: function () {
             this.listeners = {};
-        },
+        }
     };
 
     angular.module('ovTopo2')
@@ -72,6 +72,6 @@
                 wss = _wss_;
 
                 return instance || new RegionNavigationService();
-            },
+            }
         ]);
-})();
+})();
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Select.js b/web/gui/src/main/webapp/app/view/topo2/topo2Select.js
index d7fe6a5..49fbfe7 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Select.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Select.js
@@ -27,7 +27,7 @@
     var instance,
         consumeClick,
         zoomer,
-        previousNearestLink; // previous link to mouse position
+        previousNearestLink;    // previous link to mouse position
 
     function mouseClickHandler() {
         if (d3.event.defaultPrevented) return;
@@ -162,11 +162,11 @@
         },
         updateDetails: function () {
 
-            var nodeCount = this.selectedNodes.length;
+            var nodeCount =  this.selectedNodes.length;
 
             if (nodeCount === 1) {
                 this.selectedNodes[0].showDetails();
-            } else if (nodeCount > 1) {
+            } else if (nodeCount > 1)  {
                 t2ddp.showMulti(this.selectedNodes);
             } else {
                 t2ddp.hide();
@@ -211,7 +211,7 @@
             var cc = consumeClick;
             consumeClick = Boolean(x);
             return cc;
-        },
+        }
     };
 
     angular.module('ovTopo2')
@@ -221,7 +221,7 @@
             t2zs = _t2zs_;
             t2ddp = _t2ddp_;
             return instance || new SelectionService();
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js b/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
index 6d1b8c6..f53ccc6 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
@@ -19,10 +19,11 @@
  Defines behavior for loading sprites into the sprite layer.
  */
 
- (function () {
+ (function() {
     'use strict';
 
-    var instance;
+    var instance,
+        renderer;
 
     function vbox(w, h) {
       return '0 0 ' + w + ' ' + h;
@@ -40,14 +41,14 @@
                     id: 'topo2-sprites',
                     displayName: 'Sprite Layer',
 
-                    init: function () {
+                    init: function() {
                         this.svg = d3.select('#topo2');
                         this.createSpriteDefs();
                         this.container = this.appendElement('#topo2-background', 'g');
                     },
                     loadLayout: function (id) {
                         var _this = this;
-                        this.container.selectAll('*').remove();
+                        this.container.selectAll("*").remove();
                         this.layout = ss.layout(id);
 
                         if (this.layout) {
@@ -64,7 +65,7 @@
                         }
 
                         // Returns a promise for consistency with Topo2MapService
-                        return new Promise(function (resolve) {
+                        return new Promise(function(resolve) {
                             resolve(_this);
                         });
                     },
@@ -131,7 +132,7 @@
 
                             layout
                                 .append('g')
-                                .append('use')
+                                .append("use")
                                 .attr('xlink:href', '#rack')
                                 .attr('width', 20)
                                 .attr('height', 25)
@@ -163,7 +164,7 @@
                                 .attr('y', i * gridSpacing)
                                 .attr('x', 0);
                         }
-                    },
+                    }
                 });
 
                 function getInstance() {
@@ -171,6 +172,6 @@
                 }
 
                 return getInstance();
-            },
-        ]);
- })();
+            }
+        ])
+ })();
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
index a34e075..c426d64 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
@@ -25,14 +25,14 @@
     var Collection, Model;
 
     var remappedDeviceTypes = {
-        virtual: 'cord',
+        virtual: 'cord'
     };
 
     function createSubRegionCollection(data, region) {
 
         var SubRegionCollection = Collection.extend({
             model: Model,
-            region: region,
+            region: region
         });
 
         return new SubRegionCollection(data);
@@ -52,7 +52,7 @@
                 nodeType: 'sub-region',
                 events: {
                     'dblclick': 'navigateToRegion',
-                    'click': 'onClick',
+                    'click': 'onClick'
                 },
 
                 initialize: function () {
@@ -76,13 +76,13 @@
                     if (d3.event.defaultPrevented) return;
                     t2rns.navigateToRegion(this.get('id'));
                     t2srp.hide();
-                },
+                }
             });
 
             return {
-                createSubRegionCollection: createSubRegionCollection,
+                createSubRegionCollection: createSubRegionCollection
             };
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegionPanel.js b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegionPanel.js
index 68e091a..e084980 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegionPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegionPanel.js
@@ -41,8 +41,8 @@
                 'Id': data.get('id'),
                 'Type': data.get('nodeType'),
                 'Number of Devices': data.get('nDevs'),
-                'Number of Hosts': data.get('nHosts'),
-            },
+                'Number of Hosts': data.get('nHosts')
+            }
         };
     }
 
@@ -103,9 +103,9 @@
                 hide: hide,
                 toggle: toggle,
                 destroy: destroy,
-                isVisible: function () { return subRegionPanel.isVisible(); },
+                isVisible: function () { return subRegionPanel.isVisible(); }
             };
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SummaryPanel.js b/web/gui/src/main/webapp/app/view/topo2/topo2SummaryPanel.js
index 6b651f7..982cd5d4 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SummaryPanel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SummaryPanel.js
@@ -33,10 +33,10 @@
         className = 'topo2-p',
         panelOpts = {
             show: true,
-            width: 260, // summary and detail panel width
+            width: 260 // summary and detail panel width
         },
         handlerMap = {
-            showSummary: handleSummaryData,
+            showSummary: handleSummaryData
         };
 
     function init(_detailsPanel_) {
@@ -47,7 +47,7 @@
         wss.sendEvent('requestSummary');
 
         var options = angular.extend({}, panelOpts, {
-            class: className,
+            class: className
         });
 
         summaryPanel = new Panel(id, options);
@@ -128,9 +128,9 @@
                 toggle: toggle,
                 destroy: destroy,
                 isVisible: function () { return summaryPanel.isVisible(); },
-                getInstance: function () { return summaryPanel; },
+                getInstance: function () { return summaryPanel; }
             };
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Toolbar.js b/web/gui/src/main/webapp/app/view/topo2/topo2Toolbar.js
index ec45bd8..1edcdff 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Toolbar.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Toolbar.js
@@ -24,7 +24,7 @@
 
     // key to button mapping data
     var k2b = {
-        O: { id: 'topo2-summary-tog', gid: 'm_summary', isel: true },
+        O: { id: 'topo2-summary-tog', gid: 'm_summary', isel: true},
         I: { id: 'topo2-instance-tog', gid: 'm_uiAttached', isel: true },
         // D: { id: 'details-tog', gid: 'm_details', isel: true },
         // H: { id: 'hosts-tog', gid: 'm_endstation', isel: false },
@@ -37,7 +37,7 @@
         L: { id: 'topo2-cycleLabels-btn', gid: 'm_cycleLabels' },
         R: { id: 'topo2-resetZoom-btn', gid: 'm_resetZoom' },
 
-        E: { id: 'topo2-eqMaster-btn', gid: 'm_eqMaster' },
+        E: { id: 'topo2-eqMaster-btn', gid: 'm_eqMaster' }
     };
 
     angular.module('ovTopo2')
@@ -63,13 +63,11 @@
                         this.el.hide();
                     },
                     initKeyData: function () {
-                        _.each(k2b, function (value, key) {
+                        _.each(k2b, function(value, key) {
                             var data = t2kcs.getActionEntry(key);
                             if (data) {
-                                // on-click callback
-                                value.cb = data[0];
-                                // tooltip
-                                value.tt = data[1] + ' (' + key + ')';
+                                value.cb = data[0];                     // on-click callback
+                                value.tt = data[1] + ' (' + key + ')';  // tooltip
                             }
                         });
                     },
@@ -84,11 +82,11 @@
                         }
                     },
                     addButton: function (key) {
-                        var v = this.getKey(key);
+                        var v =  this.getKey(key);
                         v.btn = this.el.addButton(v.id, v.gid, v.cb, v.tt);
                     },
                     addToggle: function (key, suppressIfMobile) {
-                        var v = this.getKey(key);
+                        var v =  this.getKey(key);
                         if (suppressIfMobile && fs.isMobile()) { return; }
                         v.tog = this.el.addToggle(v.id, v.gid, v.isel, v.cb, v.tt);
                     },
@@ -109,7 +107,7 @@
                         this.addToggle('B');
                     },
                     addSecondRow: function () {
-                        // addToggle('X');
+                        //addToggle('X');
                         // this.addToggle('Z');
                         // this.addButton('N');
                         this.addButton('L');
@@ -122,10 +120,10 @@
                         // TODO: Should the tbs remove button id's in the destroyToolbar method?
                         // If you go topo2 -> topo -> topo2 there's a button id conflict
                         tbs.destroyToolbar(this.className);
-                    },
+                    }
                 };
 
                 return instance || new Toolbar();
-            },
+            }
         ]);
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Traffic.js b/web/gui/src/main/webapp/app/view/topo2/topo2Traffic.js
index 994e32c..1cb703f 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Traffic.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Traffic.js
@@ -19,18 +19,18 @@
     'use strict';
 
     // injected refs
-    var $log, flash, wss;
+    var $log, fs, flash, wss, api;
 
     // configuration
     var allTrafficTypes = [
             'flowStatsBytes',
             'portStatsBitSec',
-            'portStatsPktSec',
+            'portStatsPktSec'
         ],
         allTrafficMsgs = [
             'Flow Stats (bytes)',
             'Port Stats (bits / second)',
-            'Port Stats (packets / second)',
+            'Port Stats (packets / second)'
         ];
 
     // internal state
@@ -57,7 +57,7 @@
 
         mode = 'allFlowPort';
         wss.sendEvent('topo2RequestAllTraffic', {
-            trafficType: allTrafficTypes[allIndex],
+            trafficType: allTrafficTypes[allIndex]
         });
         flash.flash(allTrafficMsgs[allIndex]);
         currentIndex = allIndex;
@@ -72,23 +72,23 @@
 
     angular.module('ovTopo2')
         .factory('Topo2TrafficService', [
-            '$log', 'FlashService', 'WebSocketService',
+            '$log', 'FnService', 'FlashService', 'WebSocketService',
 
-            function (_$log_, _flash_, _wss_) {
+            function (_$log_, _fs_, _flash_, _wss_) {
                 $log = _$log_;
+                fs = _fs_;
                 flash = _flash_;
                 wss = _wss_;
 
                 return {
-                    // TODO: Remove References
-                    initTraffic: function (_api_) {},
+                    initTraffic: function (_api_) { api = _api_; },
                     destroyTraffic: function () {},
 
                     // invoked from toolbar overlay buttons or keystrokes
                     cancelTraffic: cancelTraffic,
                     showAllTraffic: showAllTraffic,
-                    selectedTrafficOverlay: selectedTrafficOverlay,
-                };
-            },
+                    selectedTrafficOverlay: selectedTrafficOverlay
+                }
+            }
         ]);
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2TrafficOverlay.js b/web/gui/src/main/webapp/app/view/topo2/topo2TrafficOverlay.js
index a606078..19d0844 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2TrafficOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2TrafficOverlay.js
@@ -30,12 +30,12 @@
         tooltip: 'Traffic Overlay',
 
         activate: function () {
-            $log.debug('Traffic-2 overlay ACTIVATED');
+            $log.debug("Traffic-2 overlay ACTIVATED");
         },
 
         deactivate: function () {
             t2ts.cancelTraffic(true);
-            $log.debug('Traffic-2 overlay DEACTIVATED');
+            $log.debug("Traffic-2 overlay DEACTIVATED");
         },
 
         // key bindings for toolbar buttons
@@ -44,18 +44,18 @@
             0: {
                 cb: function () { t2ts.cancelTraffic(true); },
                 tt: 'Cancel traffic monitoring',
-                gid: 'm_xMark',
+                gid: 'm_xMark'
             },
 
             A: {
                 cb: function () { t2ts.showAllTraffic(); },
                 tt: 'Monitor all traffic',
-                gid: 'm_allTraffic',
+                gid: 'm_allTraffic'
             },
 
             _keyOrder: [
-                '0', 'A',
-            ],
+                '0', 'A'
+            ]
         },
 
         hooks: {
@@ -63,10 +63,10 @@
             escape: function () {
                 // Must return true to consume ESC, false otherwise.
                 return t2ts.cancelTraffic(true);
-            },
+            }
             // TODO : add node selection events etc.
             // NOTE : see topoTrafficNew.js
-        },
+        }
     };
 
     // invoke code to register with the overlay service
@@ -80,4 +80,4 @@
             t2ov.register(overlay);
         }]);
 
-}());
+}());
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2View.js b/web/gui/src/main/webapp/app/view/topo2/topo2View.js
index 9e6d6b1..ae29894 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2View.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2View.js
@@ -28,7 +28,7 @@
     // Internal State
     var dimensions,
         viewOptions = {
-            linkPortHighlighting: true,
+            linkPortHighlighting: true
         };
 
     function newDim(_dimensions) {
@@ -65,9 +65,9 @@
                     getDimensions: getDimensions,
 
                     togglePortHighlights: togglePortHighlights,
-                    getPortHighlighting: getPortHighlighting,
+                    getPortHighlighting: getPortHighlighting
                 };
-            },
+            }
         ]
     );
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js b/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js
index 7387c94..190f751 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js
@@ -34,10 +34,10 @@
         displayName: 'View',
 
         initialize: function () {
-            this.name = this.displayName.toLowerCase().replace(/ /g, '_');
+            this.name = this.displayName.toLowerCase().replace(/ /g,"_");
             this.prefs = {
-                visible: this.name + '_visible',
-            };
+                visible: this.name + '_visible'
+            }
         },
         appendElement: function (parent, node) {
             var el = d3.select('#' + this.id);
@@ -46,7 +46,7 @@
             }
             return el;
         },
-        node: function () {
+        node: function() {
             return d3.select('#' + this.id);
         },
         enabled: function () {
@@ -64,7 +64,7 @@
                     .duration(400)
                     .style('opacity', 0)
                     .each('end', function () {
-                        node.style('visibility', 'hidden');
+                        node.style('visibility', 'hidden')
                     });
             }
         },
@@ -76,7 +76,7 @@
                     .style('visibility', 'visible')
                     .transition()
                     .duration(400)
-                    .style('opacity', 1);
+                    .style('opacity', 1)
             }
         },
         toggle: function () {
@@ -95,7 +95,7 @@
             var state = ps.getPrefs('topo2_prefs');
             state[key] = value ? 1 : 0;
             ps.setPrefs('topo2_prefs', state);
-        },
+        }
     };
 
     angular.module('ovTopo2')
@@ -108,6 +108,6 @@
 
                 ViewController.extend = fn.extend;
                 return ViewController;
-            },
+            }
         ]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Zoom.js b/web/gui/src/main/webapp/app/view/topo2/topo2Zoom.js
index f70496b..3e6f12a 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Zoom.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Zoom.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected references
-    var fs, zs;
+    var fs, zs, ps;
 
     // internal state
     var zoomer,
@@ -91,11 +91,12 @@
 
     angular.module('ovTopo2')
     .factory('Topo2ZoomService', [
-        'FnService', 'ZoomService',
-        function (_fs_, _zs_) {
+        'FnService', 'ZoomService', 'PrefsService',
+        function (_fs_, _zs_, _ps_) {
 
             fs = _fs_;
             zs = _zs_;
+            ps = _ps_;
 
             return {
                 getZoomer: getZoomer,
@@ -105,7 +106,7 @@
 
                 scale: scale,
                 adjustmentScale: adjustmentScale,
-                panAndZoom: panAndZoom,
+                panAndZoom: panAndZoom
             };
         }]);
 })();
diff --git a/web/gui/src/main/webapp/app/view/topo2/uiView.js b/web/gui/src/main/webapp/app/view/topo2/uiView.js
index ba1219e..77419a5 100644
--- a/web/gui/src/main/webapp/app/view/topo2/uiView.js
+++ b/web/gui/src/main/webapp/app/view/topo2/uiView.js
@@ -47,12 +47,12 @@
                     // TODO: Unbind Events
                     this.empty();
                     return this;
-                },
+                }
             });
 
             View.extend = fn.extend;
             return View;
-        },
+        }
     ]);
 
 })();
diff --git a/web/gui/src/main/webapp/app/view/tunnel/tunnel.js b/web/gui/src/main/webapp/app/view/tunnel/tunnel.js
index 810774c..88325e2 100644
--- a/web/gui/src/main/webapp/app/view/tunnel/tunnel.js
+++ b/web/gui/src/main/webapp/app/view/tunnel/tunnel.js
@@ -28,13 +28,13 @@
         function ($log, $scope, $sce, fs, tbs) {
             tbs.buildTable({
                 scope: $scope,
-                tag: 'tunnel',
+                tag: 'tunnel'
             });
 
             $scope.$watch('tableData', function () {
                 if (!fs.isEmptyObject($scope.tableData)) {
                     $scope.tableData.forEach(function (tunnel) {
-                        // tunnel.direction = $sce.trustAsHtml(tunnel.direction);
+                        //tunnel.direction = $sce.trustAsHtml(tunnel.direction);
                     });
                 }
             });