aboutsummaryrefslogtreecommitdiff
path: root/static/js/instantpage.ts
blob: 1b5ed366a1cb4ed7e9527fb7f4bb260ba6f11a1f (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
79
80
81
82
/*
 * Instant Page Copyright (C) 2019-2023 Alexandre Dieulot
 * https://github.com/instantpage/instant.page/blob/master/LICENSE
 * Licence: MIT | https://mit-license.org/
*/

(function () {

  /*/
   *  Element.closest() polyfill
   *  https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
   *  https://github.com/idmadj/element-closest-polyfill#readme
   *  Copyright (C) Abdelmadjid Hammou
   *  Licence: ISC | https://www.isc.org/licenses/
  /*/

  if (typeof Element !== "undefined") {
    if (!Element.prototype.matches) {
      Element.prototype.matches = Element.prototype.msMatchesSelector ||
        Element.prototype.webkitMatchesSelector;
    }
    if (!Element.prototype.closest) {
      Element.prototype.closest = function (s) {
        var el = this;
        do {
          if (el.matches(s)) return el;
          el = el.parentElement || el.parentNode;
        } while (el !== null && el.nodeType === 1);
        return null;
      };
    }
  }

  /*/
   * -----------------------------------------------------------------
  /*/

  function fetch(url, method, callback) {
    const http = new XMLHttpRequest();
    http.onreadystatechange = function () {
      if (http.readyState === 4 && http.status === 200) {
        if (callback) callback(http);
      }
    };
    http.open(method, url);
    http.send();
    return http;
  }

  self.addEventListener("DOMContentLoaded", function () {

    ["mouseout", "mousedown", "touchstart"].forEach(function (event) {
      self.addEventListener(event, function (event) {
        const url = event.target.closest("a");
        if (preloadable(url) === undefined) return;
        preload(url.href);
      });
    });

    function preloadable(url) {
      switch (true) {
        case (url === null || url.href === null): return;
        case (url.origin !== location.origin): return;
        case (["http:", "https:"].includes(url.protocol) === null): return;
        case (url.protocol === "http:" && location.protocol === "https:"): return;
        case (url.hash && url.pathname + url.search == location.pathname + location.search): return;
        default: return true;
      }
    }

    function preload(url) {
      const prefetcher = document.createElement("link");
      prefetcher.rel = "custom-prefetch";
      prefetcher.href = url;
      const selector = 'link[rel="'.concat(prefetcher.rel, '"][href="').concat(prefetcher.href, '"]');
      const prefetched = document.head.contains(document.querySelector(selector));
      if (prefetched) { return; }
      document.head.appendChild(prefetcher);
      fetch(url, "GET", function () {});
    }
  });
})();