GUI -- Tabular views have divs that encapsulate the header to make math easier for calculating table height. - fixed bug in Device Details Panel where Ports table wouldn't scroll. - Minor refactoring

Change-Id: I2d8133fb4a92f82087566084143c32deb7393fb3
diff --git a/web/gui/src/main/webapp/app/common.css b/web/gui/src/main/webapp/app/common.css
index b188930..d0d878e 100644
--- a/web/gui/src/main/webapp/app/common.css
+++ b/web/gui/src/main/webapp/app/common.css
@@ -18,3 +18,9 @@
  ONOS GUI -- common -- CSS file
  */
 
+#view h2 {
+    margin: 0;
+    /* separated out so that other padding doesn't get clobbered */
+    padding-top: 20px;
+    padding-bottom: 20px;
+}
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 2a358c7..6b94dd2 100644
--- a/web/gui/src/main/webapp/app/fw/widget/table.js
+++ b/web/gui/src/main/webapp/app/fw/widget/table.js
@@ -25,10 +25,7 @@
 
     // constants
     var tableIconTdSize = 33,
-        mastPdg = 8,
-        h2Pdg = 40,
-        thPdg = 12,
-        tbodyPdg = 5,
+        pdg = 12,
         colWidth = 'col-width',
         tableIcon = 'table-icon';
 
@@ -100,15 +97,15 @@
     // get the size of the window and then subtract the extra space at the top
     // to get the height of the table
     function setTableHeight(thead, tbody) {
-        var titleHeight = h2Pdg + fs.noPxStyle(d3.select('h2'), 'height'),
-            thHeight = thPdg + fs.noPxStyle(thead, 'height'),
-            totalHeight = titleHeight + thHeight + mastPdg - tbodyPdg,
-            tableHeight = fs.windowSize(mast.mastHeight() + totalHeight).height;
+        var ttlHgt = fs.noPxStyle(d3.select('.tabular-header'), 'height'),
+            thHgt = fs.noPxStyle(thead, 'height'),
+            totalHgt = ttlHgt + thHgt + pdg,
+            tbleHgt = fs.windowSize(mast.mastHeight() + totalHgt).height;
 
         thead.style('display', 'block');
         tbody.style({
             display: 'block',
-            height: tableHeight + 'px',
+            height: tbleHgt + 'px',
             overflow: 'auto'
         });
     }
diff --git a/web/gui/src/main/webapp/app/view/app/app.html b/web/gui/src/main/webapp/app/view/app/app.html
index 45f9cbc..ced8ec2 100644
--- a/web/gui/src/main/webapp/app/view/app/app.html
+++ b/web/gui/src/main/webapp/app/view/app/app.html
@@ -1,6 +1,6 @@
 <!-- app partial HTML -->
 <div id="ov-app">
-    <div>
+    <div class="tabular-header">
         <h2>Applications ({{ctrl.tableData.length}} total)</h2>
         <div class="ctrl-btns">
             <div icon icon-size="36" icon-id="plus"></div>
@@ -9,6 +9,7 @@
             <div icon icon-size="36" icon-id="stop" class="disabled"></div>
         </div>
     </div>
+
     <table class="summary-list"
            onos-fixed-header
            onos-sortable-header
@@ -44,5 +45,4 @@
             </tr>
         </tbody>
     </table>
-
 </div>
diff --git a/web/gui/src/main/webapp/app/view/cluster/cluster.html b/web/gui/src/main/webapp/app/view/cluster/cluster.html
index c758ed7..b08f4ac 100644
--- a/web/gui/src/main/webapp/app/view/cluster/cluster.html
+++ b/web/gui/src/main/webapp/app/view/cluster/cluster.html
@@ -16,7 +16,10 @@
 
 <!-- Cluster partial HTML -->
 <div id="ov-cluster">
-    <h2>Cluster Nodes ({{ctrl.tableData.length}} total)</h2>
+    <div class="tabular-header">
+        <h2>Cluster Nodes ({{ctrl.tableData.length}} total)</h2>
+    </div>
+
     <table class="summary-list"
            onos-fixed-header
            onos-sortable-header
@@ -50,5 +53,4 @@
         </tr>
         </tbody>
     </table>
-
 </div>
diff --git a/web/gui/src/main/webapp/app/view/device/device.html b/web/gui/src/main/webapp/app/view/device/device.html
index 849e666..d68dbed 100644
--- a/web/gui/src/main/webapp/app/view/device/device.html
+++ b/web/gui/src/main/webapp/app/view/device/device.html
@@ -1,6 +1,9 @@
 <!-- Device partial HTML -->
 <div id="ov-device">
-    <h2>Devices ({{ctrl.tableData.length}} total)</h2>
+    <div class="tabular-header">
+        <h2>Devices ({{ctrl.tableData.length}} total)</h2>
+    </div>
+
     <table class="summary-list"
            onos-fixed-header
            onos-sortable-header
@@ -46,5 +49,4 @@
             </tr>
         </tbody>
     </table>
-
 </div>
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 c5b9828..0f02124 100644
--- a/web/gui/src/main/webapp/app/view/device/device.js
+++ b/web/gui/src/main/webapp/app/view/device/device.js
@@ -27,19 +27,20 @@
     // internal state
     var self,
         detailsPanel,
-        container, top, bottom, iconDiv,
-        selRow;
+        pStartY, pHeight,
+        top, bottom, iconDiv,
+        wSize, selRow;
 
     // constants
-    // TODO: consider having a set y height that all tables start at
-    // to make calculations easier
-    var h2Pdg = 40,
-        mastPdg = 8,
-        tbodyPdg = 5,
-        cntrPdg = 24,
+    var topPdg = 13,
+        ctnrPdg = 24,
+        scrollSize = 10,
+        portsTblPdg = 50,
+
         pName = 'device-details-panel',
         detailsReq = 'deviceDetailsRequest',
         detailsResp = 'deviceDetailsResponse',
+
         propOrder = [
             'type', 'masterid', 'chassisid',
             'mfr', 'hw', 'sw', 'protocol', 'serial'
@@ -66,7 +67,7 @@
     }
 
     function setUpPanel() {
-        var closeBtn;
+        var container, closeBtn;
         detailsPanel.empty();
 
         container = detailsPanel.append('div').classed('container', true);
@@ -77,35 +78,13 @@
         iconDiv = top.append('div').classed('dev-icon', true);
         top.append('h2');
         top.append('table');
-
-        container.append('hr');
+        top.append('hr');
 
         bottom = container.append('div').classed('bottom', true);
-        bottom.append('h2').text('Ports');
+        bottom.append('h2').classed('ports-title', true).html('Ports');
         bottom.append('table');
     }
 
-    function createDetailsPane() {
-        var headerHeight = h2Pdg + fs.noPxStyle(d3.select('h2'), 'height'),
-            panelTop = headerHeight + tbodyPdg + mast.mastHeight() + mastPdg,
-            wSize = fs.windowSize(panelTop);
-
-        detailsPanel = ps.createPanel(pName, {
-            height: wSize.height,
-            margin: 0,
-            hideMargin: 0
-        });
-
-        detailsPanel.el().style({
-            position: 'absolute',
-            top: panelTop + 'px'
-        });
-
-        setUpPanel();
-
-        detailsPanel.hide();
-    }
-
     function addProp(tbody, index, value) {
         var tr = tbody.append('tr');
 
@@ -118,7 +97,7 @@
 
     function populateTop(tbody, details) {
         is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
-        top.select('h2').text(details.id);
+        top.select('h2').html(details.id);
 
         propOrder.forEach(function (prop, i) {
             addProp(tbody, i, details[prop]);
@@ -139,9 +118,7 @@
     function populateBottom(table, ports) {
         var theader = table.append('thead').append('tr'),
             tbody = table.append('tbody'),
-            tbWidth, tbHeight,
-            scrollSize = 20,
-            padding = 55;
+            tbWidth, tbHeight;
 
         friendlyPortCols.forEach(function (col) {
             theader.append('th').html(col);
@@ -151,11 +128,12 @@
         });
 
         tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
-        tbHeight = detailsPanel.height()
-                    - (fs.noPxStyle(detailsPanel.el().select('.top'), 'height')
-                    + fs.noPxStyle(detailsPanel.el().select('hr'), 'height')
-                    + fs.noPxStyle(detailsPanel.el().select('h2'), 'height')
-                    + padding);
+        tbHeight = pHeight
+                    - (fs.noPxStyle(detailsPanel.el()
+                                        .select('.top'), 'height')
+                    + fs.noPxStyle(detailsPanel.el()
+                                        .select('.ports-title'), 'height')
+                    + portsTblPdg);
 
         table.style({
             height: tbHeight + 'px',
@@ -164,18 +142,21 @@
             display: 'block'
         });
 
-        detailsPanel.width(tbWidth + cntrPdg);
+        detailsPanel.width(tbWidth + ctnrPdg);
     }
 
     function populateDetails(details) {
+        var topTb, btmTbl, ports;
         setUpPanel();
 
-        var topTb = top.select('table').append('tbody'),
-            btmTbl = bottom.select('table'),
-            ports = details.ports;
+        topTb = top.select('table').append('tbody');
+        btmTbl = bottom.select('table');
+        ports = details.ports;
 
         populateTop(topTb, details);
         populateBottom(btmTbl, ports);
+
+        detailsPanel.height(pHeight);
     }
 
     function respDetailsCb(data) {
@@ -184,6 +165,19 @@
         detailsPanel.show();
     }
 
+    function createDetailsPane() {
+        detailsPanel = ps.createPanel(pName, {
+            width: wSize.width,
+            margin: 0,
+            hideMargin: 0
+        });
+        detailsPanel.el().style({
+            position: 'absolute',
+            top: pStartY + 'px'
+        });
+        detailsPanel.hide();
+    }
+
     angular.module('ovDevice', [])
     .controller('OvDeviceCtrl',
         ['$log', '$scope', 'TableBuilderService', 'FnService',
@@ -200,10 +194,13 @@
             self = this;
             var handlers = {};
             self.panelData = [];
+            pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
+                                            + mast.mastHeight() + topPdg;
+            wSize = fs.windowSize(pStartY);
+            pHeight = wSize.height;
 
             function selCb($event, row) {
                 selRow = angular.element($event.currentTarget);
-
                 if ($scope.sel) {
                     wss.sendEvent(detailsReq, { id: row.id });
                 } else {
@@ -218,7 +215,6 @@
                 tag: 'device',
                 selCb: selCb
             });
-
             createDetailsPane();
 
             handlers[detailsResp] = respDetailsCb;
diff --git a/web/gui/src/main/webapp/app/view/host/host.html b/web/gui/src/main/webapp/app/view/host/host.html
index af65694..5ebc9ae 100644
--- a/web/gui/src/main/webapp/app/view/host/host.html
+++ b/web/gui/src/main/webapp/app/view/host/host.html
@@ -1,6 +1,9 @@
 <!-- Host partial HTML -->
 <div id="ov-host">
-    <h2>Hosts ({{ctrl.tableData.length}} total)</h2>
+    <div class="tabular-header">
+        <h2>Hosts ({{ctrl.tableData.length}} total)</h2>
+    </div>
+
     <table class="summary-list"
            onos-fixed-header
            onos-sortable-header
@@ -36,5 +39,4 @@
             </tr>
         </tbody>
     </table>
-
 </div>
diff --git a/web/gui/src/main/webapp/app/view/intent/intent.html b/web/gui/src/main/webapp/app/view/intent/intent.html
index 85ac085..cc48a7c 100644
--- a/web/gui/src/main/webapp/app/view/intent/intent.html
+++ b/web/gui/src/main/webapp/app/view/intent/intent.html
@@ -16,7 +16,9 @@
 
 <!-- Intent partial HTML -->
 <div id="ov-intent">
-    <h2>Intents ({{ctrl.tableData.length}} total)</h2>
+    <div class="tabular-header">
+        <h2>Intents ({{ctrl.tableData.length}} total)</h2>
+    </div>
     <table class="summary-list"
            onos-fixed-header
            onos-sortable-header
@@ -51,5 +53,4 @@
             </tr>
         </tbody>
     </table>
-
 </div>
diff --git a/web/gui/src/main/webapp/app/view/link/link.html b/web/gui/src/main/webapp/app/view/link/link.html
index b82b4fb4..18f3e1f 100644
--- a/web/gui/src/main/webapp/app/view/link/link.html
+++ b/web/gui/src/main/webapp/app/view/link/link.html
@@ -16,7 +16,10 @@
 
 <!-- Link partial HTML -->
 <div id="ov-link">
-    <h2>Links ({{ctrl.tableData.length}} total)</h2>
+    <div class="tabular-header">
+        <h2>Links ({{ctrl.tableData.length}} total)</h2>
+    </div>
+
     <table class="summary-list"
            onos-fixed-header
            onos-sortable-header
@@ -52,5 +55,4 @@
             </tr>
         </tbody>
     </table>
-
 </div>