Skip to content

Commit

Permalink
Fix positioning of table footer rows when rows are of varying heights
Browse files Browse the repository at this point in the history
  • Loading branch information
jiayingxu committed Oct 27, 2020
1 parent 70d0960 commit 3716d2d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 7 deletions.
7 changes: 4 additions & 3 deletions addon/-private/sticky/table-sticky-polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class TableStickyPolyfill {
add row 0's height (25px) to its current offset and move on to row 1,
where it will set each of that row's `th` cells' `top` to the current
offset of `25px`.
* For the tfoot TableStickyPolyfill, its `respositionStickyElements` will
* For the tfoot TableStickyPolyfill, its `repositionStickyElements` will
start at the bottom-most row, row 1, and set each of its `td` cells'
`bottom` value to `0px`, then add row 1's height (20px) to its current
offset and move on to the next row, row 0, where it will set each of that
Expand Down Expand Up @@ -187,8 +187,9 @@ class TableStickyPolyfill {
for (let i = 0; i < rows.length; i++) {
// Work top-down (index order) for 'top', bottom-up (reverse index
// order) for 'bottom' rows
let row = rows[this.side === 'top' ? i : rows.length - 1 - i];
let height = heights[i];
let index = this.side === 'top' ? i : rows.length - 1 - i;
let row = rows[index];
let height = heights[index];

for (let child of row.children) {
child.style.position = '-webkit-sticky';
Expand Down
82 changes: 78 additions & 4 deletions tests/unit/-private/table-sticky-polyfill-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,23 @@ const standardTemplate = hbs`
</div>
`;

function constructMatrix(n, m, prefix = '') {
/**
* Constructs a matrix m by n
* @param m Rows
* @param n Columns
* @param prefix Prefix string
* @param skipPrefixOnRowIndices Skip adding the prefix string to the row (m) indices specified in the list
* @returns {Array} matrix
*/
function constructMatrix(m, n, prefix = '', skipPrefixOnRowIndices = []) {
let rows = emberA();

for (let i = 0; i < n; i++) {
for (let i = 0; i < m; i++) {
let cols = emberA();

for (let j = 0; j < m; j++) {
cols.pushObject(`${m}${prefix}`);
for (let j = 0; j < n; j++) {
let skipPrefix = skipPrefixOnRowIndices.includes(i);
cols.pushObject(skipPrefix ? n : `${n}${prefix}`);
}

rows.pushObject(cols);
Expand Down Expand Up @@ -100,6 +109,38 @@ function verifyFooter(assert) {
});
}

/**
* Verifies multi line header when scrolled to the bottom of the table
* @param assert
*/
function verifyMultiLineHeader(assert) {
let firstCellRect = find('thead tr:first-child th:first-child').getBoundingClientRect();
let expectedOffset = firstCellRect.top;

findAll('thead > tr')
.forEach((row, i) => {
let firstCellRect = row.firstElementChild.getBoundingClientRect();
expectedOffset += firstCellRect.height;
assert.equal(expectedOffset, firstCellRect.bottom);
});
}

/**
* Verifies multi line footer when scrolled to the top of the table
* @param assert
*/
function verifyMultiLineFooter(assert) {
let firstCellRect = find('tfoot tr:first-child td:first-child').getBoundingClientRect();
let expectedOffset = firstCellRect.top;

findAll('tfoot > tr')
.forEach((row, i) => {
let firstCellRect = row.firstElementChild.getBoundingClientRect();
expectedOffset += firstCellRect.height;
assert.equal(expectedOffset, firstCellRect.bottom);
});
}

componentModule('Unit | Private | TableStickyPolyfill', function() {
test('it works', async function(assert) {
this.set('headerRows', constructMatrix(3, 3, 'thead'));
Expand Down Expand Up @@ -293,4 +334,37 @@ componentModule('Unit | Private | TableStickyPolyfill', function() {
'the bottom of the last header cell is close to 50% of the way down the table'
);
});

test('when the header has rows with varying heights', async function(assert) {
this.set('headerRows', constructMatrix(2, 3, 'table header has multiple lines of content', [1]));
this.set('bodyRows', constructMatrix(20, 3, 'body'));
this.set('footerRows', constructMatrix(1, 3, 'footer'));

await this.render(standardTemplate);

setupTableStickyPolyfill(find('thead'));
setupTableStickyPolyfill(find('tfoot'));

await wait();

let container = find('.ember-table');
await scrollTo('.ember-table', 0, container.scrollHeight);

verifyMultiLineHeader(assert);
});

test('when the footer has rows with varying heights', async function(assert) {
this.set('headerRows', constructMatrix(1, 3, 'header'));
this.set('bodyRows', constructMatrix(20, 3, 'body'));
this.set('footerRows', constructMatrix(2, 3, 'table footer has multiple lines of content', [1]));

await this.render(standardTemplate);

setupTableStickyPolyfill(find('thead'));
setupTableStickyPolyfill(find('tfoot'));

await wait();

verifyMultiLineFooter(assert);
});
});

0 comments on commit 3716d2d

Please sign in to comment.