aboutsummaryrefslogtreecommitdiff
path: root/static/js/infinitescroll.ts
blob: bef477b678b872b54dc3b8465006f787f38355c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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);
    });
  });
})();