💄 refactor infinite scroll (#325)

closes #321, closes #323
- use `requestAnimationFrame` and related techniques to minimise scroll processing
- add an `isLoading` guard to ensure we don't try to process anything until the next page has been loaded+inserted
- check for a 404 as an indication we've loaded as many pages as possible at which point the scroll behaviour is removed
- sanitize `window.location.pathname` to remove hash params and any double-slashes that may result
- add a 100px buffer from the bottom of the screen so that it's not necessary to exactly hit the bottom before infinite loading is triggered
This commit is contained in:
Kevin Ansfield 2017-07-10 13:53:42 +01:00 committed by Aileen Nowak
parent d3a9af0666
commit 0f9410fb3d
1 changed files with 61 additions and 12 deletions

View File

@ -1,29 +1,78 @@
// Code snippet inspired by https://github.com/douglasrodrigues5/ghost-blog-infinite-scroll
$(function ($) {
var currentPage = 1,
pathname = window.location.pathname,
$window = $(window),
$document = $(document),
$result = $('.post-feed');
var currentPage = 1;
var pathname = window.location.pathname;
var $document = $(document);
var $result = $('.post-feed');
var buffer = 100;
function handleScroll () {
// return if not scroll to the bottom
if ($window.scrollTop() + $window.height() !== $document.height()) {
var ticking = false;
var isLoading = false;
var lastScrollY = window.scrollY;
var lastWindowHeight = window.innerHeight;
var lastDocumentHeight = $document.height();
// remove hash params from pathname
pathname = pathname.replace(/#(.*)$/g, '').replace('/\//g', '/');
function onScroll() {
lastScrollY = window.scrollY;
requestTick();
}
function onResize() {
lastWindowHeight = window.innerHeight;
lastDocumentHeight = $document.height();
requestTick();
}
function requestTick() {
if (!ticking) {
requestAnimationFrame(infiniteScroll)
}
ticking = true;
}
function infiniteScroll () {
// return if already loading
if (isLoading) {
return;
}
if (currentPage >= maxPages) {
return $window.off('scroll', handleScroll);
// return if not scroll to the bottom
if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {
ticking = false;
return;
}
isLoading = true;
// next page
currentPage++;
// Load more
$.get((pathname + 'page/' + currentPage + '/'), function (content) {
var nextPage = pathname + 'page/' + currentPage + '/';
$.get(nextPage, function (content) {
$result.append($(content).find('.post').hide().fadeIn(100));
}).fail(function (xhr) {
// 404 indicates we've run out of pages
if (xhr.status === 404) {
window.removeEventListener('scroll', onScroll, {passive: true});
window.removeEventListener('resize', onResize);
}
}).always(function () {
lastDocumentHeight = $document.height();
isLoading = false;
ticking = false;
});
}
$window.on('scroll', handleScroll).trigger('scroll');
window.addEventListener('scroll', onScroll, {passive: true});
window.addEventListener('resize', onResize);
infiniteScroll();
});