Skip to content

Commit

Permalink
fix(uiGridHeader): Fix dynamic header heights
Browse files Browse the repository at this point in the history
Previously header cell heights were calculated based on a "max height is
king" algorithm where cells could grow to match the largest height, but
could never shrink, e.g. this let cells with no filter box be the same
height as those with no filter box.

This presented a problem with toggling features like filtering. If
suddenly no columns were filterable this would leave a big empty space at
the bottom of each header cell.

This change makes header cells display-type "table-cell", which lets them
render like a TD with full height, and places them in table-row and
table divs. Replacing "width" with "min-width" and "max-width" forces the
header cells to be the correct width.

Also the `columnStyle` method has been replaced with a
`columnWrapperStyle` method.
  • Loading branch information
c0bra committed Feb 18, 2015
1 parent 78a4b43 commit 893bb13
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 77 deletions.
69 changes: 7 additions & 62 deletions src/js/core/directives/ui-grid-render-container.js
Expand Up @@ -100,7 +100,7 @@
var newScrollLeft = args.getNewScrollLeft(colContainer,containerCtrl.viewport);

// Make the current horizontal scroll position available in the $scope
$scope.newScrollLeft = newScrollLeft;
$scope.newScrollLeft = newScrollLeft;

if (containerCtrl.headerViewport) {
containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.headerViewport, newScrollLeft);
Expand All @@ -110,7 +110,7 @@
containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.footerViewport, newScrollLeft);
}

//scroll came from somewhere else, so the viewport must be positioned
// Scroll came from somewhere else, so the viewport must be positioned
if (args.source !== ScrollEvent.Sources.ViewPortScroll) {
containerCtrl.viewport[0].scrollLeft = newScrollLeft;
}
Expand Down Expand Up @@ -189,22 +189,17 @@
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';

ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';

if (renderContainer.explicitHeaderCanvasHeight) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
}

ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';

ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + canvasWidth + grid.scrollbarWidth + 'px; }';
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';

// If the render container has an "explicit" header height (such as in the case that its header is smaller than the other headers and needs to be explicitly set to be the same, ue thae)
if (renderContainer.explicitHeaderCanvasHeight !== undefined && renderContainer.explicitHeaderCanvasHeight !== null && renderContainer.explicitHeaderCanvasHeight > 0) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { min-height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
}
// Otherwise if the render container has an INNER header height, use that on the header cells (so that all the header cells are the same height and those that have less elements don't have undersized borders)
else if (renderContainer.headerCanvasHeight !== undefined && renderContainer.headerCanvasHeight !== null && renderContainer.headerCanvasHeight > 0) {
ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-cell { min-height: ' + renderContainer.headerCanvasHeight + 'px; }';
}

return ret;
}

Expand All @@ -220,57 +215,7 @@
}]);

module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {
var self = this;

self.rowStyle = function (index) {
var renderContainer = $scope.grid.renderContainers[$scope.containerId];

var styles = {};

if (!renderContainer.disableRowOffset) {
if (index === 0 && self.currentTopRow !== 0) {
// The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered
var hiddenRowWidth = ($scope.rowContainer.currentTopRow) *
$scope.rowContainer.visibleRowCache[$scope.rowContainer.currentTopRow].height;

// return { 'margin-top': hiddenRowWidth + 'px' };
//gridUtil.logDebug('margin-top ' + hiddenRowWidth );
styles['margin-top'] = hiddenRowWidth + 'px';
}
}

if (!renderContainer.disableColumnOffset && $scope.colContainer.currentFirstColumn !== 0) {
if ($scope.grid.isRTL()) {
styles['margin-right'] = $scope.colContainer.columnOffset + 'px';
}
else {
styles['margin-left'] = $scope.colContainer.columnOffset + 'px';
}
}

return styles;
};

self.columnStyle = function (index) {
var renderContainer = $scope.grid.renderContainers[$scope.containerId];

var self = this;

if (!renderContainer.disableColumnOffset) {
if (index === 0 && $scope.colContainer.currentFirstColumn !== 0) {
var offset = $scope.colContainer.columnOffset;

if ($scope.grid.isRTL()) {
return { 'margin-right': offset + 'px' };
}
else {
return { 'margin-left': offset + 'px' };
}
}
}

return null;
};

}]);

})();
2 changes: 1 addition & 1 deletion src/js/core/factories/GridColumn.js
Expand Up @@ -585,7 +585,7 @@ angular.module('ui.grid')
* @description Returns the class definition for th column
*/
GridColumn.prototype.getColClassDefinition = function () {
return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { width: ' + this.drawnWidth + 'px; }';
return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';
};

/**
Expand Down
4 changes: 2 additions & 2 deletions src/js/core/factories/GridRenderContainer.js
Expand Up @@ -518,10 +518,10 @@ angular.module('ui.grid')
return styles;
};

GridRenderContainer.prototype.columnStyle = function (index) {
GridRenderContainer.prototype.headerCellWrapperStyle = function () {
var self = this;

if (index === 0 && self.currentFirstColumn !== 0) {
if (self.currentFirstColumn !== 0) {
var offset = self.columnOffset;

if (self.grid.isRTL()) {
Expand Down
14 changes: 12 additions & 2 deletions src/less/footer.less
Expand Up @@ -45,15 +45,25 @@
// .border-radius(@gridBorderRadius, 0, 0, @gridBorderRadius);
}

.ui-grid-footer-cell-wrapper {
position: relative;
display: table;
box-sizing: border-box;
height: 100%;
}

.ui-grid-footer-cell-row {
display: table-row;
}

.ui-grid-footer-cell {
overflow: hidden;
// position: absolute;
// position: relative; // NOTE: removing so border is visible
float: left;
background-color: inherit;
border-right: @gridBorderWidth solid;
border-color: @borderColor;
box-sizing: border-box;
display: table-cell;

&:last-child {
border-right: 0;
Expand Down
16 changes: 12 additions & 4 deletions src/less/header.less
Expand Up @@ -29,7 +29,6 @@
}

.ui-grid-header-canvas {
position: relative;

// Clearfix for floating header cells
&:before, &:after {
Expand All @@ -45,15 +44,24 @@
// .border-radius(@gridBorderRadius, 0, 0, @gridBorderRadius);
}

.ui-grid-header-cell-wrapper {
position: relative;
display: table;
box-sizing: border-box;
height: 100%;
}

.ui-grid-header-cell-row {
display: table-row;
}

.ui-grid-header-cell {
position: relative;
box-sizing: border-box;
float: left;
top: 0;
bottom: 0;
background-color: inherit;
border-right: @gridBorderWidth solid;
border-color: @headerVerticalBarColor;
display: table-cell;

&:last-child {
border-right: 0;
Expand Down
10 changes: 7 additions & 3 deletions src/templates/ui-grid/ui-grid-footer.html
@@ -1,7 +1,11 @@
<div class="ui-grid-footer-panel ui-grid-footer-aggregates-row">
<div class="ui-grid-footer ui-grid-footer-viewport">
<div class="ui-grid-footer-canvas">
<div ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ui-grid-footer-cell col="col" render-index="$index" class="ui-grid-footer-cell ui-grid-clearfix" ng-style="$index === 0 && colContainer.columnStyle($index)"></div>
<div class="ui-grid-footer ui-grid-footer-viewport">
<div class="ui-grid-footer-canvas">
<div class="ui-grid-footer-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()">
<div class="ui-grid-footer-cell-row">
<div ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ui-grid-footer-cell col="col" render-index="$index" class="ui-grid-footer-cell ui-grid-clearfix"></div>
</div>
</div>
</div>
</div>
</div>
5 changes: 4 additions & 1 deletion src/templates/ui-grid/ui-grid-header.html
Expand Up @@ -2,8 +2,11 @@
<div class="ui-grid-top-panel">
<div class="ui-grid-header-viewport">
<div class="ui-grid-header-canvas">
<div class="ui-grid-header-cell ui-grid-clearfix" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ui-grid-header-cell col="col" render-index="$index" ng-style="$index === 0 && colContainer.columnStyle($index)">
<div class="ui-grid-header-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()">
<div class="ui-grid-header-cell-row">
<div class="ui-grid-header-cell ui-grid-clearfix" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" ui-grid-header-cell col="col" render-index="$index"></div>
</div>
</div>
</div>

</div>
Expand Down
4 changes: 2 additions & 2 deletions src/templates/ui-grid/uiGridViewport.html
@@ -1,6 +1,6 @@
<div class="ui-grid-viewport" ng-style="containerCtrl.colContainer.getViewPortStyle()">
<div class="ui-grid-viewport" ng-style="colContainer.getViewPortStyle()">
<div class="ui-grid-canvas">
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row" ng-style="containerCtrl.rowStyle(rowRenderIndex)">
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row" ng-style="rowContainer.rowStyle(rowRenderIndex)">
<div ui-grid-row="row" row-render-index="rowRenderIndex"></div>
</div>
</div>
Expand Down

0 comments on commit 893bb13

Please sign in to comment.