Skip to content

Commit

Permalink
Refactor offsetHeight use float-compat API
Browse files Browse the repository at this point in the history
  • Loading branch information
mixonic committed May 20, 2022
1 parent 955b8b9 commit f3eb2b4
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 11 deletions.
10 changes: 2 additions & 8 deletions addon-test-support/helpers/element.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
export function getScale(element) {
let rect = element.getBoundingClientRect();
import { getScale } from 'ember-table/-private/utils/element';

if (element.offsetHeight === rect.height || rect.height === 0) {
return 1;
} else {
return element.offsetHeight / rect.height;
}
}
export { getScale };
28 changes: 28 additions & 0 deletions addon-test-support/pages/ember-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ export default PageObject.extend({
return findElement(this, 'table').offsetWidth;
},

/**
* Retrieves the logical width of the table.
*/
get logicalWidth() {
return window.getComputedStyle(findElement(this, 'table')).width;
},

/**
* Retrieves the rendered width of the table.
*/
get renderedWidth() {
return findElement(this, 'table').getBoundingClientRect().width;
},

/**
* Returns the table container width.
*
Expand All @@ -72,6 +86,20 @@ export default PageObject.extend({
return findElement(this).offsetWidth;
},

/**
* Retrieves the logical width of the container.
*/
get logicalContainerWidth() {
return window.getComputedStyle(findElement(this)).width;
},

/**
* Retrieves the rendered width of the container.
*/
get renderedContainerWidth() {
return findElement(this).getBoundingClientRect().width;
},

/**
* Returns the specified scroll indicator element
*/
Expand Down
4 changes: 3 additions & 1 deletion addon/-private/sticky/table-sticky-polyfill.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { getScale } from '../utils/element';

/* global ResizeSensor */
/* eslint-disable ember/no-observers */

Expand Down Expand Up @@ -171,7 +173,7 @@ class TableStickyPolyfill {
*/
repositionStickyElements = () => {
let table = this.element.parentNode;
let scale = table.offsetHeight / table.getBoundingClientRect().height;
let scale = getScale(table);
let containerHeight = table.parentNode.offsetHeight;

// exclude ResizeSensor divs
Expand Down
36 changes: 34 additions & 2 deletions addon/-private/utils/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,45 @@ export function closest(el, selector) {
return null;
}

/*
* Calculate the scale of difference between an element's logical height
* (the offsetHeight or getComputedStyle height) compared to its rendered
* height (via getBoundingClientRect).
*
* Note that there are some interesting edge cases to consider around
* these APIs.
*
* - `getComputedStyle` returns a string from styles in pixels. For
* example `48.23px`. The precision of this API in Chrome seems to
* be 3 decimal places. Additionally, there can be unexpected values
* such as `auto`. Finally, this API may be slow compared to other
* DOM API calls.
* - `offsetHeight` always returns in integer. If the height of an
* element is at float precision, then the value is rounded. This
* makes it at best useful as a fallback.
*
*/
export function getScale(element) {
let rect = element.getBoundingClientRect();
let renderedHeight = rect.height;

if (element.offsetHeight === rect.height || rect.height === 0) {
if (renderedHeight === 0) {
return 1;
}

let computedHeightStyleValue = window.getComputedStyle(element).height;
let computedHeightInPixels = Number(
computedHeightStyleValue.substring(0, computedHeightStyleValue.length - 2)
);

if (isNaN(computedHeightInPixels)) {
computedHeightInPixels = element.offsetHeight;
}

if (computedHeightInPixels === renderedHeight) {
return 1;
} else {
return element.offsetHeight / rect.height;
return computedHeightInPixels / renderedHeight;
}
}

Expand Down
33 changes: 33 additions & 0 deletions tests/unit/-private/element-utils-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { module, test } from 'qunit';
import { getScale } from 'ember-table/-private/utils/element';

module('Unit | Private | element', function(hooks) {
hooks.beforeEach(function() {
/*
* Use an element outside the normal test harness as that harness
* uses scale() on the test container.
*/
this.element = document.createElement('div');
document.body.append(this.element);
});

hooks.afterEach(function() {
this.element.remove();
});

test('can get the scale of a transformed element', function(assert) {
let div = document.createElement('div');
div.style.height = '4px';
this.element.append(div);

assert.equal(getScale(div), 1, 'scale on a simple element is correct');

div.style.transform = 'scale(0.5)';

assert.equal(getScale(div), 2, 'scale on a scaled element is correct');

div.style.height = '1.5px';

assert.equal(getScale(div), 2, 'scale on a scaled element is correct');
});
});

0 comments on commit f3eb2b4

Please sign in to comment.