Skip to content
quarry Artifact [7a07582fbc]
Login

Artifact [7a07582fbc]

Artifact 7a07582fbc920c25f5766e5ec2102757a5de0e0af75606acf4db3a6397cdb7be:


// repotabs.js — a repository tab the bar cannot show whole moves into
// the "…" drawer.
//
// The stylesheet folds tabs by width in tiers, but a long repository
// name or a wide count moves the point where the row runs out, and the
// row then clips its last tab: at 390px Tickets showed as a "T" beside
// the button and was in no menu. The bar is measured here instead. A
// tab whose box is not entirely inside the bar is hidden (.clip) and
// its drawer entry, matched by href, is shown (.clipped). The lit tab
// never yields, and a tab with no drawer entry stays where it is.
(function () {
  "use strict";

  var bar = document.querySelector(".repobar .bar");
  var drawer = document.getElementById("navmore");
  if (!bar || !drawer) { return; }

  function fit() {
    var nav = document.getElementById("repo-tabs");
    if (!nav) { return; }
    var tabs = Array.prototype.slice.call(nav.querySelectorAll("a"));
    tabs.forEach(function (a) { a.classList.remove("clip"); });
    Array.prototype.forEach.call(drawer.querySelectorAll("span.clipped"), function (s) {
      s.classList.remove("clipped");
    });
    // Hiding a tab changes how wide the nav is laid out, so measure
    // again until a pass hides nothing more.
    for (var moved = true, pass = 0; moved && pass < tabs.length; pass++) {
      moved = false;
      var edge = nav.getBoundingClientRect();
      tabs.forEach(function (a) {
        if (a.classList.contains("clip") || a.classList.contains("here") || a.offsetParent === null) { return; }
        var r = a.getBoundingClientRect();
        if (r.left >= edge.left - 0.5 && r.right <= edge.right + 0.5) { return; }
        var entry = drawer.querySelector("a[href='" + a.getAttribute("href") + "']");
        if (!entry || !entry.parentNode || entry.parentNode.tagName !== "SPAN") { return; }
        a.classList.add("clip");
        entry.parentNode.classList.add("clipped");
        moved = true;
      });
    }
  }

  fit();
  window.addEventListener("resize", fit);
  if (window.ResizeObserver) { new ResizeObserver(fit).observe(bar); }
  // The tabs are patched live (nav.frag), which replaces the nav.
  if (window.MutationObserver) { new MutationObserver(fit).observe(bar, { childList: true, subtree: true }); }
  if (document.fonts && document.fonts.ready) { document.fonts.ready.then(fit); }
})();