MediaWiki:Common.js

来自Mindustry中文wiki
绿豆留言 | 贡献2026年1月8日 (四) 16:16的版本

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:Ctrl-F5

/* MediaWiki:Common.js */
  (function () {
    'use strict';

    function legacyCopy(text) {
      if (!window.jQuery) return;
      var $ = window.jQuery;
      var $temp = $('<textarea>');
      $('body').append($temp);
      $temp.val(text).select();
      document.execCommand('copy');
      $temp.remove();
      alert('复制成功!');
    }

    // 复制按钮:<button class="copy-button" data-text="...">复制
  </button>
    if (window.jQuery) {
      window.jQuery(function ($) {
        $(document).on('click', '.copy-button', function () {
          var text = $(this).attr('data-text') || '';

          if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(text).then(
              function () { alert('复制成功!'); },
              function () { legacyCopy(text); }
            );
            return;
          }

          legacyCopy(text);
        });
      });
    }

    // Timeless:把 Sidebar 里以 "-- " 开头的条目变成可折叠子项
    mw.loader.using(['mediawiki.util'], function () {
      if (mw.config.get('skin') !== 'timeless') return;

      var dash = String.fromCharCode(45);
      var idSiteNav = 'mw' + dash + 'site' + dash + 'navigation';
      var idNav = 'p' + dash + 'navigation';
      var ariaLabel = 'aria' + dash + 'label';
      var ariaExpanded = 'aria' + dash + 'expanded';

      function normTitle(t) {
        return (t || '').split(' ').join('_');
      }

      function initNavTree() {
        var siteNav = document.getElementById(idSiteNav);
        if (!siteNav) return;

        var pNav = document.getElementById(idNav);
        if (!pNav) pNav = siteNav.querySelector('#' + idNav);
        if (!pNav) return;

        var root = pNav.querySelector('.mw-portlet-body > ul');
        if (!root) root = pNav.querySelector('ul');
        if (!root) return;

        if (root.dataset && root.dataset.mdtNav === '1') return;
        if (root.dataset) root.dataset.mdtNav = '1';

        var KEY = 'mdtNavTreeOpen';
        var store = {};

        try {
          store = JSON.parse(localStorage.getItem(KEY) || '{}');
        } catch (e) {
          store = {};
        }

        function getKey(li) {
          if (li && li.id) return li.id;
          var a = li ? li.querySelector('a') : null;
          return a ? (a.getAttribute('href') || '') : '';
        }

        function setStored(li, open) {
          var k = getKey(li);
          if (!k) return;
          store[k] = open;
          try {
            localStorage.setItem(KEY, JSON.stringify(store));
          } catch (e) {}
        }

        function setOpen(li, open, persist) {
          li.classList.toggle('mdtNavOpen', open);
          if (persist) setStored(li, open);
        }

        function ensureGroup(li) {
          li.classList.add('mdtNavGroup');

          var sub = li.querySelector('ul.mdtNavSublist');
          if (!sub) {
            sub = document.createElement('ul');
            sub.className = 'mdtNavSublist';
            li.appendChild(sub);
          }

          var btn = li.querySelector('button.mdtNavToggle');
          if (!btn) {
            btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'mdtNavToggle';
            btn.setAttribute(ariaLabel, '展开/收起');
            btn.setAttribute(ariaExpanded, 'false');
            li.insertBefore(btn, sub);

            btn.addEventListener('click', function (ev) {
              ev.preventDefault();
              ev.stopPropagation();
              var isOpen = li.classList.contains('mdtNavOpen');
              setOpen(li, !isOpen, true);
              btn.setAttribute(ariaExpanded, String(!isOpen));
            });
          }

          var k = getKey(li);
          if (store[k] === true) {
            li.classList.add('mdtNavOpen');
            btn.setAttribute(ariaExpanded, 'true');
          }

          return sub;
        }

        // 1) 把平铺的列表改成树
        var items = Array.prototype.slice.call(root.children);
        var lastAtDepth = [];

        for (var i = 0; i < items.length; i++) {
          var li = items[i];
          if (!li || li.tagName !== 'LI') continue;

          var a = li.querySelector('a');
          if (!a) continue;

          var raw = (a.textContent || '').trim();
          var m = raw.match(/^(-{2,})\s*(.*)$/);

          var depth = 0;
          if (m) {
            depth = Math.min(Math.floor(m[1].length / 2), 3);
            a.textContent = m[2];
          }

          li.classList.add('mdtNavItem');

          if (depth > 0 && lastAtDepth[depth - 1]) {
            li.classList.add('mdtNavSubItem');
            li.classList.add('mdtNavDepth' + String(depth));
            var sub = ensureGroup(lastAtDepth[depth - 1]);
            sub.appendChild(li);
          } else {
            depth = 0;
          }

          lastAtDepth[depth] = li;
          lastAtDepth.length = depth + 1;
        }

        // 2) 当前页面高亮 + 自动展开父级
        var current = normTitle(mw.config.get('wgPageName'));
        var links = pNav.querySelectorAll('a');

        function titleFromHref(href) {
          var t = mw.util.getParamValue('title', href);
          if (t) return normTitle(t);

          var mark = '/index.php/';
          var pos = href.indexOf(mark);
          if (pos !== -1) {
            var tail = href.slice(pos + mark.length);
            var decoded = decodeURIComponent(tail);
            return normTitle(decoded);
          }

          return '';
        }

        for (var j = 0; j < links.length; j++) {
          var href = links[j].getAttribute('href') || '';
          var page = titleFromHref(href);

          if (!page || page !== current) continue;

          links[j].classList.add('mdtNavActive');

          var n = links[j].parentNode;
          while (n && n !== root) {
            if (n.tagName === 'LI' &&
              n.classList.contains('mdtNavGroup')) {
              setOpen(n, true, false);
              var b = n.querySelector('button.mdtNavToggle');
              if (b) b.setAttribute(ariaExpanded, 'true');
            }
            n = n.parentNode;
          }
          break;
        }
      }

      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initNavTree);
        return;
      }

      initNavTree();
    });
  })();