Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve footer tracking for bottom scroll indicator #873

Merged

Conversation

ahmacleod
Copy link
Contributor

@ahmacleod ahmacleod commented Feb 11, 2021

In order to position the bottom scroll indicator correctly, we need to know if and when the visible portion of the footer changes height. Presently, we detect when the dimensions of the table's container changes, but not specifically when the height of the footer, or the position of its sticky cells, change. These changes can occur without altering the overall height or width of the table, which can leave the bottom scroll indicator floating in the wrong position.

So far this has only been a problem in testing environments, where it manifests as an erratic race condition during initial render. It is exacerbated by increased functionality in the footer (e.g. child rows), because of increased jostling during layout. During a typical application pageload, there are sufficiently many layout changes that the effect is rarely seen.

Since it is possible to programmatically add and remove a footer from the table, we install and remove those listeners dynamically.

Changes:

  • Dynamically installs ResizeSensor on footer to detect changes in total footer height
  • Dynamically installs MutationObserver on footer to detect changes to the style attribute of td elements; we are interested in when bottom changes value

@ahmacleod ahmacleod marked this pull request as draft February 11, 2021 22:17
@ahmacleod ahmacleod force-pushed the alex.macleod.temp/improve-bottom-scroll-indicator-tracking branch from 97e11b5 to 5e9f9df Compare February 24, 2021 22:57
@ahmacleod ahmacleod force-pushed the alex.macleod.temp/improve-bottom-scroll-indicator-tracking branch from 5e9f9df to ffa0efa Compare February 24, 2021 23:03
@ahmacleod ahmacleod marked this pull request as ready for review February 24, 2021 23:15
@ahmacleod ahmacleod requested review from a team and jiayingxu March 15, 2021 22:02
Copy link
Contributor

@twokul twokul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code change looks fine. Could you explain your approach?

@@ -269,6 +317,12 @@ export default Component.extend({

didInsertElement() {
this._super(...arguments);

// debounced, runloop-safe version
this._updateIndicators = bind(this, () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need bind here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a leftover, let's nix it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, I forgot this is why:
image

You need to wrap the scheduleOnce in a run loop or else the test suite gets mad. You can't get at it from the test itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two more questions on this topic:

  • Why do we set this._updateIndicators inside didInsertElement vs. init?
  • Are there any issues with using an anonymous function vs. a function defined on the component?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. No objection; consider it moved.

  2. Not afaik. Anything we move to a component function is ultimately going to have to be wrapped in a bind or something that produces an anonymous function anyway. This forward declaration does a lot of heavy lifting:

  • Context binding for a scroll listener, two ResizeSensors, and a MutationObserver
  • Deals with the test runloop situation
  • Encapsulates the scheduleOnce
  • Simplifies removing the scroll listener on teardown; don't have to cache a this._scrollListener function

What we can do is dump the bind for a run. The context is already available via the anonymous closure, so run is a more precise solution to its problem and can be documented as such.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run won't cut it for ember-2.8-lts test suite. I've notated the seemingly redundant bind for now; we can visit when we drop 2.8 support.

@ahmacleod ahmacleod requested review from twokul and a team March 18, 2021 22:26
Copy link
Contributor

@twokul twokul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a comment. Provisional ✅

@@ -269,6 +317,12 @@ export default Component.extend({

didInsertElement() {
this._super(...arguments);

// debounced, runloop-safe version
this._updateIndicators = bind(this, () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two more questions on this topic:

  • Why do we set this._updateIndicators inside didInsertElement vs. init?
  • Are there any issues with using an anonymous function vs. a function defined on the component?

@ahmacleod ahmacleod merged commit 85abbae into master Mar 26, 2021
@ahmacleod ahmacleod deleted the alex.macleod.temp/improve-bottom-scroll-indicator-tracking branch March 26, 2021 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants