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

Add center option for scrollToAlignment #252

Merged
merged 3 commits into from May 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/Collection.md
Expand Up @@ -19,7 +19,7 @@ Unlike `Grid`, which renders checkerboard data, `Collection` can render arbitrar
| onSectionRendered | Function | | Callback invoked with information about the section of the Collection that was just rendered: `({ indices: Array<number> }): void` |
| onScroll | Function | | Callback invoked whenever the scroll offset changes within the inner scrollable region: `({ clientHeight: number, clientWidth: number, scrollHeight: number, scrollLeft: number, scrollTop: number, scrollWidth: number }): void` |
| scrollLeft | Number | | Horizontal offset |
| scrollToAlignment | String | | Controls the alignment of scrolled-to-cells. The default ("_auto_") scrolls the least amount possible to ensure that the specified cell is fully visible. Use "_start_" to always align cells to the top/left of the `Collection` and "_end_" to align them bottom/right. |
| scrollToAlignment | String | | Controls the alignment of scrolled-to-cells. The default ("_auto_") scrolls the least amount possible to ensure that the specified cell is fully visible. Use "_start_" to always align cells to the top/left of the `Collection` and "_end_" to align them bottom/right. Use "_center_" to align specified cell in the middle of container. |
| scrollToCell | Number | | Cell index to ensure visible (by scrolling if necessary) |
| scrollTop | Number | | Vertical offset |
| sectionSize | Number | | Optionally override the size of the sections a Collection's cells are split into. This is an advanced option and should only be used for performance tuning purposes. |
Expand Down
2 changes: 1 addition & 1 deletion docs/FlexTable.md
Expand Up @@ -25,7 +25,7 @@ This component expects explicit width, height, and padding parameters.
| rowGetter | Function | ✓ | Callback responsible for returning a data row given an index. `({ index: int }): any` |
| rowHeight | Number or Function | ✓ | Either a fixed row height (number) or a function that returns the height of a row given its index: `({ index: number }): number` |
| rowStyle | Object | | Optional custom inline style to attach to table rows. |
| scrollToAlignment | String | | Controls the alignment scrolled-to-rows. The default ("_auto_") scrolls the least amount possible to ensure that the specified row is fully visible. Use "_start_" to always align rows to the top of the list and "_end_" to align them bottom. |
| scrollToAlignment | String | | Controls the alignment scrolled-to-rows. The default ("_auto_") scrolls the least amount possible to ensure that the specified row is fully visible. Use "_start_" to always align rows to the top of the list and "_end_" to align them bottom. Use "_center_" to align them in the middle of container. |
| scrollToIndex | Number | | Row index to ensure visible (by forcefully scrolling if necessary) |
| scrollTop | Number | | Vertical offset |
| sort | Function | | Sort function to be called if a sortable header is clicked. `({ sortBy: string, sortDirection: SortDirection }): void` |
Expand Down
2 changes: 1 addition & 1 deletion docs/Grid.md
Expand Up @@ -21,7 +21,7 @@ Only a small number of cells are rendered based on the horizontal and vertical s
| rowCount | Number | ✓ | Number of rows in grid. |
| rowHeight | Number or Function | ✓ | Either a fixed row height (number) or a function that returns the height of a row given its index: `({ index: number }): number` |
| scrollLeft | Number | | Horizontal offset |
| scrollToAlignment | String | | Controls the alignment of scrolled-to-cells. The default ("_auto_") scrolls the least amount possible to ensure that the specified cell is fully visible. Use "_start_" to always align cells to the top/left of the `Grid` and "_end_" to align them bottom/right. |
| scrollToAlignment | String | | Controls the alignment of scrolled-to-cells. The default ("_auto_") scrolls the least amount possible to ensure that the specified cell is fully visible. Use "_start_" to always align cells to the top/left of the `Grid` and "_end_" to align them bottom/right. Use "_center_" to align specified cell in the middle of container. |
| scrollToColumn | Number | | Column index to ensure visible (by forcefully scrolling if necessary) |
| scrollToRow | Number | | Row index to ensure visible (by forcefully scrolling if necessary) |
| scrollTop | Number | | Vertical offset |
Expand Down
2 changes: 1 addition & 1 deletion docs/VirtualScroll.md
Expand Up @@ -15,7 +15,7 @@ This component renders a virtualized list of elements with either fixed or dynam
| rowHeight | Number or Function | ✓ | Either a fixed row height (number) or a function that returns the height of a row given its index: `({ index: number }): number` |
| rowRenderer | Function | ✓ | Responsbile for rendering a row given an index. Signature should look like `({ index: number, isScrolling: boolean }): React.PropTypes.node` |
| rowCount | Number | ✓ | Number of rows in list. |
| scrollToAlignment | String | | Controls the alignment scrolled-to-rows. The default ("_auto_") scrolls the least amount possible to ensure that the specified row is fully visible. Use "_start_" to always align rows to the top of the list and "_end_" to align them bottom. |
| scrollToAlignment | String | | Controls the alignment scrolled-to-rows. The default ("_auto_") scrolls the least amount possible to ensure that the specified row is fully visible. Use "_start_" to always align rows to the top of the list and "_end_" to align them bottom. Use "_center_" to align them in the middle of container. |
| scrollToIndex | Number | | Row index to ensure visible (by forcefully scrolling if necessary) |
| scrollTop | Number | | Forced vertical scroll offset; can be used to synchronize scrolling between components |
| style | Object | | Optional custom inline style to attach to root `VirtualScroll` element. |
Expand Down
9 changes: 9 additions & 0 deletions source/Collection/Collection.test.js
Expand Up @@ -215,6 +215,15 @@ describe('Collection', () => {
// This cell would already by visible by "auto" rules
expect(grid.refs.CollectionView.state.scrollLeft).toEqual(1)
expect(grid.refs.CollectionView.state.scrollTop).toEqual(0)

grid = render(getMarkup({
scrollToAlignment: 'center',
scrollToCell: 4,
width: SECTION_SIZE
}))
// This cell would already by visible by "auto" rules
expect(grid.refs.CollectionView.state.scrollLeft).toEqual(1)
expect(grid.refs.CollectionView.state.scrollTop).toEqual(0)
})

it('should scroll to a cell just added', () => {
Expand Down
2 changes: 1 addition & 1 deletion source/Collection/CollectionView.js
Expand Up @@ -79,7 +79,7 @@ export default class CollectionView extends Component {
* The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible.
* Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right.
*/
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start']).isRequired,
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired,

/**
* Cell index to ensure visible (by forcefully scrolling if necessary).
Expand Down
2 changes: 1 addition & 1 deletion source/FlexTable/FlexTable.js
Expand Up @@ -103,7 +103,7 @@ export default class FlexTable extends Component {
rowStyle: PropTypes.object,

/** See Grid#scrollToAlignment */
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start']).isRequired,
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired,

/** Row index to ensure visible (by forcefully scrolling if necessary) */
scrollToIndex: PropTypes.number,
Expand Down
2 changes: 1 addition & 1 deletion source/Grid/Grid.js
Expand Up @@ -141,7 +141,7 @@ export default class Grid extends Component {
* The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible.
* Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right.
*/
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start']).isRequired,
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired,

/**
* Column index to ensure visible (by forcefully scrolling if necessary)
Expand Down
19 changes: 19 additions & 0 deletions source/Grid/Grid.test.js
Expand Up @@ -299,6 +299,25 @@ describe('Grid', () => {
expect(grid.state.scrollLeft).toEqual(1050)
expect(grid.state.scrollTop).toEqual(900)
})

it('should scroll to the correct position for :scrollToAlignment "center"', () => {
render(getMarkup({
scrollToColumn: 99,
scrollToRow: 99
}))
const grid = render(getMarkup({
scrollToAlignment: 'center',
scrollToColumn: 24,
scrollToRow: 49
}))
// 100 columns * 50 item width = 5,000 total item width
// 100 rows * 20 item height = 2,000 total item height
// We first scroll past the specified cell and then back.
// The minimum amount of scrolling then should leave the specified cell in the middle (just scrolled into view).
// Since alignment is set to "center" we should scroll past this point until the cell is aligned center.
expect(grid.state.scrollLeft).toEqual(1075)
expect(grid.state.scrollTop).toEqual(920)
})
})

describe('property updates', () => {
Expand Down
2 changes: 1 addition & 1 deletion source/VirtualScroll/VirtualScroll.js
Expand Up @@ -57,7 +57,7 @@ export default class VirtualScroll extends Component {
rowCount: PropTypes.number.isRequired,

/** See Grid#scrollToAlignment */
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start']).isRequired,
scrollToAlignment: PropTypes.oneOf(['auto', 'end', 'start', 'center']).isRequired,

/** Row index to ensure visible (by forcefully scrolling if necessary) */
scrollToIndex: PropTypes.number,
Expand Down
13 changes: 13 additions & 0 deletions source/VirtualScroll/VirtualScroll.test.js
Expand Up @@ -115,6 +115,19 @@ describe('VirtualScroll', () => {
expect(rendered.textContent).toContain('Name 40')
expect(rendered.textContent).toContain('Name 49')
})

it('should scroll to the correct position for :scrollToAlignment "center"', () => {
render(getMarkup({
scrollToIndex: 99
}))
const rendered = findDOMNode(render(getMarkup({
scrollToAlignment: 'center',
scrollToIndex: 49
})))
// 100 items * 10 item height = 1,000 total item height; 11 items can be visible at a time (the first and last item are only partially visible)
expect(rendered.textContent).toContain('Name 43')
expect(rendered.textContent).toContain('Name 53')
})
})

describe('property updates', () => {
Expand Down
2 changes: 2 additions & 0 deletions source/utils/getUpdatedOffsetForIndex.js
Expand Up @@ -25,6 +25,8 @@ export default function getUpdatedOffsetForIndex ({
return maxOffset
case 'end':
return minOffset
case 'center':
return maxOffset - (containerSize + cellSize) / 2
default:
return Math.max(minOffset, Math.min(maxOffset, currentOffset))
}
Expand Down
7 changes: 7 additions & 0 deletions source/utils/getUpdatedOffsetForIndex.test.js
Expand Up @@ -60,5 +60,12 @@ describe('getUpdatedOffsetForIndex', () => {
containerSize: 50,
currentOffset: 100
})).toEqual(10)
expect(getUpdatedOffsetForIndex({
align: 'center',
cellOffset: 50,
cellSize: 10,
containerSize: 50,
currentOffset: 100
})).toEqual(20)
})
})