aboutsummaryrefslogtreecommitdiff
path: root/static/js/infinitescroll.ts
diff options
context:
space:
mode:
Diffstat (limited to 'static/js/infinitescroll.ts')
-rw-r--r--static/js/infinitescroll.ts78
1 files changed, 78 insertions, 0 deletions
diff --git a/static/js/infinitescroll.ts b/static/js/infinitescroll.ts
new file mode 100644
index 0000000..bef477b
--- /dev/null
+++ b/static/js/infinitescroll.ts
@@ -0,0 +1,78 @@
+(function () {
+ const cookiesDisabled = !navigator.cookieEnabled;
+
+ if (cookiesDisabled) {
+ document.cookie = "disabled";
+ document.cookie.indexOf("disabled");
+ return console.warn("WARNING: Native pagination fallback due to cookie restrictions");
+ }
+
+ type percent = number;
+
+ function fetch(url, method, callback, fallback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function () {
+ if (callback && http.readyState === 4) {
+ if (http.status === 200) callback(http);
+ else fallback(http);
+ }
+ };
+ http.open(method, url);
+ http.send();
+ return http;
+ }
+
+ let abort = false;
+
+ const key = "config.scroll.infinite";
+
+ if (!localStorage[key]) localStorage[key] = "";
+
+ ["scroll", "DOMContentLoaded"].forEach(function (event) {
+ self.addEventListener(event, function () {
+ if (abort) return;
+
+ const remaining = Math.abs(
+ document.documentElement.scrollHeight
+ - document.documentElement.clientHeight
+ - self.pageYOffset
+ );
+
+ const traversed = self.pageYOffset;
+ const journey = remaining + traversed;
+ const ratio: percent = traversed / journey * 100;
+ const threshold = ratio >= 50;
+ const pagination = document.querySelector('[data-type="pagination"]');
+
+ if (!pagination) return;
+
+ const main = document.querySelector("main");
+ const count = main.childNodes.length;
+ const next = pagination.querySelector('[rel="next"]');
+ const end = pagination.querySelector('[rel="last"]').title === "hidden";
+ const asynchronous = document.querySelectorAll("[data-type='pagination']").length !== 1;
+
+ if (end || asynchronous) return pagination.remove();
+
+ if (threshold && (pagination.remove() === undefined)) {
+ fetch(next.href, "GET", function (http) {
+ const page = (new DOMParser()).parseFromString(http.responseText, "text/html");
+ const items = page.querySelector("main").childNodes;
+ const paginate = page.querySelector('[data-type="pagination"]');
+
+ for (let i = 0; i < items.length; i++) main.appendChild(items[i]);
+
+ main.after(paginate);
+
+ console.log("INFO: Fetch", next.href, items);
+
+ }, function (http) {
+ console.warn("WARNING: Switching to native pagination", http);
+ main.insertAdjacentElement("afterend", pagination);
+ abort = true;
+ });
+ }
+ console.log("INFO:", "r:", remaining, "t:", traversed, "j:", journey, "%:", ratio, "c:", count);
+ });
+ });
+})();