MediaWiki:Common.js
Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.
- Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
- Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
- Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
/* Das folgende JavaScript wird für alle Benutzer geladen. */
/* ==== Sidebar: klickbare Kopfzeile + Gruppen mit Auf/Zu (Vector-2022, auch im Drawer) ==== */
(function () {
if (mw.config.get('skin') !== 'vector-2022') return;
// ---------- helpers ----------
function extractDirective(a) {
if (!a) return null;
var href = a.getAttribute('href') || '';
try { href = new URL(href, location.href).hash || ''; } catch (e) {}
var s = (href || '').trim().toLowerCase();
if (s.indexOf('#group:') >= 0) return { kind: 'group', value: decodeURIComponent(s.split('#group:').pop()) };
if (s.indexOf('#link:') >= 0) return { kind: 'link', value: decodeURIComponent(s.split('#link:').pop()) };
return null;
}
function stripDirectiveHash(a){
if (!a) return;
var href = a.getAttribute('href') || '';
a.setAttribute('href', href.replace(/#(?:link|group):[^#]*$/i,''));
}
function hasRealHref(a){
if (!a) return false;
var h = a.getAttribute('href') || '';
// reiner Hash => kein echter Link
if (/^#/.test(h)) return false;
return true;
}
function makeHead(li, keepLink) {
var a = li.querySelector(':scope > a');
var head = document.createElement('div');
head.className = 'kr-head';
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'kr-arrow';
btn.setAttribute('aria-expanded', 'false'); // default: zu
head.appendChild(btn);
if (keepLink && a) { stripDirectiveHash(a); head.appendChild(a); }
else {
var span = document.createElement('span');
span.className = 'kr-title';
span.textContent = (a && a.textContent) || '';
head.appendChild(span);
if (a) a.remove();
}
li.insertBefore(head, li.firstChild);
li.classList.add('is-collapsed'); // default: zu
return head;
}
function attachToggle(containerUL){
if (containerUL.dataset.krToggleAttached) return;
containerUL.dataset.krToggleAttached = '1';
containerUL.addEventListener('click', function (e) {
if (!e.target.classList.contains('kr-arrow')) return;
var li = e.target.closest('li.kr-group, li.kr-top');
if (!li) return;
var collapsed = li.classList.toggle('is-collapsed');
e.target.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
});
}
function buildGroups(ul) {
var lis = Array.from(ul.querySelectorAll(':scope > li.mw-list-item'));
var current = null;
lis.forEach(function (li) {
var a = li.querySelector(':scope > a');
var d = extractDirective(a);
if (d && d.kind === 'group') {
// Gruppe: mit oder ohne Link
var clickable = hasRealHref(a);
li.classList.add('kr-group');
makeHead(li, clickable);
if (clickable) stripDirectiveHash(a);
else if (a) a.remove();
var sub = document.createElement('ul');
sub.className = 'kr-sub';
li.appendChild(sub);
current = sub;
return;
}
// Normale Elemente wandern in die aktuelle Gruppe (falls vorhanden)
if (current && !(d && (d.kind === 'group' || d.kind === 'link'))) {
current.appendChild(li);
}
});
attachToggle(ul);
}
function buildPortlets(root) {
var lists = root.querySelectorAll('.vector-menu .vector-menu-content-list');
lists.forEach(function (ul) {
if (ul.dataset.krSbDone) return;
ul.dataset.krSbDone = '1';
var items = Array.from(ul.querySelectorAll(':scope > li.mw-list-item'));
var topIdx = items.findIndex(function (li) {
var a = li.querySelector(':scope > a');
var d = extractDirective(a);
return d && d.kind === 'link';
});
if (topIdx >= 0) {
var top = items[topIdx];
top.classList.add('kr-top');
makeHead(top, true); // klickbarer Titel
stripDirectiveHash(top.querySelector(':scope > a'));
var sub = document.createElement('ul');
sub.className = 'kr-sub';
top.appendChild(sub);
for (var i = topIdx + 1; i < items.length; i++) sub.appendChild(items[i]);
buildGroups(sub); // Gruppen in der Unterliste
attachToggle(ul); // Toggle auch für kr-top (Pfeil am Kopf)
} else {
buildGroups(ul);
}
// Rest säubern
ul.querySelectorAll('a[href*="#link:"], a[href*="#group:"]').forEach(stripDirectiveHash);
var portlet = ul.closest('.vector-menu');
var heading = portlet && portlet.querySelector(':scope > .vector-menu-heading');
if (heading) heading.remove();
});
}
function processRoot(root){
if (!root || root.dataset.krSbRootDone) return;
root.dataset.krSbRootDone = '1';
root.classList.add('kr-sb');
buildPortlets(root);
}
function init() {
document.querySelectorAll('#mw-panel, #vector-main-menu, #vector-main-menu-pinned, .vector-drawer')
.forEach(processRoot);
}
init();
mw.hook('wikipage.content').add(init);
var mo = new MutationObserver(function (muts) {
muts.forEach(function (m) {
m.addedNodes && m.addedNodes.forEach(function (n) {
if (!(n instanceof Element)) return;
if (n.matches('#vector-main-menu, #vector-main-menu-pinned, .vector-drawer, #mw-panel')) processRoot(n);
n.querySelectorAll && n.querySelectorAll('#vector-main-menu, #vector-main-menu-pinned, .vector-drawer, #mw-panel')
.forEach(processRoot);
});
});
});
mo.observe(document.body, { childList: true, subtree: true });
})();