From 3c2347c7f96a098cec3558638030e2f79f928d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=AA=E7=A3=8A?= Date: Wed, 5 Dec 2018 20:38:11 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Optimised=20infinite=20scroll=20?= =?UTF-8?q?(#503)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue - removed jQuery usage - use the `` tag provided by Ghost to determine the next page to fetch --- assets/built/infinitescroll.js | 2 +- assets/built/infinitescroll.js.map | 2 +- assets/js/infinitescroll.js | 167 +++++++++++++---------------- default.hbs | 6 -- 4 files changed, 74 insertions(+), 103 deletions(-) diff --git a/assets/built/infinitescroll.js b/assets/built/infinitescroll.js index ecddff9..85d1b87 100644 --- a/assets/built/infinitescroll.js +++ b/assets/built/infinitescroll.js @@ -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 diff --git a/assets/built/infinitescroll.js.map b/assets/built/infinitescroll.js.map index f053426..3f56687 100644 --- a/assets/built/infinitescroll.js.map +++ b/assets/built/infinitescroll.js.map @@ -1 +1 @@ -{"version":3,"sources":["infinitescroll.js"],"names":["$","currentPage","pathname","window","location","$document","document","$result","buffer","ticking","isLoading","lastScrollY","scrollY","lastWindowHeight","innerHeight","lastDocumentHeight","height","onScroll","requestTick","onResize","requestAnimationFrame","infiniteScroll","path","paginationRegex","replace","match","parseInt","maxPages","removeEventListener","passive","nextPage","get","content","posts","createRange","createContextualFragment","querySelectorAll","length","forEach","call","post","appendChild","fail","xhr","status","always","addEventListener"],"mappings":"AAGAA,EAAE,SAAUA,GACR,IAAIC,EAAc,EACdC,EAAWC,OAAOC,SAASF,SAC3BG,EAAYL,EAAEM,UACdC,EAAUP,EAAE,cACZQ,EAAS,IAETC,GAAU,EACVC,GAAY,EAEZC,EAAcR,OAAOS,QACrBC,EAAmBV,OAAOW,YAC1BC,EAAqBV,EAAUW,SAEnC,SAASC,IACLN,EAAcR,OAAOS,QACrBM,IAGJ,SAASC,IACLN,EAAmBV,OAAOW,YAC1BC,EAAqBV,EAAUW,SAC/BE,IAGJ,SAASA,IACAT,GACDW,sBAAsBC,GAE1BZ,GAAU,EAsBd,SAASY,IAnBT,IAA0BC,EAClBC,EAuBJ,GAvBIA,EAAkB,0BAGtBD,GAJsBA,EAqBMpB,GAjBhBsB,QAAQ,UAAW,IAAIA,QAAQ,QAAS,MAM3CC,MAAMF,KACXtB,EAAcyB,SAASJ,EAAKG,MAAMF,GAAiB,IAEnDD,EAAOA,EAAKE,QAAQD,EAAiB,KAQzCrB,EALOoB,GAQHZ,EAKJ,GAAIC,EAAcE,GAAoBE,EAAqBP,EACvDC,GAAU,MADd,CAWA,GAAIR,GAAe0B,SAGf,OAFAxB,OAAOyB,oBAAoB,SAAUX,EAAU,CAACY,SAAS,SACzD1B,OAAOyB,oBAAoB,SAAUT,GAIzCT,GAAY,EAMZ,IAAIoB,EAAW5B,EAAW,SAH1BD,GAAe,GAGmC,IAElDD,EAAE+B,IAAID,EAAU,SAAUE,GACtB,IACIC,EADQ3B,SAAS4B,cAAcC,yBAAyBH,GAC1CI,iBAAiB,SAC/BH,EAAMI,QACN,GAAGC,QAAQC,KAAKN,EAAO,SAAUO,GAC7BjC,EAAQ,GAAGkC,YAAYD,OAGhCE,KAAK,SAAUC,GAEK,MAAfA,EAAIC,SACJzC,OAAOyB,oBAAoB,SAAUX,EAAU,CAACY,SAAS,IACzD1B,OAAOyB,oBAAoB,SAAUT,MAE1C0B,OAAO,WACN9B,EAAqBV,EAAUW,SAE/BP,EADAC,GAAY,KAKpBP,OAAO2C,iBAAiB,SAAU7B,EAAU,CAACY,SAAS,IACtD1B,OAAO2C,iBAAiB,SAAU3B,GAElCE","file":"infinitescroll.js","sourcesContent":["/* global maxPages */\n\n// Code snippet inspired by https://github.com/douglasrodrigues5/ghost-blog-infinite-scroll\n$(function ($) {\n var currentPage = 1;\n var pathname = window.location.pathname;\n var $document = $(document);\n var $result = $('.post-feed');\n var buffer = 300;\n\n var ticking = false;\n var isLoading = false;\n\n var lastScrollY = window.scrollY;\n var lastWindowHeight = window.innerHeight;\n var lastDocumentHeight = $document.height();\n\n function onScroll() {\n lastScrollY = window.scrollY;\n requestTick();\n }\n\n function onResize() {\n lastWindowHeight = window.innerHeight;\n lastDocumentHeight = $document.height();\n requestTick();\n }\n\n function requestTick() {\n if (!ticking) {\n requestAnimationFrame(infiniteScroll);\n }\n ticking = true;\n }\n\n function sanitizePathname(path) {\n var paginationRegex = /(?:page\\/)(\\d)(?:\\/)$/i;\n\n // remove hash params from path\n path = path.replace(/#(.*)$/g, '').replace('////g', '/');\n\n // remove pagination from the path and replace the current pages\n // with the actual requested page. E. g. `/page/3/` indicates that\n // the user actually requested page 3, so we should request page 4\n // next, unless it's the last page already.\n if (path.match(paginationRegex)) {\n currentPage = parseInt(path.match(paginationRegex)[1]);\n\n path = path.replace(paginationRegex, '');\n }\n\n return path;\n }\n\n function infiniteScroll() {\n // sanitize the pathname from possible pagination or hash params\n pathname = sanitizePathname(pathname);\n\n // return if already loading\n if (isLoading) {\n return;\n }\n\n // return if not scroll to the bottom\n if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {\n ticking = false;\n return;\n }\n\n /**\n * maxPages is defined in default.hbs and is the value\n * of the amount of pagination pages.\n * If we reached the last page or are past it,\n * we return and disable the listeners.\n */\n if (currentPage >= maxPages) {\n window.removeEventListener('scroll', onScroll, {passive: true});\n window.removeEventListener('resize', onResize);\n return;\n }\n\n isLoading = true;\n\n // next page\n currentPage += 1;\n\n // Load more\n var nextPage = pathname + 'page/' + currentPage + '/';\n\n $.get(nextPage, function (content) {\n var parse = document.createRange().createContextualFragment(content);\n var posts = parse.querySelectorAll('.post');\n if (posts.length) {\n [].forEach.call(posts, function (post) {\n $result[0].appendChild(post);\n });\n }\n }).fail(function (xhr) {\n // 404 indicates we've run out of pages\n if (xhr.status === 404) {\n window.removeEventListener('scroll', onScroll, {passive: true});\n window.removeEventListener('resize', onResize);\n }\n }).always(function () {\n lastDocumentHeight = $document.height();\n isLoading = false;\n ticking = false;\n });\n }\n\n window.addEventListener('scroll', onScroll, {passive: true});\n window.addEventListener('resize', onResize);\n\n infiniteScroll();\n});\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["infinitescroll.js"],"names":["window","document","nextElement","querySelector","feedElement","buffer","ticking","loading","lastScrollY","scrollY","lastWindowHeight","innerHeight","lastDocumentHeight","documentElement","scrollHeight","addEventListener","onScroll","passive","onResize","requestTick","onPageLoad","this","status","removeEventListener","response","querySelectorAll","forEach","item","appendChild","resNextElement","href","onUpdate","xhr","XMLHttpRequest","responseType","open","send","requestAnimationFrame"],"mappings":"CAIA,SAAUA,EAAQC,GAEd,IAAIC,EAAcD,EAASE,cAAc,kBACzC,GAAKD,EAAL,CAGA,IAAIE,EAAcH,EAASE,cAAc,cACzC,GAAKC,EAAL,CAEA,IAAIC,EAAS,IAETC,GAAU,EACVC,GAAU,EAEVC,EAAcR,EAAOS,QACrBC,EAAmBV,EAAOW,YAC1BC,EAAqBX,EAASY,gBAAgBC,aAmElDd,EAAOe,iBAAiB,SAAUC,EAAU,CAAEC,SAAS,IACvDjB,EAAOe,iBAAiB,SAAUG,GAElCC,KApEA,SAASC,IACL,GAAoB,MAAhBC,KAAKC,OAGL,OAFAtB,EAAOuB,oBAAoB,SAAUP,QACrChB,EAAOuB,oBAAoB,SAAUL,GAKtBG,KAAKG,SAASC,iBAAiB,cACrCC,QAAQ,SAAUC,GAC3BvB,EAAYwB,YAAYD,KAI5B,IAAIE,EAAiBR,KAAKG,SAASrB,cAAc,kBAC7C0B,EACA3B,EAAY4B,KAAOD,EAAeC,MAElC9B,EAAOuB,oBAAoB,SAAUP,GACrChB,EAAOuB,oBAAoB,SAAUL,IAIzCN,EAAqBX,EAASY,gBAAgBC,aAE9CP,EADAD,GAAU,EAId,SAASyB,IAEL,IAAIxB,EAGJ,GAAIC,EAAcE,GAAoBE,EAAqBP,EACvDC,GAAU,MADd,CAKAC,GAAU,EAEV,IAAIyB,EAAM,IAAIhC,EAAOiC,eACrBD,EAAIE,aAAe,WAEnBF,EAAIjB,iBAAiB,OAAQK,GAE7BY,EAAIG,KAAK,MAAOjC,EAAY4B,MAC5BE,EAAII,KAAK,OAGb,SAASjB,IACLb,GAAWN,EAAOqC,sBAAsBN,GACxCzB,GAAU,EAGd,SAASU,IACLR,EAAcR,EAAOS,QACrBU,IAGJ,SAASD,IACLR,EAAmBV,EAAOW,YAC1BC,EAAqBX,EAASY,gBAAgBC,aAC9CK,KAhFR,CAuFGnB,OAAQC","file":"infinitescroll.js","sourcesContent":["/**\n * Infinite Scroll\n */\n\n(function(window, document) {\n // next link element\n var nextElement = document.querySelector('link[rel=next]');\n if (!nextElement) return;\n\n // post feed element\n var feedElement = document.querySelector('.post-feed');\n if (!feedElement) return;\n\n var buffer = 300;\n\n var ticking = false;\n var loading = false;\n\n var lastScrollY = window.scrollY;\n var lastWindowHeight = window.innerHeight;\n var lastDocumentHeight = document.documentElement.scrollHeight;\n\n function onPageLoad() {\n if (this.status === 404) {\n window.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', onResize);\n return;\n }\n\n // append contents\n var postElements = this.response.querySelectorAll('.post-card');\n postElements.forEach(function (item) {\n feedElement.appendChild(item);\n });\n\n // set next link\n var resNextElement = this.response.querySelector('link[rel=next]');\n if (resNextElement) {\n nextElement.href = resNextElement.href;\n } else {\n window.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', onResize);\n }\n\n // sync status\n lastDocumentHeight = document.documentElement.scrollHeight;\n ticking = false;\n loading = false;\n }\n\n function onUpdate() {\n // return if already loading\n if (loading) return;\n\n // return if not scroll to the bottom\n if (lastScrollY + lastWindowHeight <= lastDocumentHeight - buffer) {\n ticking = false;\n return;\n }\n\n loading = true;\n\n var xhr = new window.XMLHttpRequest();\n xhr.responseType = 'document';\n\n xhr.addEventListener('load', onPageLoad);\n\n xhr.open('GET', nextElement.href);\n xhr.send(null);\n }\n\n function requestTick() {\n ticking || window.requestAnimationFrame(onUpdate);\n ticking = true;\n }\n\n function onScroll() {\n lastScrollY = window.scrollY;\n requestTick();\n }\n\n function onResize() {\n lastWindowHeight = window.innerHeight;\n lastDocumentHeight = document.documentElement.scrollHeight;\n requestTick();\n }\n\n window.addEventListener('scroll', onScroll, { passive: true });\n window.addEventListener('resize', onResize);\n\n requestTick();\n})(window, document);\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/assets/js/infinitescroll.js b/assets/js/infinitescroll.js index fa72c85..fc1e80b 100644 --- a/assets/js/infinitescroll.js +++ b/assets/js/infinitescroll.js @@ -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 ticking = false; - var isLoading = false; + var loading = false; var lastScrollY = window.scrollY; 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() { lastScrollY = window.scrollY; @@ -22,94 +81,12 @@ $(function ($) { function onResize() { lastWindowHeight = window.innerHeight; - lastDocumentHeight = $document.height(); + lastDocumentHeight = document.documentElement.scrollHeight; 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); - infiniteScroll(); -}); + requestTick(); +})(window, document); diff --git a/default.hbs b/default.hbs index 0d768ee..e90657a 100644 --- a/default.hbs +++ b/default.hbs @@ -76,12 +76,6 @@ {{#if pagination.pages}} - {{/if}}