Created
October 1, 2019 02:47
-
-
Save ArcticLight/cff8dccede30273a3c2cf6150305b913 to your computer and use it in GitHub Desktop.
For Forceh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const rows = []; | |
const filteredRows = []; | |
for (let i = 0; i < 100; i++) { | |
rows.push({ | |
text: "I'm a row!", | |
id: (i * 1000).toString(32), | |
}); | |
} | |
const DEFAULT_BATCH_SIZE = 15; | |
let startIndex = 0; | |
let batchSize = DEFAULT_BATCH_SIZE; | |
let firstVisibleId = ''; | |
let lastVisibleId = ''; | |
let isFiltering = false; | |
function filterList() { | |
// get start/end points | |
let start = startIndex; | |
let end = Math.min(startIndex + batchSize, rows.length - 1); | |
// check the length of the batch and figure out how many we're missing | |
const length = end - start; | |
const missing = batchSize - length; | |
filteredRows.splice(0, filteredRows.length); | |
for (let i = start; i < end; i++) { | |
filteredRows.push(rows[i]); | |
} | |
} | |
function render() { | |
const el = document.getElementById('tbody'); | |
while (el.firstChild) { | |
el.removeChild(el.firstChild); | |
} | |
filteredRows.forEach((row, ix) => { | |
el.innerHTML += `<tr id="row.${row.id}" data-id="${row.id}" data-ix="${ix}"><td>${row.text} (${row.id})</td><td>row ${ix + 1 + startIndex}</td>`; | |
}); | |
// get first visible row | |
firstVisibleId = getFirstVisibleRow(); | |
lastVisibleId = getLastVisibleRow(); | |
} | |
function getFirstVisibleRow() { | |
const el = document.getElementById('tbody'); | |
const children = [...el.children]; | |
const firstVisibleIndex = children.findIndex((childNode) => isRowVisible(childNode)); | |
return (firstVisibleIndex === -1) ? null : children[firstVisibleIndex].dataset.id; | |
} | |
function getLastVisibleRow() { | |
const el = document.getElementById('tbody'); | |
const children = [...el.children]; | |
children.reverse(); | |
const lastVisibleIndex = children.findIndex((childNode) => isRowVisible(childNode)); | |
return (lastVisibleIndex === -1) ? null : children[lastVisibleIndex].dataset.id; | |
} | |
function isRowVisible(rowNode) { | |
const top = 0; | |
const bottom = window.innerHeight; | |
const boundingRect = rowNode.getBoundingClientRect(); | |
return bottom > boundingRect.top && boundingRect.top > top; | |
} | |
let previousScrollTop = 0; | |
let scrollDirection = 0; // 1 = down, -1 = up | |
window.addEventListener('scroll', (e) => { | |
const el = e.currentTarget; | |
if (!el) return; | |
const scrollAmount = document.body.scrollTop || document.documentElement.scrollTop; | |
const direction = scrollDirection = scrollAmount > previousScrollTop ? 1 : -1; | |
previousScrollTop = scrollAmount; | |
if (direction === 1) { | |
scrollingDownHandler(); | |
} else if (direction === -1) { | |
scrollingUpHandler(); | |
} | |
}); | |
function scrollingDownHandler() { | |
// see if the first thing is out of the window | |
const row = document.getElementById(`row.${firstVisibleId}`); | |
if (!row) return; | |
// still visible so stop | |
if (isRowVisible(row)) return | |
// otherwise get its height | |
const height = row.clientHeight; | |
// then update the start index by 1 | |
const idx = rows.findIndex(r => r.id === row.dataset.id); | |
if (idx === -1) return; | |
// create some padding on the list | |
containerAddPadding(height); | |
startIndex = idx + 1; | |
// re-render | |
filterAndRender(); | |
} | |
function scrollingUpHandler() { | |
if (isFiltering) return; | |
let row = document.getElementById(`row.${lastVisibleId}`); | |
if (!row) return; | |
// still visible so stop | |
if (isRowVisible(row)) return; | |
// otherwise get its height | |
const height = row.clientHeight; | |
// create some padding on the list | |
containerRemovePadding(height); | |
// Need the current top of the list to find where to back up from: | |
row = document.getElementById(`row.${firstVisibleId}`); | |
const idx = rows.findIndex(r => r.id === row.dataset.id); | |
if (idx === -1) return; // oops? | |
// then back up the start of the list: | |
startIndex = idx - 1; | |
// re-render | |
filterAndRender(); | |
} | |
function containerAddPadding(amount) { | |
console.log("adding padding") | |
const el = document.getElementById("container"); | |
if (!el) return; | |
const padding = parseInt(el.style.paddingTop || 0); | |
el.style.paddingTop = `${padding + amount}px` | |
} | |
function containerRemovePadding(amount) { | |
console.log("remove padding") | |
const el = document.getElementById("container"); | |
if (!el) return; | |
const padding = parseInt(el.style.paddingTop || 0); | |
el.style.paddingTop = `${padding - amount}px` | |
} | |
function filterAndRender() { | |
filterList(); | |
render(); | |
} | |
filterAndRender(); | |
function showMe() { | |
const el = document.getElementById('tbody'); | |
const children = [...el.children]; | |
children.forEach((row) => { | |
if (isRowVisible(row)) { | |
row.style.background = 'green'; | |
} else { | |
row.style.background = 'red'; | |
} | |
}); | |
} | |
window.setInterval(showMe, 100); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment