OXYGENHUB
# a7c05940ebc4 oxygenhub / assets / hub.js
3.6 KiB · JavaScript · last changed Milestone 0.1: browse 1 month ago source blame history raw
1
/* Progressive enhancement only: every page works without this file. */
2
(function () {
3
  "use strict";
4
  /* The band's active tab: the longest link that prefixes the path. */
5
  var p = location.pathname, best = null;
6
  document.querySelectorAll(".band a").forEach(function (a) {
7
    var h = a.getAttribute("href");
8
    if (h !== "/" && (p === h || p.indexOf(h + "/") === 0) && (!best || h.length > best.getAttribute("href").length)) best = a;
9
  });
10
  if (best) best.classList.add("on");
11
12
  /* Copy buttons. */
13
  document.querySelectorAll("[data-copy]").forEach(function (b) {
14
    b.addEventListener("click", function () {
15
      navigator.clipboard.writeText(b.getAttribute("data-copy")).then(function () {
16
        var t = b.textContent; b.textContent = "copied"; setTimeout(function () { b.textContent = t; }, 1200);
17
      });
18
    });
19
  });
20
21
  /* Tree rows: the last change per entry, fetched after the page paints. */
22
  var tree = document.querySelector("table.tree[data-last]");
23
  if (tree) {
24
    var paths = [].map.call(tree.querySelectorAll("tr[data-path]"), function (r) { return r.getAttribute("data-path"); });
25
    if (paths.length) {
26
      fetch(tree.getAttribute("data-last") + "?paths=" + encodeURIComponent(paths.join(",")), { credentials: "same-origin" })
27
        .then(function (r) { return r.json(); })
28
        .then(function (rows) {
29
          rows.forEach(function (c) {
30
            var tr = tree.querySelector('tr[data-path="' + CSS.escape(c.path) + '"]');
31
            if (!tr) return;
32
            var a = tr.querySelector("td.last a"), t = tr.querySelector("td.age");
33
            if (a) { a.textContent = c.title; a.href = tree.getAttribute("data-change") + c.hash; }
34
            if (t) { t.textContent = c.ago; t.title = c.when; }
35
          });
36
        }).catch(function () {});
37
    }
38
  }
39
40
  /* Line anchors: #L12 or #L12-L20 highlight a range and clicking a number selects. */
41
  function mark() {
42
    var m = location.hash.match(/^#L(\d+)(?:-L(\d+))?$/);
43
    document.querySelectorAll("tr.hl").forEach(function (r) { r.classList.remove("hl"); });
44
    if (!m) return;
45
    var a = +m[1], b = +(m[2] || m[1]);
46
    for (var i = Math.min(a, b); i <= Math.max(a, b); i++) {
47
      var row = document.getElementById("L" + i);
48
      if (row) row.classList.add("hl");
49
    }
50
    var first = document.getElementById("L" + Math.min(a, b));
51
    if (first && !mark.done) { first.scrollIntoView({ block: "center" }); mark.done = true; }
52
  }
53
  window.addEventListener("hashchange", mark);
54
  mark();
55
  document.querySelectorAll("table.code td.n").forEach(function (td) {
56
    td.addEventListener("click", function (e) {
57
      var n = td.parentNode.id;
58
      if (e.shiftKey && location.hash.match(/^#L(\d+)/)) location.hash = location.hash.replace(/^#(L\d+).*/, "$1-" + n);
59
      else location.hash = n;
60
    });
61
  });
62
63
  /* Keyboard: / focuses search; g c / g p / g i jump; ? shows the sheet. */
64
  var pending = null;
65
  document.addEventListener("keydown", function (e) {
66
    if (e.target && /^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName)) return;
67
    if (e.key === "/") { var s = document.querySelector("input[name=q]"); if (s) { e.preventDefault(); s.focus(); } return; }
68
    if (e.key === "?") { var k = document.getElementById("keys"); if (k) k.hidden = !k.hidden; return; }
69
    var repo = document.body.getAttribute("data-repo");
70
    if (pending === "g" && repo) {
71
      var to = { c: "", p: "/proposals", i: "/issues", h: "/changes/" + (document.body.getAttribute("data-ref") || "main"), b: "/bookmarks", t: "/trust" }[e.key];
72
      if (to !== undefined) location.href = repo + to;
73
      pending = null; return;
74
    }
75
    pending = e.key === "g" ? "g" : null;
76
  });
77
})();