MediaWiki:Common.js:修订间差异
来自Mindustry中文wiki
无编辑摘要 |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
/* MediaWiki:Common.js */ | |||
(function () { | (function () { | ||
'use strict'; | 'use strict'; | ||
function | function legacyCopy(text) { | ||
if (!window.jQuery) return; | if (!window.jQuery) return; | ||
var $ = window.jQuery; | var $ = window.jQuery; | ||
| 第15行: | 第15行: | ||
} | } | ||
// | // 复制按钮:<button class="copy-button" data-text="...">复制 | ||
</button> | |||
if (window.jQuery) { | if (window.jQuery) { | ||
window.jQuery(function ($) { | window.jQuery(function ($) { | ||
$(document).on('click', '.copy-button', function () { | $(document).on('click', '.copy-button', function () { | ||
var text = $(this).attr('data-text') || ''; | var text = $(this).attr('data-text') || ''; | ||
if (navigator.clipboard && navigator.clipboard.writeText) { | if (navigator.clipboard && navigator.clipboard.writeText) { | ||
navigator.clipboard.writeText(text).then(function () { | navigator.clipboard.writeText(text).then( | ||
function () { alert('复制成功!'); }, | |||
function () { legacyCopy(text); } | |||
); | |||
return; | |||
} | } | ||
legacyCopy(text); | |||
}); | }); | ||
}); | }); | ||
| 第37行: | 第38行: | ||
mw.loader.using(['mediawiki.util'], function () { | mw.loader.using(['mediawiki.util'], function () { | ||
if (mw.config.get('skin') !== 'timeless') return; | 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() { | function initNavTree() { | ||
var siteNav = document.getElementById( | var siteNav = document.getElementById(idSiteNav); | ||
if (!siteNav) return; | if (!siteNav) return; | ||
var pNav = siteNav.querySelector('# | var pNav = document.getElementById(idNav); | ||
if (!pNav) pNav = siteNav.querySelector('#' + idNav); | |||
if (!pNav) return; | if (!pNav) return; | ||
var root = pNav.querySelector('.mw-portlet-body > ul') | var root = pNav.querySelector('.mw-portlet-body > ul'); | ||
if (!root) root = pNav.querySelector('ul'); | |||
if (!root) return; | if (!root) return; | ||
if (root. | if (root.dataset && root.dataset.mdtNav === '1') return; | ||
root. | if (root.dataset) root.dataset.mdtNav = '1'; | ||
var KEY = 'mdtNavTreeOpen'; | var KEY = 'mdtNavTreeOpen'; | ||
var store = {}; | var store = {}; | ||
try { | try { | ||
store = JSON.parse(localStorage.getItem(KEY) || '{}'); | store = JSON.parse(localStorage.getItem(KEY) || '{}'); | ||
| 第95行: | 第108行: | ||
btn.type = 'button'; | btn.type = 'button'; | ||
btn.className = 'mdtNavToggle'; | btn.className = 'mdtNavToggle'; | ||
btn.setAttribute( | btn.setAttribute(ariaLabel, '展开/收起'); | ||
btn.setAttribute( | btn.setAttribute(ariaExpanded, 'false'); | ||
li.insertBefore(btn, sub); | li.insertBefore(btn, sub); | ||
| 第104行: | 第117行: | ||
var isOpen = li.classList.contains('mdtNavOpen'); | var isOpen = li.classList.contains('mdtNavOpen'); | ||
setOpen(li, !isOpen, true); | setOpen(li, !isOpen, true); | ||
btn.setAttribute( | btn.setAttribute(ariaExpanded, String(!isOpen)); | ||
}); | }); | ||
} | } | ||
| 第111行: | 第124行: | ||
if (store[k] === true) { | if (store[k] === true) { | ||
li.classList.add('mdtNavOpen'); | li.classList.add('mdtNavOpen'); | ||
btn.setAttribute( | btn.setAttribute(ariaExpanded, 'true'); | ||
} | } | ||
| 第117行: | 第130行: | ||
} | } | ||
// 1) 把平铺的列表改成树 | |||
var items = Array.prototype.slice.call(root.children); | var items = Array.prototype.slice.call(root.children); | ||
var lastAtDepth = []; | var lastAtDepth = []; | ||
| 第141行: | 第155行: | ||
li.classList.add('mdtNavSubItem'); | li.classList.add('mdtNavSubItem'); | ||
li.classList.add('mdtNavDepth' + String(depth)); | li.classList.add('mdtNavDepth' + String(depth)); | ||
var | var sub = ensureGroup(lastAtDepth[depth - 1]); | ||
sub.appendChild(li); | |||
} else { | } else { | ||
depth = 0; | depth = 0; | ||
| 第151行: | 第165行: | ||
} | } | ||
// 当前页面高亮 + 自动展开父级 | // 2) 当前页面高亮 + 自动展开父级 | ||
var current = (mw.config.get('wgPageName') | var current = normTitle(mw.config.get('wgPageName')); | ||
var links = pNav.querySelectorAll('a'); | var links = pNav.querySelectorAll('a'); | ||
function titleFromHref(href) { | function titleFromHref(href) { | ||
var t = mw.util.getParamValue('title', href); | var t = mw.util.getParamValue('title', href); | ||
if (t) return t | if (t) return normTitle(t); | ||
var mark = '/index.php/'; | var mark = '/index.php/'; | ||
var pos = href.indexOf(mark); | var pos = href.indexOf(mark); | ||
if (pos !== -1) { | if (pos !== -1) { | ||
var tail = href.slice(pos + mark.length); | |||
var decoded = decodeURIComponent(tail); | |||
return normTitle(decoded); | |||
} | } | ||
| 第174行: | 第188行: | ||
var page = titleFromHref(href); | var page = titleFromHref(href); | ||
if (page | 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; | |||
} | } | ||
} | } | ||
| 第194行: | 第208行: | ||
if (document.readyState === 'loading') { | if (document.readyState === 'loading') { | ||
document.addEventListener('DOMContentLoaded', initNavTree); | document.addEventListener('DOMContentLoaded', initNavTree); | ||
return; | |||
} | } | ||
initNavTree(); | |||
}); | }); | ||
})(); | })(); | ||
2026年1月8日 (四) 16:16的版本
/* 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();
});
})();
