React-virtualized scrollsync issue
Demo for Issue http://stackoverflow.com/questions/41956669/unable-to-scroll-past-the-last-child-with-scrollsync-with-multiple-grids-and-col
by mauron85
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>
<script src="https://npmcdn.com/react@latest/dist/react-with-addons.js"></script>
<script src="https://npmcdn.com/react-dom@latest/dist/react-dom.js"></script>
<link rel="stylesheet" href="https://unpkg.com/react-virtualized/styles.css">
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<script src="https://unpkg.com/react/dist/react-with-addons.min.js"></script>
<script src="https://unpkg.com/react-dom/dist/react-dom.min.js"></script>
<script src="https://rawgit.com/mauron85/6e13b39ad5a822590b43da3a57e6da26/raw/81f9b7d7a0952474c3be27ad6b01a7cd4559feaf/react-virtualized.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.min.js"></script>
<div id="example">
<!-- This element's contents will be replaced with your code... -->
</div>
CSS
html, body {
font-family: Verdana, Geneva, sans-serif;
font-weight: normal;
padding: 0;
margin: 0;
}
.icon {
height: 1.5em;
align-self: center;
margin-right: .5em;
}
.GridRow {
position: relative;
display: flex;
flex-direction: row;
}
.GridColumn {
display: flex;
flex-direction: column;
flex: 1 1 auto;
}
.LeftSideGridContainer {
flex: 0 0 75px;
z-index: 10;
}
.LeftSideGrid {
overflow: hidden !important;
background: #fff;
}
.HeaderGrid {
width: 100%;
overflow: hidden !important;
background-color: #fff;
font-size: .8em;
}
.Body {
position: relative;
}
.BodyPart {
position: absolute;
top: 0;
left: 0;
}
.BodyGrid {
width: 100%;
}
.evenRow {
background-color: #fff;
}
.oddRow {
background-color: #e5e2de;
}
.cell,
.headerCell,
.leftCell {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 0 .5em;
}
.headerCell,
.leftCell {
font-weight: bold;
}
.Calendar {
color: silver;
}
.Routes {
width: 100%;
}
.route {
height: 100%;
border: 1px solid #fff;
cursor: move;
background-color: green;
}
.routeHightlight {
background-color: yellow;
}
.delivery {
background-color: silver;
cursor: move;
}
.workingHourCell {
background-color: green;
}
JavaScript 1.7
const { calculateSizeAndPositionData, defaultCellRangeRenderer, List, Grid, Collection, ScrollSync, AutoSizer } = ReactVirtualized;
const cn = classNames;
const HOUR_IN_MILLIS = 60 * 60 * 1000;
function defaultCellGroupRenderer ({
cellCache,
cellRenderer,
cellSizeAndPositionGetter,
indices,
isScrolling
}) {
return indices
.map((index) => {
const cellMetadata = cellSizeAndPositionGetter({ index })
let cellRendererProps = {
index,
isScrolling,
key: index,
style: {
height: cellMetadata.height,
left: cellMetadata.x,
position: 'absolute',
top: cellMetadata.y,
width: cellMetadata.width
}
}
// Avoid re-creating cells while scrolling.
// This can lead to the same cell being created many times and can cause performance issues for "heavy" cells.
// If a scroll is in progress- cache and reuse cells.
// This cache will be thrown away once scrolling complets.
if (isScrolling) {
if (!(index in cellCache)) {
cellCache[index] = cellRenderer(cellRendererProps)
}
return cellCache[index]
} else {
return cellRenderer(cellRendererProps)
}
})
.filter((renderedCell) => !!renderedCell)
}
function getHoursBetween(startDate, endDate) {
return Math.ceil(moment(endDate).diff(moment(startDate), 'hours', true));
}
function getCouriers(count) {
const couriers = {};
for (let i = 1; i <= count; i++) {
couriers[i] = { id: i, username: `courier${i}` };
}
return couriers;
}
function getRoutes(couriers, startDate, endDate, routeMinDurationInHours = 1) {
const routes = [];
const hours = moment(endDate).diff(moment(startDate), 'hours');
const hoursPerCourier = hours / couriers.length;
const routesPerCourier = Math.floor(hoursPerCourier / routeMinDurationInHours) || 1;
const routeDuration = 2 * hoursPerCourier / routesPerCourier;
console.log(`Total ${hours}...