ONOS-1865 - GUI -- Keys from Topo View are deregistered once view is navigated away from. Device and App View 'esc' key registration added.

Change-Id: I88896266936a4f148007170d67058036fb365fe5
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 b2e06ca..2985565 100644
--- a/web/gui/src/main/webapp/app/fw/util/keys.js
+++ b/web/gui/src/main/webapp/app/fw/util/keys.js
@@ -167,6 +167,12 @@
         };
     }
 
+    function unbindKeys() {
+        keyHandler.viewKeys = {};
+        keyHandler.viewFn = null;
+        keyHandler.viewGestures = [];
+    }
+
     angular.module('onosUtil')
     .factory('KeyService',
         ['$log', 'FnService', 'ThemeService', 'NavService',
@@ -192,6 +198,7 @@
                         setKeyBindings(x);
                     }
                 },
+                unbindKeys: unbindKeys,
                 gestureNotes: function (g) {
                     if (g === undefined) {
                         return keyHandler.viewGestures;
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 c5a7961..5bcb428 100644
--- a/web/gui/src/main/webapp/app/view/app/app.js
+++ b/web/gui/src/main/webapp/app/view/app/app.js
@@ -31,8 +31,9 @@
     .controller('OvAppCtrl',
         ['$log', '$scope', '$http',
         'FnService', 'TableBuilderService', 'WebSocketService', 'UrlFnService',
+        'KeyService',
 
-    function ($log, $scope, $http, fs, tbs, wss, ufs) {
+    function ($log, $scope, $http, fs, tbs, wss, ufs, ks) {
         $scope.ctrlBtnState = {};
         $scope.uploadTip = 'Upload an application';
         $scope.activateTip = 'Activate selected application';
@@ -42,8 +43,6 @@
         function selCb($event, row) {
             // selId comes from tableBuilder
             $scope.ctrlBtnState.selection = !!$scope.selId;
-            $log.debug('Got a click on:', row);
-
             refreshCtrls();
         }
 
@@ -68,6 +67,16 @@
             respCb: refreshCtrls
         });
 
+        // TODO: reexamine where keybindings should be - directive or controller?
+        ks.keyBindings({
+            esc: [$scope.selectCallback, 'Deselect app'],
+            _helpFormat: ['esc']
+        });
+        ks.gestureNotes([
+            ['click row', 'Select / deselect app'],
+            ['scroll down', 'See more apps']
+        ]);
+
         $scope.appAction = function (action) {
             if ($scope.ctrlBtnState.selection) {
                 $log.debug('Initiating ' + action + ' of ' + $scope.selId);
@@ -95,6 +104,10 @@
             }
         });
 
+        $scope.$on('$destroy', function () {
+            ks.unbindKeys();
+        });
+
         $log.log('OvAppCtrl has been created');
     }])
 
diff --git a/web/gui/src/main/webapp/app/view/device/device.css b/web/gui/src/main/webapp/app/view/device/device.css
index e4a30b1..fc08f68 100644
--- a/web/gui/src/main/webapp/app/view/device/device.css
+++ b/web/gui/src/main/webapp/app/view/device/device.css
@@ -31,6 +31,7 @@
 #device-details-panel.floatpanel {
     -moz-border-radius: 0;
     border-radius: 0;
+    z-index: 0;
 }
 
 .light #device-details-panel.floatpanel {
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 0e16dec..1f2a8ca 100644
--- a/web/gui/src/main/webapp/app/view/device/device.js
+++ b/web/gui/src/main/webapp/app/view/device/device.js
@@ -55,14 +55,17 @@
             'Enabled', 'ID', 'Speed', 'Type', 'Egress Links', 'Name'
         ];
 
+    function closePanel() {
+        if (detailsPanel.isVisible()) {
+            $scope.selId = null;
+            detailsPanel.hide();
+        }
+    }
+
     function addCloseBtn(div) {
         is.loadEmbeddedIcon(div, 'plus', 30);
         div.select('g').attr('transform', 'translate(25, 0) rotate(45)');
-
-        div.on('click', function () {
-            $scope.selId = null;
-            detailsPanel.hide();
-        });
+        div.on('click', closePanel);
     }
 
     function setUpPanel() {
@@ -247,8 +250,8 @@
             $log.log('OvDeviceCtrl has been created');
         }])
 
-    .directive('deviceDetailsPanel', ['$rootScope', '$window',
-    function ($rootScope, $window) {
+    .directive('deviceDetailsPanel', ['$rootScope', '$window', 'KeyService',
+    function ($rootScope, $window, ks) {
         return function (scope) {
             var unbindWatch;
 
@@ -262,6 +265,16 @@
 
             createDetailsPane();
 
+            // create key bindings to handle panel
+            ks.keyBindings({
+                esc: [closePanel, 'Close the details panel'],
+                _helpFormat: ['esc']
+            });
+            ks.gestureNotes([
+                ['click', 'Select a row to show device details'],
+                ['scroll down', 'See more devices']
+            ]);
+
             scope.$watch('panelData', function () {
                 if (!fs.isEmptyObject(scope.panelData)) {
                     populateDetails(scope.panelData);
@@ -285,6 +298,7 @@
 
             scope.$on('$destroy', function () {
                 unbindWatch();
+                ks.unbindKeys();
                 ps.destroyPanel(pName);
             });
         };
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 1ec18b9..5727a78 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -447,6 +447,7 @@
             $scope.$on('$destroy', function () {
                 $log.log('OvTopoCtrl is saying Buh-Bye!');
                 tes.stop();
+                ks.unbindKeys();
                 tps.destroyPanels();
                 tis.destroyInst();
                 tfs.destroyForce();