From b8f278cabf77318ee7ec6bb0ce930b6e51cb2e58 Mon Sep 17 00:00:00 2001 From: Deep Tailor Date: Fri, 29 Jun 2018 11:38:18 -0700 Subject: [PATCH] [Tables] - Sticky headers (#2071) * first revision * [Frontend] Styling for sticky table headers Fixes #1481 - WIP convert mct-table layout to use flex; - TODO: fix flex layout when a small number of rows; - Rename CSS classes used as selectors by JS; * remove header height from calculations since it is outside in its own table now * [Frontend] Styling for sticky table headers Fixes #1481 - Fixed flex layout when a small number of rows; - Refined input padding and dropshadow for more compactness; * fix tests and verify tables works properly in layout and large view * add mct-scroll to header table to allow scrolling in sync with the rest of mct-table * Various fixes and polishing Fixes #2071 - Fix headers height issue; - Move inline styles to classes; - First round fix for horz overflow due to scrollbar problem; * WIP horz overflow Fixes #2071 - Commented out CSS-based scrollbar with approach in anticipation of better JS solution; * Horz overflow/scrollbar problem fixed Fixes #2071 - Added calcTableWidthPx to allow sizing-table to subtract width of scrollbar; * Remove commented code * add clear icon back into filter text boxes * Polishing on sticky table headers filtering Fixes #1481 Fixes #2071 - Now hides the magnify glass in table header filters when typing; --- .../commonUI/general/res/sass/_constants.scss | 2 +- .../commonUI/general/res/sass/_global.scss | 6 ++ .../commonUI/general/res/sass/_mixins.scss | 2 +- .../general/res/sass/lists/_tabular.scss | 89 +++++++++++-------- platform/features/table/res/sass/table.scss | 69 +++++++------- .../table/res/templates/mct-table.html | 53 ++++++----- .../table/res/templates/telemetry-table.html | 2 +- .../src/controllers/MCTTableController.js | 34 ++++--- .../controllers/MCTTableControllerSpec.js | 2 +- 9 files changed, 146 insertions(+), 113 deletions(-) diff --git a/platform/commonUI/general/res/sass/_constants.scss b/platform/commonUI/general/res/sass/_constants.scss index ec52e2b56f..d79da903ab 100644 --- a/platform/commonUI/general/res/sass/_constants.scss +++ b/platform/commonUI/general/res/sass/_constants.scss @@ -111,7 +111,7 @@ $bubbleMaxW: 300px; $reqSymbolW: 15px; $reqSymbolM: $interiorMargin * 2; $reqSymbolFontSize: 0.75em; -$inputTextPTopBtm: 3px; +$inputTextPTopBtm: 2px; $inputTextPLeftRight: 5px; $inputTextP: $inputTextPTopBtm $inputTextPLeftRight; /*************** Wait Spinner Defaults */ diff --git a/platform/commonUI/general/res/sass/_global.scss b/platform/commonUI/general/res/sass/_global.scss index d2e58072d9..c25558055f 100644 --- a/platform/commonUI/general/res/sass/_global.scss +++ b/platform/commonUI/general/res/sass/_global.scss @@ -199,12 +199,18 @@ a.disabled { } .vscroll { + overflow-x: hidden; overflow-y: auto; &.scroll-pad { padding-right: $interiorMargin; } } +.vscroll--persist { + overflow-x: hidden; + overflow-y: scroll; +} + .slidable { cursor: move; // Fallback cursor: grab; diff --git a/platform/commonUI/general/res/sass/_mixins.scss b/platform/commonUI/general/res/sass/_mixins.scss index c9ac76c1c8..89e7050088 100644 --- a/platform/commonUI/general/res/sass/_mixins.scss +++ b/platform/commonUI/general/res/sass/_mixins.scss @@ -334,7 +334,7 @@ color: $fg; } -@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) { +@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.5) 0 0px 2px) { @include s-input($bg, $fg, $shdw); border: none; outline: none; diff --git a/platform/commonUI/general/res/sass/lists/_tabular.scss b/platform/commonUI/general/res/sass/lists/_tabular.scss index 5ffaa31218..662ca693af 100644 --- a/platform/commonUI/general/res/sass/lists/_tabular.scss +++ b/platform/commonUI/general/res/sass/lists/_tabular.scss @@ -26,6 +26,20 @@ .tabular-holder { @include absPosDefault(); + display: flex; + flex-flow: column nowrap; + justify-content: flex-start; + > * { + position: relative; + flex: 0 0 auto; + } + + &.l-sticky-headers { + .l-tabular-body { + flex: 1 1 99%; + overflow-x: auto; + } + } } .tabular, @@ -41,19 +55,20 @@ table { tbody tr, .tbody .tr { width: 100%; } - thead, .thead { - border-bottom: 1px solid $colorTabHeaderBorder; - } - &:not(.fixed-header) tr th { - background-color: $colorTabHeaderBg; - } + thead tr th { + // Add some bg to the headers. Note that this is overwritten below + // by .mct-table-headers-w when headers are wrapped by that container. + background-color: $colorTabHeaderBg; + } tbody, .tbody { display: table-row-group; + tr, .tr { + border-top: 1px solid $colorTabBorder; + } } tr, .tr { - border-top: 1px solid $colorTabBorder; display: table-row; &:first-child .td { border-top: none; @@ -118,42 +133,40 @@ table { tbody, .tbody { top: $tabularHeaderH * 2; } - input[type="text"], - input[type="search"] { - box-sizing: border-box; - width: 100%; - } + .l-filter { + input[type="text"], + input[type="search"] { + $p: 20px; + transition: padding 200ms ease-in-out; + box-sizing: border-box; + padding-right: $p; // Fend off from icon + padding-left: $p; // Fend off from icon + width: 100%; + } + &.active { + // When user has typed something, hide the icon and collapse left padding + &:before { + opacity: 0; + } + input[type="text"], + input[type="search"] { + padding-left: $interiorMargin; + } + } + } } - &.fixed-header { - height: 100%; - thead, .thead, - tbody tr, .tbody .tr { - display: table; - table-layout: fixed; - } - thead, .thead { - width: calc(100% - 10px); - &:before { - content: ""; - display: block; - z-index: 0; - position: absolute; - width: 100%; - height: $tabularHeaderH; - background-color: $colorTabHeaderBg; - } - } - tbody, .tbody { - @include absPosDefault(0); - top: $tabularHeaderH; - display: block; - overflow-y: scroll; - } - } &.t-event-messages { td, .td { min-width: 150px; } } } + +.mct-table-headers-w { + background: $colorTabHeaderBg; + overflow: hidden; + thead tr th { + background: none; + } +} diff --git a/platform/features/table/res/sass/table.scss b/platform/features/table/res/sass/table.scss index efd5ac627b..e2ad3cff7b 100644 --- a/platform/features/table/res/sass/table.scss +++ b/platform/features/table/res/sass/table.scss @@ -20,43 +20,48 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -.sizing-table { - min-width: 100%; - z-index: -1; - visibility: hidden; - position: absolute; +mct-table { + .mct-sizing-table { + z-index: -1; + visibility: hidden; + position: absolute !important; - //Add some padding to allow for decorations such as limits indicator - td { - padding-right: 15px; - padding-left: 10px; - white-space: nowrap; - } -} -.mct-table { - table-layout: fixed; - thead { - display: block; - tr { - display: block; + //Add some padding to allow for decorations such as limits indicator + td { + padding-right: 15px; + padding-left: 10px; white-space: nowrap; - th { - display: inline-block; + } + } + + .mct-table { + thead { + display: block; + tr { + display: block; + white-space: nowrap; + th { + display: inline-block; + box-sizing: border-box; + } + } + } + tbody { + tr { + position: absolute; + white-space: nowrap; + display: block; + } + td { + white-space: nowrap; + overflow: hidden; box-sizing: border-box; + display: inline-block; } } } - tbody { - tr { - position: absolute; - white-space: nowrap; - display: block; - } - td { - white-space: nowrap; - overflow: hidden; - box-sizing: border-box; - display: inline-block; - } + + .l-control-bar { + margin-bottom: 3px; } } diff --git a/platform/features/table/res/templates/mct-table.html b/platform/features/table/res/templates/mct-table.html index 2fa5b9a57c..63c41d7867 100644 --- a/platform/features/table/res/templates/mct-table.html +++ b/platform/features/table/res/templates/mct-table.html @@ -5,22 +5,11 @@ Export -
- - - - - - - -
{{header}}
- {{sizingRow[header].text}} -
- +
+
+
-
- - +
+ +
+
+ + + + + + + +
{{header}}
+ {{sizingRow[header].text}} +
+
+ + class="tabular-holder l-sticky-headers has-control-bar"> diff --git a/platform/features/table/src/controllers/MCTTableController.js b/platform/features/table/src/controllers/MCTTableController.js index 80fac94e66..e3fb75e221 100644 --- a/platform/features/table/src/controllers/MCTTableController.js +++ b/platform/features/table/src/controllers/MCTTableController.js @@ -23,10 +23,11 @@ define( this.$window = $window; this.maxDisplayRows = 100; - this.scrollable = this.element.find('.l-view-section.scrolling').first(); + this.scrollable = this.element.find('.t-scrolling').first(); this.resultsHeader = this.element.find('.mct-table>thead').first(); - this.sizingTableBody = this.element.find('.sizing-table>tbody').first(); + this.sizingTableBody = this.element.find('.t-sizing-table>tbody').first(); this.$scope.sizingRow = {}; + this.$scope.calcTableWidthPx = '100%'; this.timeApi = openmct.time; this.toiFormatter = undefined; this.formatService = formatService; @@ -286,14 +287,9 @@ define( topScroll = target.scrollTop, firstVisible; - if (topScroll < this.$scope.headerHeight) { - firstVisible = 0; - } else { - firstVisible = Math.floor( - (topScroll - this.$scope.headerHeight) / - this.$scope.rowHeight - ); - } + firstVisible = Math.floor( + (topScroll) / this.$scope.rowHeight + ); return firstVisible; }; @@ -309,7 +305,7 @@ define( lastVisible; lastVisible = Math.ceil( - (bottomScroll - this.$scope.headerHeight) / + (bottomScroll) / this.$scope.rowHeight ); return lastVisible; @@ -360,8 +356,7 @@ define( .map(function (row, i) { return { rowIndex: start + i, - offsetY: ((start + i) * self.$scope.rowHeight) + - self.$scope.headerHeight, + offsetY: ((start + i) * self.$scope.rowHeight), contents: row }; }); @@ -397,15 +392,13 @@ define( * for individual rows. */ MCTTableController.prototype.setElementSizes = function () { - var thead = this.resultsHeader, - tbody = this.sizingTableBody, + var tbody = this.sizingTableBody, firstRow = tbody.find('tr'), column = firstRow.find('td'), - headerHeight = thead.prop('offsetHeight'), rowHeight = firstRow.prop('offsetHeight'), columnWidth, tableWidth = 0, - overallHeight = headerHeight + (rowHeight * + overallHeight = (rowHeight * (this.$scope.displayRows ? this.$scope.displayRows.length - 1 : 0)); this.$scope.columnWidths = []; @@ -416,10 +409,14 @@ define( tableWidth += columnWidth; column = column.next(); } - this.$scope.headerHeight = headerHeight; this.$scope.rowHeight = rowHeight; this.$scope.totalHeight = overallHeight; + var scrollW = this.scrollable[0].offsetWidth - this.scrollable[0].clientWidth; + if (scrollW && scrollW > 0) { + this.$scope.calcTableWidthPx = 'calc(100% - ' + scrollW + 'px)'; + } + if (tableWidth > 0) { this.$scope.totalWidth = tableWidth + 'px'; } else { @@ -761,7 +758,6 @@ define( if (!visible) { var scrollTop = displayRowIndex * this.$scope.rowHeight + - this.$scope.headerHeight - (this.scrollable[0].offsetHeight / 2); this.scrollable[0].scrollTop = scrollTop; this.setVisibleRows(); diff --git a/platform/features/table/test/controllers/MCTTableControllerSpec.js b/platform/features/table/test/controllers/MCTTableControllerSpec.js index a8dc9d7987..544a8fc5cc 100644 --- a/platform/features/table/test/controllers/MCTTableControllerSpec.js +++ b/platform/features/table/test/controllers/MCTTableControllerSpec.js @@ -29,7 +29,7 @@ define( function ($, moment, MCTTableController) { var MOCK_ELEMENT_TEMPLATE = - '
' + + '
' + '
' + '
' + '
';