🎨 Optimised infinite scroll (#503)
no issue - removed jQuery usage - use the `<link rel="next">` tag provided by Ghost to determine the next page to fetch
This commit is contained in:
parent
f695d69aeb
commit
3c2347c7f9
4 changed files with 74 additions and 103 deletions
|
@ -1,2 +1,2 @@
|
||||||
$(function(t){var o=1,r=window.location.pathname,a=t(document),s=t(".post-feed"),c=300,l=!1,w=!1,d=window.scrollY,v=window.innerHeight,u=a.height();function f(){d=window.scrollY,e()}function g(){v=window.innerHeight,u=a.height(),e()}function e(){l||requestAnimationFrame(n),l=!0}function n(){var e,n;if(n=/(?:page\/)(\d)(?:\/)$/i,(e=(e=r).replace(/#(.*)$/g,"").replace("////g","/")).match(n)&&(o=parseInt(e.match(n)[1]),e=e.replace(n,"")),r=e,!w)if(d+v<=u-c)l=!1;else{if(o>=maxPages)return window.removeEventListener("scroll",f,{passive:!0}),void window.removeEventListener("resize",g);w=!0;var i=r+"page/"+(o+=1)+"/";t.get(i,function(e){var n=document.createRange().createContextualFragment(e).querySelectorAll(".post");n.length&&[].forEach.call(n,function(e){s[0].appendChild(e)})}).fail(function(e){404===e.status&&(window.removeEventListener("scroll",f,{passive:!0}),window.removeEventListener("resize",g))}).always(function(){u=a.height(),l=w=!1})}}window.addEventListener("scroll",f,{passive:!0}),window.addEventListener("resize",g),n()});
|
!function(n,t){var r=t.querySelector("link[rel=next]");if(r){var i=t.querySelector(".post-feed");if(i){var o=300,s=!1,l=!1,c=n.scrollY,u=n.innerHeight,d=t.documentElement.scrollHeight;n.addEventListener("scroll",a,{passive:!0}),n.addEventListener("resize",m),f()}}function v(){if(404===this.status)return n.removeEventListener("scroll",a),void n.removeEventListener("resize",m);this.response.querySelectorAll(".post-card").forEach(function(e){i.appendChild(e)});var e=this.response.querySelector("link[rel=next]");e?r.href=e.href:(n.removeEventListener("scroll",a),n.removeEventListener("resize",m)),d=t.documentElement.scrollHeight,l=s=!1}function e(){if(!l)if(c+u<=d-o)s=!1;else{l=!0;var e=new n.XMLHttpRequest;e.responseType="document",e.addEventListener("load",v),e.open("GET",r.href),e.send(null)}}function f(){s||n.requestAnimationFrame(e),s=!0}function a(){c=n.scrollY,f()}function m(){u=n.innerHeight,d=t.documentElement.scrollHeight,f()}}(window,document);
|
||||||
//# sourceMappingURL=infinitescroll.js.map
|
//# sourceMappingURL=infinitescroll.js.map
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,19 +1,78 @@
|
||||||
/* global maxPages */
|
/**
|
||||||
|
* Infinite Scroll
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(window, document) {
|
||||||
|
// next link element
|
||||||
|
var nextElement = document.querySelector('link[rel=next]');
|
||||||
|
if (!nextElement) return;
|
||||||
|
|
||||||
|
// post feed element
|
||||||
|
var feedElement = document.querySelector('.post-feed');
|
||||||
|
if (!feedElement) return;
|
||||||
|
|
||||||
// Code snippet inspired by https://github.com/douglasrodrigues5/ghost-blog-infinite-scroll
|
|
||||||
$(function ($) {
|
|
||||||
var currentPage = 1;
|
|
||||||
var pathname = window.location.pathname;
|
|
||||||
var $document = $(document);
|
|
||||||
var $result = $('.post-feed');
|
|
||||||
var buffer = 300;
|
var buffer = 300;
|
||||||
|
|
||||||
var ticking = false;
|
var ticking = false;
|
||||||
var isLoading = false;
|
var loading = false;
|
||||||
|
|
||||||
var lastScrollY = window.scrollY;
|
var lastScrollY = window.scrollY;
|
||||||
var lastWindowHeight = window.innerHeight;
|
var lastWindowHeight = window.innerHeight;
|
||||||
var lastDocumentHeight = $document.height();
|
var lastDocumentHeight = document.documentElement.scrollHeight;
|
||||||
|
|
||||||
|
function onPageLoad() {
|
||||||
|
if (this.status === 404) {
|
||||||
|
window.removeEventListener('scroll', onScroll);
|
||||||
|
window.removeEventListener('resize', onResize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append contents
|
||||||
|
var postElements = this.response.querySelectorAll('.post-card');
|
||||||
|
postElements.forEach(function (item) {
|
||||||
|
feedElement.appendChild(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
// set next link
|
||||||
|
var resNextElement = this.response.querySelector('link[rel=next]');
|
||||||
|
if (resNextElement) {
|
||||||
|
nextElement.href = resNextElement.href;
|
||||||
|
} else {
|
||||||
|
window.removeEventListener('scroll', onScroll);
|
||||||
|
window.removeEventListener('resize', onResize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync status
|
||||||
|
lastDocumentHeight = document.documentElement.scrollHeight;
|
||||||
|
ticking = false;
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onUpdate() {
|
||||||
|
// return if already loading
|
||||||
|
if (loading) return;
|
||||||
|
|
||||||
|
// return if not scroll to the bottom
|
||||||
|
if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {
|
||||||
|
ticking = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = true;
|
||||||
|
|
||||||
|
var xhr = new window.XMLHttpRequest();
|
||||||
|
xhr.responseType = 'document';
|
||||||
|
|
||||||
|
xhr.addEventListener('load', onPageLoad);
|
||||||
|
|
||||||
|
xhr.open('GET', nextElement.href);
|
||||||
|
xhr.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestTick() {
|
||||||
|
ticking || window.requestAnimationFrame(onUpdate);
|
||||||
|
ticking = true;
|
||||||
|
}
|
||||||
|
|
||||||
function onScroll() {
|
function onScroll() {
|
||||||
lastScrollY = window.scrollY;
|
lastScrollY = window.scrollY;
|
||||||
|
@ -22,94 +81,12 @@ $(function ($) {
|
||||||
|
|
||||||
function onResize() {
|
function onResize() {
|
||||||
lastWindowHeight = window.innerHeight;
|
lastWindowHeight = window.innerHeight;
|
||||||
lastDocumentHeight = $document.height();
|
lastDocumentHeight = document.documentElement.scrollHeight;
|
||||||
requestTick();
|
requestTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestTick() {
|
|
||||||
if (!ticking) {
|
|
||||||
requestAnimationFrame(infiniteScroll);
|
|
||||||
}
|
|
||||||
ticking = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizePathname(path) {
|
|
||||||
var paginationRegex = /(?:page\/)(\d)(?:\/)$/i;
|
|
||||||
|
|
||||||
// remove hash params from path
|
|
||||||
path = path.replace(/#(.*)$/g, '').replace('////g', '/');
|
|
||||||
|
|
||||||
// remove pagination from the path and replace the current pages
|
|
||||||
// with the actual requested page. E. g. `/page/3/` indicates that
|
|
||||||
// the user actually requested page 3, so we should request page 4
|
|
||||||
// next, unless it's the last page already.
|
|
||||||
if (path.match(paginationRegex)) {
|
|
||||||
currentPage = parseInt(path.match(paginationRegex)[1]);
|
|
||||||
|
|
||||||
path = path.replace(paginationRegex, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
function infiniteScroll() {
|
|
||||||
// sanitize the pathname from possible pagination or hash params
|
|
||||||
pathname = sanitizePathname(pathname);
|
|
||||||
|
|
||||||
// return if already loading
|
|
||||||
if (isLoading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return if not scroll to the bottom
|
|
||||||
if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {
|
|
||||||
ticking = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* maxPages is defined in default.hbs and is the value
|
|
||||||
* of the amount of pagination pages.
|
|
||||||
* If we reached the last page or are past it,
|
|
||||||
* we return and disable the listeners.
|
|
||||||
*/
|
|
||||||
if (currentPage >= maxPages) {
|
|
||||||
window.removeEventListener('scroll', onScroll, {passive: true});
|
|
||||||
window.removeEventListener('resize', onResize);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoading = true;
|
|
||||||
|
|
||||||
// next page
|
|
||||||
currentPage += 1;
|
|
||||||
|
|
||||||
// Load more
|
|
||||||
var nextPage = pathname + 'page/' + currentPage + '/';
|
|
||||||
|
|
||||||
$.get(nextPage, function (content) {
|
|
||||||
var parse = document.createRange().createContextualFragment(content);
|
|
||||||
var posts = parse.querySelectorAll('.post');
|
|
||||||
if (posts.length) {
|
|
||||||
[].forEach.call(posts, function (post) {
|
|
||||||
$result[0].appendChild(post);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).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.addEventListener('scroll', onScroll, { passive: true });
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||||||
window.addEventListener('resize', onResize);
|
window.addEventListener('resize', onResize);
|
||||||
|
|
||||||
infiniteScroll();
|
requestTick();
|
||||||
});
|
})(window, document);
|
||||||
|
|
|
@ -76,12 +76,6 @@
|
||||||
<script type="text/javascript" src="{{asset "built/jquery.fitvids.js"}}"></script>
|
<script type="text/javascript" src="{{asset "built/jquery.fitvids.js"}}"></script>
|
||||||
|
|
||||||
{{#if pagination.pages}}
|
{{#if pagination.pages}}
|
||||||
<script>
|
|
||||||
// maxPages is a global variable that is needed to determine
|
|
||||||
// if we need to load more pages for the infinitescroll, or if
|
|
||||||
// we reached the last page already.
|
|
||||||
var maxPages = parseInt('{{pagination.pages}}');
|
|
||||||
</script>
|
|
||||||
<script src="{{asset "built/infinitescroll.js"}}"></script>
|
<script src="{{asset "built/infinitescroll.js"}}"></script>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue