Jump to content

MediaWiki:Common.js: Difference between revisions

From Bconomy Wiki
Show section trees above Contents in the left column
No edit summary
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
/* Section trees ({{… sidebar}} templates, class bc-section-nav).
/* Section trees ({{… sidebar}} templates, class bc-section-nav).
  * Copies the tree on an article into a panel at the top of the left column (above
  * Copies the tree on an article into a panel in the left column, below Contents,
  * Contents), styled like the Contents panel, with the current page in bold. The
  * styled like the Contents panel: the section name is the heading, the current
  * in-page box stays as the fallback where Vector hides that column
* page is in bold, and "hide"/"show" collapses the list (remembered per browser).
  * The in-page box stays as the fallback where Vector hides that column
  * (see .bc-section-nav--moved in MediaWiki:Common.css). */
  * (see .bc-section-nav--moved in MediaWiki:Common.css). */
mw.hook("wikipage.content").add(function ($content) {
mw.hook("wikipage.content").add(function ($content) {
   var box = $content[0] && $content[0].querySelector(".bc-section-nav");
   var box = $content[0] && $content[0].querySelector(".bc-section-nav");
   var column = document.querySelector(".vector-column-start");
   var column = document.querySelector(".vector-column-start .vector-sticky-pinned-container");
   if (!box || !column || document.getElementById("bc-section-panel")) {
   if (!box || !column || document.getElementById("bc-section-panel")) {
     return;
     return;
   }
   }
  var storageKey = "bc-section-panel-hidden";
  var isHidden = function () {
    try {
      return localStorage.getItem(storageKey) === "1";
    } catch (e) {
      return false;
    }
  };
   var panel = document.createElement("nav");
   var panel = document.createElement("nav");
   panel.id = "bc-section-panel";
   panel.id = "bc-section-panel";
   panel.className = "vector-pinned-container bc-section-panel";
   panel.className = "vector-pinned-container bc-section-panel";
   panel.setAttribute("aria-label", box.getAttribute("aria-label") || "");
   panel.setAttribute("aria-label", box.getAttribute("aria-label") || "");
  // Header: section name (linked) plus a hide/show toggle, like Contents.
  var header = document.createElement("div");
  header.className =
    "vector-pinnable-header bc-section-pinnable-header vector-pinnable-header-pinned";
  var label = document.createElement("div");
  label.className = "vector-pinnable-header-label";
  var titleLink = box.querySelector(".bc-section-nav-title a");
  if (titleLink) {
    var headLink = document.createElement("a");
    headLink.href = titleLink.getAttribute("href") || location.pathname;
    headLink.textContent = titleLink.textContent;
    if (titleLink.classList.contains("mw-selflink")) {
      label.className += " bc-section-current";
    }
    label.appendChild(headLink);
  } else {
    label.textContent = panel.getAttribute("aria-label");
  }
  var toggle = document.createElement("button");
  toggle.type = "button";
  toggle.className =
    "vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button";
  header.appendChild(label);
  header.appendChild(toggle);
  panel.appendChild(header);
   var list = document.createElement("ul");
   var list = document.createElement("ul");
   var addItem = function (link, text, depth) {
   var addItem = function (link, text, depth) {
Line 31: Line 68:
     list.appendChild(li);
     list.appendChild(li);
   };
   };
  var titleLink = box.querySelector(".bc-section-nav-title a");
  if (titleLink) {
    addItem(titleLink, titleLink.textContent, 0);
  }
   box.querySelectorAll("li").forEach(function (item) {
   box.querySelectorAll("li").forEach(function (item) {
     var depth = 0;
     var depth = 0;
Line 53: Line 86:
   });
   });
   panel.appendChild(list);
   panel.appendChild(list);
   column.insertBefore(
 
     panel,
   var render = function (hidden) {
     column.querySelector(".vector-sticky-pinned-container"),
    list.hidden = hidden;
   );
     panel.classList.toggle("bc-section-panel--collapsed", hidden);
    toggle.textContent = hidden ? "show" : "hide";
     toggle.setAttribute("aria-expanded", hidden ? "false" : "true");
  };
  toggle.addEventListener("click", function () {
    var hidden = !list.hidden;
    try {
      localStorage.setItem(storageKey, hidden ? "1" : "0");
    } catch (e) {}
    render(hidden);
  });
  render(isHidden());
 
   column.appendChild(panel);
   box.classList.add("bc-section-nav--moved");
   box.classList.add("bc-section-nav--moved");
});
});

Latest revision as of 15:04, 4 November 2026

/* Section trees ({{… sidebar}} templates, class bc-section-nav).
 * Copies the tree on an article into a panel in the left column, below Contents,
 * styled like the Contents panel: the section name is the heading, the current
 * page is in bold, and "hide"/"show" collapses the list (remembered per browser).
 * The in-page box stays as the fallback where Vector hides that column
 * (see .bc-section-nav--moved in MediaWiki:Common.css). */
mw.hook("wikipage.content").add(function ($content) {
  var box = $content[0] && $content[0].querySelector(".bc-section-nav");
  var column = document.querySelector(".vector-column-start .vector-sticky-pinned-container");
  if (!box || !column || document.getElementById("bc-section-panel")) {
    return;
  }
  var storageKey = "bc-section-panel-hidden";
  var isHidden = function () {
    try {
      return localStorage.getItem(storageKey) === "1";
    } catch (e) {
      return false;
    }
  };

  var panel = document.createElement("nav");
  panel.id = "bc-section-panel";
  panel.className = "vector-pinned-container bc-section-panel";
  panel.setAttribute("aria-label", box.getAttribute("aria-label") || "");

  // Header: section name (linked) plus a hide/show toggle, like Contents.
  var header = document.createElement("div");
  header.className =
    "vector-pinnable-header bc-section-pinnable-header vector-pinnable-header-pinned";
  var label = document.createElement("div");
  label.className = "vector-pinnable-header-label";
  var titleLink = box.querySelector(".bc-section-nav-title a");
  if (titleLink) {
    var headLink = document.createElement("a");
    headLink.href = titleLink.getAttribute("href") || location.pathname;
    headLink.textContent = titleLink.textContent;
    if (titleLink.classList.contains("mw-selflink")) {
      label.className += " bc-section-current";
    }
    label.appendChild(headLink);
  } else {
    label.textContent = panel.getAttribute("aria-label");
  }
  var toggle = document.createElement("button");
  toggle.type = "button";
  toggle.className =
    "vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button";
  header.appendChild(label);
  header.appendChild(toggle);
  panel.appendChild(header);

  var list = document.createElement("ul");
  var addItem = function (link, text, depth) {
    var li = document.createElement("li");
    li.className = "bc-section-depth-" + depth;
    if (link && link.classList.contains("mw-selflink")) {
      li.className += " bc-section-current";
    }
    var inner = document.createElement(link ? "a" : "span");
    if (link) {
      inner.href = link.getAttribute("href") || location.pathname;
    } else {
      li.className += " bc-section-label";
    }
    inner.textContent = text;
    li.appendChild(inner);
    list.appendChild(li);
  };
  box.querySelectorAll("li").forEach(function (item) {
    var depth = 0;
    for (var el = item.parentElement; el && el !== box; el = el.parentElement) {
      if (el.tagName === "UL") {
        depth++;
      }
    }
    var link = item.querySelector(":scope > a");
    var text = link
      ? link.textContent
      : item.firstChild && item.firstChild.nodeType === 3
        ? item.firstChild.textContent.trim()
        : "";
    if (text) {
      addItem(link, text, depth);
    }
  });
  panel.appendChild(list);

  var render = function (hidden) {
    list.hidden = hidden;
    panel.classList.toggle("bc-section-panel--collapsed", hidden);
    toggle.textContent = hidden ? "show" : "hide";
    toggle.setAttribute("aria-expanded", hidden ? "false" : "true");
  };
  toggle.addEventListener("click", function () {
    var hidden = !list.hidden;
    try {
      localStorage.setItem(storageKey, hidden ? "1" : "0");
    } catch (e) {}
    render(hidden);
  });
  render(isHidden());

  column.appendChild(panel);
  box.classList.add("bc-section-nav--moved");
});