林泊百科开放中!
提交修改前请务必备份您的编辑内容。如有站点问题反馈,请发送邮件至account@pigeon-games.com
微件:右下角目录
来自Limbo Wiki
<script> /* loaded only by Widget:右下角目录 in Version1.1. */ (function () {
'use strict';
if (window.pdLongTocV11) {
window.pdLongTocV11.init(document);
return;
}
var nextId = 0;
function directChild(element, tag) {
return Array.prototype.find.call(element.children, function (child) {
return child.tagName === tag;
});
}
function enhance(root) {
if (root.dataset.pdLongTocReady) return;
var mode = /^[012]$/.test(root.dataset.mode || ) ? Number(root.dataset.mode) : 0;
var fold = /^[1-6]$/.test(root.dataset.fold || ) ? Number(root.dataset.fold) : 1;
var listHost = root.querySelector('.pd-long-toc-list');
var original = listHost && listHost.querySelector('.toc > ul');
if (!original) return;
root.dataset.mode = String(mode);
root.dataset.fold = String(fold);
if (mode === 0) {
root.dataset.pdLongTocReady = '1.1';
return;
}
/* Build off-DOM. A failure leaves the complete, working original TOC. */
var list = original.cloneNode(true);
var branches = [];
Array.prototype.forEach.call(list.querySelectorAll('li'), function (item) {
var match = item.className.match(/(?:^|\s)toclevel-(\d+)(?:\s|$)/);
var level = match ? Number(match[1]) : 0;
var children = directChild(item, 'UL');
var link = directChild(item, 'A');
if (!children || !link || (mode === 1 ? level !== fold : level < fold)) return;
var label = link.textContent.trim();
var row = document.createElement('div');
row.className = 'pd-long-toc-row';
var button = document.createElement('button');
button.type = 'button';
button.className = 'pd-long-toc-toggle';
button.setAttribute('aria-expanded', 'false');
children.id = 'pd-long-toc-children-' + (++nextId);
button.setAttribute('aria-controls', children.id);
while (link.firstChild) button.appendChild(link.firstChild);
link.className += ' pd-long-toc-jump';
link.textContent = '跳转';
link.setAttribute('aria-label', '跳转到 ' + label);
link.title = '跳转到 ' + label;
item.insertBefore(row, children);
row.appendChild(button);
row.appendChild(link);
children.hidden = true;
children.inert = true;
children.setAttribute('aria-hidden', 'true');
branches.push({ item: item, button: button, children: children, group: item.parentElement, animation: null });
});
function settle(branch, open) {
if (branch.animation) {
branch.animation.cancel();
branch.animation = null;
}
branch.children.style.overflow = ;
branch.children.hidden = !open;
branch.children.inert = !open;
branch.children.setAttribute('aria-hidden', String(!open));
branch.button.setAttribute('aria-expanded', String(open));
}
function transition(branch, open, startHeight) {
var children = branch.children;
var from = startHeight === undefined ? (children.hidden ? 0 : children.getBoundingClientRect().height) : startHeight;
settle(branch, open);
var reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduced || !children.animate || !root.querySelector('.pd-long-toc-panel').matches(':target')) return;
children.hidden = false;
var to = open ? children.getBoundingClientRect().height : 0;
if (from === to) {
settle(branch, open);
return;
}
children.style.overflow = 'hidden';
var animation;
try {
animation = children.animate([
{ height: from + 'px', opacity: open ? 0.6 : 1 },
{ height: to + 'px', opacity: open ? 1 : 0.6 }
], { duration: 200, easing: 'cubic-bezier(0.2, 0, 0, 1)' });
} catch (error) {
settle(branch, open);
return;
}
branch.animation = animation;
animation.finished.then(function () {
if (branch.animation === animation) settle(branch, open);
}, function () { /* Superseded by a newer click. */ });
}
function close(branch) {
var height = branch.children.hidden ? 0 : branch.children.getBoundingClientRect().height;
branches.forEach(function (descendant) {
if (branch.children.contains(descendant.item)) {
settle(descendant, false);
}
});
transition(branch, false, height);
}
branches.forEach(function (branch) {
branch.button.addEventListener('click', function () {
/* Nested clicks release any still-animating ancestor height. */
branches.forEach(function (ancestor) {
if (ancestor.animation && ancestor.children.contains(branch.item)) {
settle(ancestor, ancestor.button.getAttribute('aria-expanded') === 'true');
}
});
if (branch.button.getAttribute('aria-expanded') === 'true') {
close(branch);
return;
}
branches.forEach(function (other) {
if (other !== branch && (mode === 1 || other.group === branch.group)) close(other);
});
transition(branch, true);
});
});
/* Resize, motion preference changes and printing must not retain clipped heights. */
function settleAll() {
branches.forEach(function (branch) {
if (branch.animation) settle(branch, branch.button.getAttribute('aria-expanded') === 'true');
});
}
window.addEventListener('resize', settleAll);
window.addEventListener('beforeprint', settleAll);
window.addEventListener('hashchange', function () {
if (!root.querySelector('.pd-long-toc-panel').matches(':target')) settleAll();
});
if (window.matchMedia) {
var motionPreference = window.matchMedia('(prefers-reduced-motion: reduce)');
if (motionPreference.addEventListener) motionPreference.addEventListener('change', settleAll);
}
original.replaceWith(list);
root.classList.add('pd-long-toc-enhanced');
root.addEventListener('pointerdown', function () {
root.classList.remove('pd-long-toc-keyboard');
});
root.addEventListener('keydown', function () {
root.classList.add('pd-long-toc-keyboard');
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Tab' && root.isConnected) {
root.classList.add('pd-long-toc-keyboard');
}
});
root.dataset.pdLongTocReady = '1.1';
}
function init(scope) {
var roots = [];
if (scope.matches && scope.matches('.pd-long-toc-root')) roots.push(scope);
roots = roots.concat(Array.prototype.slice.call(scope.querySelectorAll('.pd-long-toc-root')));
roots.forEach(function (root) {
try { enhance(root); } catch (error) {
if (window.console) console.warn('Long TOC: retained original directory.', error);
}
});
}
window.pdLongTocV11 = { init: init };
if (window.mw && mw.hook) {
mw.hook('wikipage.content').add(function (content) {
init(content[0] || content);
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function () { init(document); }, { once: true });
} else {
init(document);
}
}());
</script>
