diff --git a/src/vaadin-grid-drag-and-drop-mixin.html b/src/vaadin-grid-drag-and-drop-mixin.html index 03473e99d..aa1b81b81 100644 --- a/src/vaadin-grid-drag-and-drop-mixin.html +++ b/src/vaadin-grid-drag-and-drop-mixin.html @@ -303,6 +303,20 @@ /** @private */ __getViewportRows() { + // Workaround an IE11 bug where the `getBoundingClientRect` for header/footer + // might return incorrect values + if (this._ie) { + this.$.header.style.outline = '0px solid transparent'; + const scrollerRect = this.$.scroller.getBoundingClientRect(); + const headerBottom = Math.max(this.$.header.getBoundingClientRect().bottom, scrollerRect.top); + const footerTop = Math.min(this.$.footer.getBoundingClientRect().top, scrollerRect.bottom); + + return Array.from(this.$.items.children).filter((row) => { + const rowRect = row.getBoundingClientRect(); + return rowRect.bottom > headerBottom && rowRect.top < footerTop; + }); + } + const headerBottom = this.$.header.getBoundingClientRect().bottom; const footerTop = this.$.footer.getBoundingClientRect().top; return Array.from(this.$.items.children) diff --git a/src/vaadin-grid.html b/src/vaadin-grid.html index f6225d96b..f4f3ecaac 100644 --- a/src/vaadin-grid.html +++ b/src/vaadin-grid.html @@ -467,37 +467,70 @@ } } + /** @private */ + __getIntrinsicWidth(col) { + const initialWidth = col.width; + const initialFlexGrow = col.flexGrow; + + col.width = 'auto'; + col.flexGrow = 0; + + // Note: _allCells only contains cells which are currently rendered in DOM + const width = col._allCells + .reduce((width, cell) => { + // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering) + return Math.max(width, cell.offsetWidth + 1); + }, 0); + + col.flexGrow = initialFlexGrow; + col.width = initialWidth; + + return width; + } + + /** @private */ + __getDistributedWidth(col, innerColumn) { + if (col == null || col === this) { + return 0; + } + + const columnWidth = Math.max(this.__getIntrinsicWidth(col), this.__getDistributedWidth(col.parentElement, col)); + + // we're processing a regular grid-column and not a grid-column-group + if (!innerColumn) { + return columnWidth; + } + + // At the end, the width of each vaadin-grid-column-group is determined by the sum of the width of its children. + // Here we determine how much space the vaadin-grid-column-group actually needs to render properly and then we distribute that space + // to its children, so when we actually do the summation it will be rendered properly. + // Check out vaadin-grid-column-group:_updateFlexAndWidth + const columnGroup = col; + const columnGroupWidth = columnWidth; + const sumOfWidthOfAllChildColumns = columnGroup._visibleChildColumns + .map((col) => this.__getIntrinsicWidth(col)) + .reduce((sum, curr) => sum + curr, 0); + + const extraNecessarySpaceForGridColumnGroup = Math.max(0, columnGroupWidth - sumOfWidthOfAllChildColumns); + + // The distribution of the extra necessary space is done according to the intrinsic width of each child column. + // Lets say we need 100 pixels of extra space for the grid-column-group to render properly + // it has two grid-column children, |100px|300px| in total 400px + // the first column gets 25px of the additional space (100/400)*100 = 25 + // the second column gets the 75px of the additional space (300/400)*100 = 75 + const proportionOfExtraSpace = this.__getIntrinsicWidth(innerColumn) / sumOfWidthOfAllChildColumns; + const shareOfInnerColumnFromNecessaryExtraSpace = proportionOfExtraSpace * extraNecessarySpaceForGridColumnGroup; + + return this.__getIntrinsicWidth(innerColumn) + shareOfInnerColumnFromNecessaryExtraSpace; + } + /** * @param {!Array} cols the columns to auto size based on their content width * @private */ _recalculateColumnWidths(cols) { - // Note: The `cols.forEach()` loops below could be implemented as a single loop but this has been - // split for performance reasons to batch these similar actions [write/read] together to avoid - // unnecessary layout trashing. - - // [write] Set automatic width for all cells (breaks column alignment) - cols.forEach(col => { - col.width = 'auto'; - col._origFlexGrow = col.flexGrow; - col.flexGrow = 0; - }); - // [read] Measure max cell width in each column - cols.forEach(col => { - col._currentWidth = 0; - // Note: _allCells only contains cells which are currently rendered in DOM - col._allCells.forEach(c => { - // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering) - const cellWidth = c.offsetWidth + 1; - col._currentWidth = Math.max(col._currentWidth, cellWidth); - }); - }); - // [write] Set column widths to fit widest measured content - cols.forEach(col => { - col.width = `${col._currentWidth}px`; - col.flexGrow = col._origFlexGrow; - col._currentWidth = undefined; - col._origFlexGrow = undefined; + cols.forEach((col) => { + col.width = `${this.__getDistributedWidth(col)}px`; }); } diff --git a/test/column-auto-width.html b/test/column-auto-width.html index 58128b1d9..3f2080c99 100644 --- a/test/column-auto-width.html +++ b/test/column-auto-width.html @@ -13,6 +13,7 @@ +
@@ -36,6 +37,110 @@ +