MediaWiki:Common.js

From SZ
Revision as of 16:01, 25 August 2025 by Test2 (talk | contribs)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
mw.loader.using(['mediawiki.util']).then(function () {
  $(function () {
    var STORAGE_KEY = 'sidebar-collapse-state:v2';
    var defaultExpanded = ['navigation', 'book1'];
    var defaultCollapsed = [];

    function readState() {
      try { return JSON.parse(localStorage.getItem(STORAGE_KEY)) || {}; }
      catch(e) { return {}; }
    }
    function writeState(s) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch(e) {} }

    function portalIdFor(node) {
      if (node.id?.startsWith('p-')) return node.id.slice(2).toLowerCase();
      var dn = node.getAttribute('data-name');
      if (dn) return dn.toLowerCase();
      var h = node.querySelector('h3, .vector-menu-heading');
      return h ? h.textContent.trim().toLowerCase().replace(/\s+/g,'-') : 'portal-'+Math.random();
    }

    function setExpanded(node, exp) {
      node.classList.toggle('vector-collapsible--expanded', exp);
      node.classList.toggle('vector-collapsible--collapsed', !exp);
      var heading = node.querySelector('h3, .vector-menu-heading');
      if (heading) heading.setAttribute('aria-expanded', exp);
    }

    function toggleNode(node, persist) {
      var ns = !node.classList.contains('vector-collapsible--expanded');
      setExpanded(node, ns);
      if (persist) {
        var s = readState(); s[portalIdFor(node)] = ns ? 1 : 0; writeState(s);
      }
    }

    function attachToggle(node) {
      var heading = node.querySelector('h3, .vector-menu-heading');
      if (!heading) return;
      // inject span.icon if missing
      if (!heading.querySelector('.vector-collapse-icon')) {
        var span = document.createElement('span');
        span.className = 'vector-collapse-icon';
        span.innerHTML = '▼'; // ▼ symbol
        heading.style.position = 'relative';
        heading.style.paddingLeft = '1.5em';
        heading.insertBefore(span, heading.firstChild);
      }
      heading.addEventListener('click', function(e){ e.preventDefault(); toggleNode(node,true); });
      heading.addEventListener('keydown', function(e){ if (e.key==='Enter'||e.key===' '){ e.preventDefault(); toggleNode(node,true);} });
    }

    var portals = document.body.classList.contains('skin-vector-2022')
      ? Array.from(document.querySelectorAll('nav.vector-menu-portal')).filter(e=>!e.closest('#vector-main-menu'))
      : Array.from(document.querySelectorAll('#mw-panel .portal'));

    var saved = readState();
    portals.forEach(function(p){
      var id = portalIdFor(p);
      var initial = saved.hasOwnProperty(id) ? !!saved[id] :
                    defaultExpanded.includes(id) ? true :
                    defaultCollapsed.includes(id) ? false : true;
      setExpanded(p, initial);
      attachToggle(p);
    });
  });
});