Skip to content
This repository has been archived by the owner on Dec 12, 2018. It is now read-only.

On Demand Scrolling #39

Closed
wants to merge 5 commits into from
Closed

Conversation

pottedmeat
Copy link
Contributor

Type: feature

The following has been addressed in the PR:

  • There is a related issue
  • All code matches the style guide
  • Unit or Functional tests are included in the PR

Description:

Resolves #21

This introduces the slice API to data providers to request the data only contain a subsection of the currently available data the provider would otherwise return (including sorts etc.)

The grid body makes a slice request to the data provider that will contain enough data to fill the content area as well as buffer rows above and below it.

As rows are added and removed from the grid, their heights are factored into the scroll position of the scrollable area to ensure that as the size of the scrollable content changes, the scroll position remains at the same position within the visible content.

It adds a large margin before and after the content area so that rapid scrolling won't "hit an edge".

If scrolling is done so rapidly that the user ends up outside the buffer rows, the grid body estimates how far it has been scrolled beyond the buffer rows, makes a slice for that data, and scrolls to the estimated row.

Users can also define what index to scroll the data to through a grid property.

@codecov
Copy link

codecov bot commented May 30, 2017

Codecov Report

Merging #39 into master will decrease coverage by 36.13%.
The diff coverage is 32.67%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master      #39       +/-   ##
===========================================
- Coverage   98.17%   62.03%   -36.14%     
===========================================
  Files          10       10               
  Lines         219      461      +242     
  Branches       34      109       +75     
===========================================
+ Hits          215      286       +71     
- Misses          0      144      +144     
- Partials        4       31       +27
Impacted Files Coverage Δ
src/bases/DataProviderBase.ts 95.55% <100%> (+0.55%) ⬆️
src/Body.ts 30.96% <28.26%> (-69.04%) ⬇️
src/Grid.ts 85.36% <58.33%> (-11.51%) ⬇️
src/providers/ArrayDataProvider.ts 96.55% <83.33%> (-3.45%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4cbb547...5aa365b. Read the comment docs.

Copy link
Member

@dylans dylans left a comment

Choose a reason for hiding this comment

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

Two minor nits (my review focused on comments rather than the code logic)

@@ -8,7 +8,7 @@ import DataProviderBase from './bases/DataProviderBase';
import Body from './Body';
import GridRegistry, { gridRegistry } from './GridRegistry';
import Header from './Header';
import { DataProperties, HasColumns, SortRequestListener } from './interfaces';
import { DataProperties, HasBufferRows, HasColumns, HasScrollTo, ScrollToDetails, SliceRequestListener, SortRequestListener } from './interfaces';
Copy link
Member

Choose a reason for hiding this comment

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

Looks like some unintentional double spaces in here.

@@ -101,6 +107,18 @@ abstract class DataProviderBase<T = object, O extends DataProviderOptions = Data
}

/**
* Apply a slice to the data that would be returned
* otherwise. Can also be assigned from
Copy link
Member

Choose a reason for hiding this comment

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

assigned from ... ?

@dylans dylans added this to the 2017.06 milestone May 30, 2017

let rowHeight = 0;
let rowCount = 0;
for (let details of from(itemElementMap.values())) {
Copy link

Choose a reason for hiding this comment

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

Does itemElementMap contain collapsed rows in a tree scenario, and would they have an element that could mess up the average height if that is the case? Not sure if we're even worried about tree stuff for this PR.

Copy link
Contributor

@msssk msssk left a comment

Choose a reason for hiding this comment

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

Some comments inline, overall looks good.

classes: this.classes(bodyClasses.content)
key
}, [
w<Row>('row', {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is it necessary to wrap each row in a div?

* Based on what is currently rendered, find the average height
* of each row and, if nothing is rendered, return 20.
*/
protected estimatedRowHeight(): number {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be better if this is a property with get defined, or rename the method to getEstimatedRowHeight

* Uses the height of the scroll area and the estimated row height
* to estimate the number of rows that will fill it
*/
protected estimatedRowCount(): number {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be better if this is a property with get defined, or rename the method to getEstimatedRowCount


let rowHeight = 0;
let rowCount = 0;
for (let details of from(itemElementMap.values())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

A pain point I discovered in working with this same logic in dgrid 1 is that browsers do not always give reliable information about element dimensions, most notably when there is any scaling in effect (e.g. a high dpi display with OS-provided scaling, or zoom level set in the browser).

Inspecting a node in the dev tools would give a non-integer value, e.g. 25.57, whereas element.offsetHeight would report 25. This error accumulated over a large number of rows results in significant height discrepancies. I found it more accurate to get height values directly from the node containing all the rows, rather than summing up the heights of each individual row.

@@ -1,44 +1,590 @@
import { from, includes } from '@dojo/shim/array';
Copy link
Contributor

Choose a reason for hiding this comment

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

Have we developed any standard for this? Had any discussion? Personally I rather dislike importing and calling from directly. It doesn't make for clear code. I'd prefer:
array.from
or
import { from as toArray } from '@dojo/shim/array';

}, children);
}

protected visibleKeys() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be better if this is a property with get defined, or rename the method to getVisibleKeys

break;
}
}
for (const renderedDetails of allDetails.reverse()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might calling reverse impact performance?

} = {}
}
} = this;
const max = (dataLength > 0 ? dataLength - 1 : 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

max what? Could this benefit from a more descriptive name?


// Use previous keys to watch for deleted items
// and insert new keys at the indexes detected above
for (let i = 0, il = previousKeys.length; i <= il; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use a more descriptive name than il? Perhaps i as well given the length and complexity of this loop.

sort?: SortDetails[];
}

export interface HasBufferRows {
/**
* @default 10
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like not the right place to document default values - is it possible to document them in the right place and get the right generated doc output?

@pottedmeat pottedmeat closed this Jun 29, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants