Skip to content

Commit

Permalink
Fix bug of space to the right of the last column (#6513)
Browse files Browse the repository at this point in the history
The change to using integer column widths means that we sometimes have some grid width left over where column widths are rounded down for asterisk or percentage widths, see #6371. The logic that then re-allocates the remaining widths currently only does this over columns with asterisk widths.

I've updated the logic to check if there are any asterisk columns and, if not, check for any percentage columns as a fall back. Only if there are no asterisk column widths, all columns are percentage widths and the percentages add up to 100%, then the percentage columns will be used to allocate remaining space, or trim if needed.
  • Loading branch information
RobPierce authored and mportuga committed Dec 22, 2017
1 parent faa8ece commit a2f2fd5
Showing 1 changed file with 62 additions and 43 deletions.
105 changes: 62 additions & 43 deletions src/js/core/factories/GridRenderContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -609,20 +609,23 @@ angular.module('ui.grid')
asteriskNum = 0,
usedWidthSum = 0,
ret = '',
pinRightColumn = false;
pinRightColumn = false,
fixedNumberArray = [],
percentageArray = [],
totalPercentage = 0;

// Get the width of the viewport
var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;

// get all the columns across all render containers, we have to calculate them all or one render container
// could consume the whole viewport
var columnCache = [];
angular.forEach(self.grid.renderContainers, function( container, name){
angular.forEach(self.grid.renderContainers, function (container, name) {
columnCache = columnCache.concat(container.visibleColumnCache);
});

// look at each column, process any manual values or %, put the * into an array to look at later
columnCache.forEach(function(column, i) {
columnCache.forEach(function (column, i) {
var width = 0;
// Skip hidden columns
if (!column.visible) { return; }
Expand All @@ -641,21 +644,26 @@ angular.module('ui.grid')
usedWidthSum = usedWidthSum + width;
column.drawnWidth = width;

fixedNumberArray.push(column);
} else if (gridUtil.endsWith(column.width, "%")) {
// percentage width, set to percentage of the viewport
// round down to int - some browsers don't play nice with float maxWidth
width = parseInt(parseInt(column.width.replace(/%/g, ''), 10) / 100 * availableWidth);
var percentageIntegerValue = parseInt(column.width.replace(/%/g, ''), 10);
width = parseInt(percentageIntegerValue / 100 * availableWidth);

if ( width > column.maxWidth ){
if (width > column.maxWidth) {
width = column.maxWidth;
}

if ( width < column.minWidth ){
if (width < column.minWidth) {
width = column.minWidth;
}

usedWidthSum = usedWidthSum + width;
column.drawnWidth = width;

totalPercentage = totalPercentage + percentageIntegerValue;
percentageArray.push(column);
} else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {
// is an asterisk column, the gridColumn already checked the string consists only of '****'
asteriskNum = asteriskNum + column.width.length;
Expand All @@ -672,62 +680,73 @@ angular.module('ui.grid')
// the width that each asterisk value would be assigned (this can be negative)
var asteriskVal = remainingWidth / asteriskNum;

asterisksArray.forEach(function( column ){
asterisksArray.forEach(function (column) {
var width = parseInt(column.width.length * asteriskVal, 10);

if ( width > column.maxWidth ){
width = column.maxWidth;
if (width > column.maxWidth) {
width = column.maxWidth;
}

if ( width < column.minWidth ){
width = column.minWidth;
if (width < column.minWidth) {
width = column.minWidth;
}

usedWidthSum = usedWidthSum + width;
column.drawnWidth = width;
});
}

// If the grid width didn't divide evenly into the column widths and we have pixels left over, or our
// calculated widths would have the grid narrower than the available space,
// dole the remainder out one by one to make everything fit
var processColumnUpwards = function(column){
if ( column.drawnWidth < column.maxWidth && leftoverWidth > 0) {
column.drawnWidth++;
usedWidthSum++;
leftoverWidth--;
columnsToChange = true;
}
};
// If there are no columns with asterisk widths then check if there are any with % widths and
// use them as a fallback for adjusting column widths up or down if we have remaining grid width
// or need to claw some width back
var variableWidthColumnArray;
if (asterisksArray.length > 0) {
variableWidthColumnArray = asterisksArray;
} else if (percentageArray.length > 0 && fixedNumberArray.length === 0 && totalPercentage === 100) {
variableWidthColumnArray = percentageArray;
}

var leftoverWidth = availableWidth - usedWidthSum;
var columnsToChange = true;
if (!angular.isUndefined(variableWidthColumnArray)) {
// If the grid width didn't divide evenly into the column widths and we have pixels left over, or our
// calculated widths would have the grid narrower than the available space,
// dole the remainder out one by one to make everything fit
var processColumnUpwards = function (column) {
if (column.drawnWidth < column.maxWidth && leftoverWidth > 0) {
column.drawnWidth++;
usedWidthSum++;
leftoverWidth--;
columnsToChange = true;
}
};

while (leftoverWidth > 0 && columnsToChange) {
columnsToChange = false;
asterisksArray.forEach(processColumnUpwards);
}
var leftoverWidth = availableWidth - usedWidthSum;
var columnsToChange = true;

// We can end up with too much width even though some columns aren't at their max width, in this situation
// we can trim the columns a little
var processColumnDownwards = function(column){
if ( column.drawnWidth > column.minWidth && excessWidth > 0) {
column.drawnWidth--;
usedWidthSum--;
excessWidth--;
columnsToChange = true;
while (leftoverWidth > 0 && columnsToChange) {
columnsToChange = false;
variableWidthColumnArray.forEach(processColumnUpwards);
}
};

var excessWidth = usedWidthSum - availableWidth;
columnsToChange = true;
// We can end up with too much width even though some columns aren't at their max width, in this situation
// we can trim the columns a little
var processColumnDownwards = function (column) {
if (column.drawnWidth > column.minWidth && excessWidth > 0) {
column.drawnWidth--;
usedWidthSum--;
excessWidth--;
columnsToChange = true;
}
};

var excessWidth = usedWidthSum - availableWidth;
columnsToChange = true;

while (excessWidth > 0 && columnsToChange) {
columnsToChange = false;
asterisksArray.forEach(processColumnDownwards);
while (excessWidth > 0 && columnsToChange) {
columnsToChange = false;
variableWidthColumnArray.forEach(processColumnDownwards);
}
}


// all that was across all the renderContainers, now we need to work out what that calculation decided for
// our renderContainer
var canvasWidth = 0;
Expand Down

0 comments on commit a2f2fd5

Please sign in to comment.