这是测试站点!!!!
不要保存重要内容!不要保存重要内容!不要保存重要内容!不要保存重要内容!不要保存重要内容!
微件:PD卡牌
来自Limbo Wiki
<script> /* Project Divide unified card interface. Loaded only by its widget; no dependencies. */ (function () {
'use strict';
if (window.pdCards) { window.pdCards.init(); return; }
var packs = [], reduce = window.matchMedia('(prefers-reduced-motion: reduce)');
var collator = new Intl.Collator('zh-Hans-CN-u-co-pinyin', { numeric: true, sensitivity: 'base' });
function button(text, action) {
var b = document.createElement('button'); b.type = 'button'; b.textContent = text;
b.addEventListener('click', action); return b;
}
function cancelEffects(s) {
(s.effects || []).forEach(function (a) { a.cancel(); }); s.effects = [];
if (s.move) { s.move.cancel(); s.move = null; }
}
function clearHeight(s) {
s.detail.hidden = !s.open; s.detail.inert = !s.open;
s.detail.style.height = ; s.detail.style.overflow = ; s.detail.style.opacity = ;
}
function settle(s) {
if (s.animation) { s.animation.cancel(); s.animation = null; }
cancelEffects(s); clearHeight(s);
}
function near(rect) { return rect.bottom > -100 && rect.top < window.innerHeight + 100; }
function layers(s) {
var items = [], rules = s.detail.querySelector('.pd-card-ui-rules');
s.detail.querySelectorAll('.pd-card-ui-label').forEach(function (el) { items.push({ el: el, delay: 0 }); });
var skills = Array.from(rules ? rules.children : []).filter(function (el) { return el.classList.contains('pd-skill'); });
if (skills.length) skills.forEach(function (el, i) { items.push({ el: el, delay: 100 + Math.min(i * 25, 100) }); });
else if (rules) items.push({ el: rules, delay: 100 });
s.detail.querySelectorAll('.pd-card-ui-field').forEach(function (field, i) {
Array.from(field.children).filter(function (el) { return !el.classList.contains('pd-card-ui-label'); }).forEach(function (el) {
items.push({ el: el, delay: 100 + Math.min(i * 25, 100) });
});
});
var credit = s.detail.querySelector('.pd-card-ui-credit'); if (credit) items.push({ el: credit, delay: 150 });
return items;
}
function toggle(s, open, immediate) {
if (s.open === open && !immediate) return;
var wasHidden = s.detail.hidden;
var cs = getComputedStyle(s.detail);
var height = wasHidden ? 0 : s.detail.getBoundingClientRect().height - parseFloat(cs.borderTopWidth) - parseFloat(cs.borderBottomWidth);
var parts = layers(s).map(function (item) {
var style = getComputedStyle(item.el);
item.opacity = wasHidden ? 0 : Number(style.opacity);
item.transform = wasHidden ? 'translateY(6px)' : style.transform;
return item;
});
if (s.animation) { s.animation.cancel(); s.animation = null; }
cancelEffects(s);
if (!open && s.detail.contains(document.activeElement)) s.button.focus({ preventScroll: true });
s.open = open; s.button.setAttribute('aria-expanded', String(open)); s.summary.setAttribute('data-expanded', String(open)); s.detail.inert = !open;
s.detail.hidden = false;
if (immediate || reduce.matches || !s.detail.animate) { settle(s); return; }
s.detail.style.overflow = 'hidden';
parts.forEach(function (item) {
var effect = item.el.animate([
{ opacity: item.opacity, transform: item.transform },
{ opacity: open ? 1 : 0, transform: open ? 'translateY(0)' : item.transform }
], { duration: open ? 250 : 100, delay: open && wasHidden ? item.delay : 0, easing: 'cubic-bezier(.2,.7,.2,1)', fill: 'both' });
s.effects.push(effect);
effect.onfinish = function () { if (open) { effect.cancel(); s.effects = s.effects.filter(function (a) { return a !== effect; }); } };
});
var a = s.detail.animate([{ height: Math.max(0, height) + 'px' },
{ height: (open ? s.detail.scrollHeight : 0) + 'px' }],
{ duration: open ? 300 : 200, easing: 'cubic-bezier(.2,.7,.2,1)', fill: 'both' });
s.animation = a;
a.onfinish = function () {
if (s.animation !== a) return;
a.cancel(); s.animation = null;
if (open) clearHeight(s); else settle(s);
};
}
function batch(p, open) {
var visible = p.states.map(function (s) { var r = s.card.getBoundingClientRect(); return r.bottom > 0 && r.top < window.innerHeight; });
p.states.forEach(function (s, i) { toggle(s, open, !visible[i]); });
}
function numeric(raw) {
var v = raw.trim().replace(/−/g, '-');
return /^[+-]?(?:\d+(?:\.\d+)?|\.\d+)$/.test(v) ? Number(v) : null;
}
function placeIcons(s) {
var group = s.indicators || s.summary.querySelector('.pd-card-ui-indicators');
if (!group) return; s.indicators = group;
var container = window.innerWidth < 700 ? s.summary.querySelector('.pd-card-ui-type') : s.summary.querySelector('.pd-card-ui-name');
if (group.parentNode !== container) {
if (window.innerWidth < 700) container.insertBefore(group, container.firstChild);
else container.appendChild(group);
}
}
function glyph(type) {
var ns = 'http://www.w3.org/2000/svg';
var svg = document.createElementNS(ns, 'svg');
svg.setAttribute('viewBox', '0 0 14 14'); svg.setAttribute('width', '14'); svg.setAttribute('height', '14');
svg.setAttribute('aria-hidden', 'true'); svg.setAttribute('focusable', 'false');
var shape;
if (type === '被动') {
shape = document.createElementNS(ns, 'circle'); shape.setAttribute('cx', '7'); shape.setAttribute('cy', '7'); shape.setAttribute('r', '5.5');
} else if (type === '主动') {
shape = document.createElementNS(ns, 'rect'); shape.setAttribute('x', '1.5'); shape.setAttribute('y', '1.5'); shape.setAttribute('width', '11'); shape.setAttribute('height', '11');
} else {
shape = document.createElementNS(ns, 'polygon');
shape.setAttribute('points', type === '特殊' ? '7,0.7 8.9,4.7 13.3,5.3 10.1,8.4 10.9,12.8 7,10.7 3.1,12.8 3.9,8.4 0.7,5.3 5.1,4.7' : '7,1.6 12.3,11.9 1.7,11.9');
}
shape.setAttribute('fill', type === '离场' ? 'none' : 'currentColor');
if (type === '离场') { shape.setAttribute('stroke', 'currentColor'); shape.setAttribute('stroke-width', '1.6'); shape.setAttribute('stroke-linejoin', 'round'); }
svg.appendChild(shape); return svg;
}
function enhanceDetails(detail) {
detail.querySelectorAll('.pd-card-ui-tags').forEach(function (source) {
if (source.dataset.pdTagsReady) return;
var result = document.createDocumentFragment(), tag = document.createElement('span');
tag.className = 'pd-card-ui-tag';
function finish() {
var walker = document.createTreeWalker(tag, NodeFilter.SHOW_TEXT), first;
while ((first = walker.nextNode())) {
if (first.textContent.trim()) { first.textContent = first.textContent.replace(/^\s*·\s*/, ); break; }
}
if (tag.textContent.trim()) result.appendChild(tag);
tag = document.createElement('span'); tag.className = 'pd-card-ui-tag';
}
function visit(node) {
if (node.nodeType === 1 && node.tagName === 'BR') { finish(); return; }
if (node.nodeType === 1 && /^(P|UL|OL|LI|DIV)$/.test(node.tagName)) {
finish(); Array.from(node.childNodes).forEach(visit); finish(); return;
}
// Split inline markup at explicit line breaks without flattening its links or formatting.
if (node.nodeType === 1 && node.querySelector('br')) {
while (node.querySelector('br')) {
var br = node.querySelector('br'), range = document.createRange();
range.setStart(node, 0); range.setEndBefore(br);
var shell = node.cloneNode(false); shell.appendChild(range.extractContents()); tag.appendChild(shell);
br.remove(); finish();
}
}
tag.appendChild(node);
}
Array.from(source.childNodes).forEach(visit); finish(); source.replaceChildren(result);
source.dataset.pdTagsReady = 'true';
});
}
var activeSkill = null;
function selectSkill(skill) {
if (activeSkill) activeSkill.classList.remove('pd-card-ui-skill-active');
activeSkill = skill;
if (activeSkill) activeSkill.classList.add('pd-card-ui-skill-active');
}
function ownSkill(target) {
var skill = target.closest('.pd-skill');
while (skill && skill.parentElement.closest('.pd-skill')) skill = skill.parentElement.closest('.pd-skill');
return skill && skill.id && skill.closest('.pd-card-ui-rules') ? skill : null;
}
function enhanceSkills(s) {
var kind = s.card.dataset.kind;
if (kind !== '角色' && kind !== '置物') return;
var rules = s.detail.querySelector('.pd-card-ui-rules');
if (!rules) return;
var skills = Array.from(rules.querySelectorAll('.pd-skill')).filter(function (el) {
return !el.parentElement.closest('.pd-skill') && el.closest('.pd-card-ui-rules') === rules;
});
var icons = document.createElement('span'); icons.className = 'pd-card-ui-skill-icons';
skills.forEach(function (skill, i) {
skill.id = s.card.id + '-skill-' + (i + 1); skill.setAttribute('tabindex', '-1');
var heading = skill.querySelector('.pd-skill-title');
var type = heading.querySelector('.pd-skill-type').textContent.trim().replace(/^【|】$/g, );
var iconType = /主动$/.test(type) ? '主动' : type === '退场' ? '离场' : type;
if (['登场','被动','主动','离场','特殊'].indexOf(iconType) < 0) return;
var label = type + ':' + heading.querySelector('.pd-skill-name').textContent.trim();
var link = document.createElement('a'); link.className = 'pd-card-ui-skill-link';
link.href = '#' + skill.id; link.title = label; link.setAttribute('aria-label', label);
link.appendChild(glyph(iconType));
link.addEventListener('click', function (event) {
if (event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
event.preventDefault(); toggle(s, true, true); selectSkill(skill);
if (location.hash !== '#' + skill.id) location.hash = skill.id;
skill.focus({ preventScroll: true }); skill.scrollIntoView({ block: 'start', behavior: 'instant' });
});
icons.appendChild(link);
});
if (icons.childElementCount) {
s.icons = icons;
s.indicators = s.summary.querySelector('.pd-card-ui-indicators');
if (!s.indicators) { s.indicators = document.createElement('span'); s.indicators.className = 'pd-card-ui-indicators'; }
s.indicators.insertBefore(icons, s.indicators.firstChild);
s.summary.classList.add('pd-card-ui-has-skills'); placeIcons(s);
}
}
function key(s, field) {
if (field === 'number') return s.number === '未编号' ? null : s.number;
if (field === 'name') return s.name;
if (field === 'rarity') { var r = ['C', 'B', 'A', 'S'].indexOf(s.card.dataset.rarity.trim()); return r < 0 ? null : r; }
return numeric(s.card.dataset[field] || );
}
function sort(p) {
var field = p.select.value;
p.states.forEach(settle);
var before = p.states.map(function (s) { return s.card.getBoundingClientRect(); });
var ordered = p.states.slice().sort(function (a, b) {
if (field === 'original') return a.index - b.index;
var x = key(a, field), y = key(b, field);
if (x === null || y === null) return x === y ? a.index - b.index : x === null ? 1 : -1;
var diff = typeof x === 'number' ? x - y : collator.compare(x, y);
return diff ? diff * p.direction : a.index - b.index;
});
ordered.forEach(function (s) { p.list.appendChild(s.card); });
if (!reduce.matches) p.states.forEach(function (s, i) {
if (!s.card.animate) return;
var old = before[i], rect = s.card.getBoundingClientRect(), dy = old.top - rect.top;
if (Math.abs(dy) < 1 || !near(rect)) return;
var shortMove = near(old) && Math.abs(dy) <= 160;
var a = s.card.animate(shortMove ? [{ transform: 'translateY(' + dy + 'px)' }, { transform: 'translateY(0)' }] : [{ opacity: .65 }, { opacity: 1 }],
{ duration: shortMove ? 250 : 160, easing: 'cubic-bezier(.2,.7,.2,1)', fill: 'both' });
s.move = a; a.onfinish = function () { if (s.move === a) { a.cancel(); s.move = null; } };
});
p.directionButton.disabled = field === 'original';
p.directionButton.textContent = p.direction === 1 ? '升序 ↑' : '降序 ↓';
}
function assignAnchor(root, card, doc) {
if (card.id) return card.id;
var original = card.querySelector('.pd-card-ui-summary');
var packId = root.dataset.anchorPrefix || root.dataset.pack || root.dataset.packName || 'cards';
var seed = card.dataset.number.trim() || original.querySelector('.pd-card-ui-name-text').textContent.trim();
var base = 'pd-card-' + (packId + '-' + seed).trim().replace(/\s+/g, '_').replace(/[\u0000-\u001f\u007f]/g, ), candidate = base, serial = 2;
while (doc.getElementById(candidate)) { candidate = base + '-' + serial; serial++; }
card.id = candidate; return candidate;
}
function resolveAnchors(doc) {
var ids = [];
doc.querySelectorAll('.pd-card-ui-pack-root').forEach(function(root) {
Array.from(root.querySelector('.pd-card-ui-list').children).filter(function(c) { return c.classList.contains('pd-card-ui-card'); }).forEach(function(card) { ids.push(assignAnchor(root, card, doc)); });
});
return ids;
}
function initPack(root) {
if (root.dataset.pdCardsReady) return;
var p = { root: root, list: root.querySelector('.pd-card-ui-list'), states: [], direction: 1 };
var controls = root.querySelector('.pd-card-ui-controls');
try {
Array.from(p.list.children).filter(function (c) { return c.classList.contains('pd-card-ui-card'); }).forEach(function (card, i) {
var original = card.querySelector('.pd-card-ui-summary');
assignAnchor(root, card, document);
var b = document.createElement('button'); b.type = 'button'; b.className = 'pd-card-ui-toggle';
b.setAttribute('aria-label', original.textContent.trim().replace(/\s+/g, ' '));
var detail = card.querySelector('.pd-card-ui-detail'); detail.id = card.id + '-detail';
b.setAttribute('aria-controls', detail.id);
var s = { card: card, button: b, detail: detail, summary: original, index: i, open: false, animation: null,
number: original.querySelector('.pd-card-ui-number').textContent.trim(), name: original.querySelector('.pd-card-ui-name-text').textContent.trim() };
p.states.push(s);
detail.addEventListener('click', function (event) { var skill = ownSkill(event.target); if (skill) selectSkill(skill); });
detail.addEventListener('focusin', function (event) { var skill = ownSkill(event.target); if (skill) selectSkill(skill); });
original.appendChild(b); b.addEventListener('click', function () { toggle(s, !s.open, false); });
try { enhanceDetails(detail); enhanceSkills(s); placeIcons(s); } catch (error) {
if (s.icons) s.icons.remove(); s.icons = null; original.classList.remove('pd-card-ui-has-skills');
console.error('PD skill icons unavailable; skill text retained.', error);
}
});
var count = document.createElement('span'); count.className = 'pd-card-ui-count'; count.textContent = p.states.length + ' 张卡牌';
var label = document.createElement('label'); label.textContent = '排序方式';
p.select = document.createElement('select'); p.select.style.colorScheme = 'dark';
p.list.style.overflowAnchor = 'none';
[['original','原顺序'],['number','编号'],['name','名字'],['ep','EP'],['bp','BP'],['kb','KB'],['rarity','稀有度']].forEach(function (item) {
var option = document.createElement('option'); option.value = item[0]; option.textContent = item[1]; p.select.appendChild(option);
});
label.appendChild(p.select);
p.directionButton = button('升序 ↑', function () { p.direction *= -1; sort(p); }); p.directionButton.disabled = true;
p.select.addEventListener('change', function () { p.direction = 1; sort(p); });
var expand = button('全部展开', function () { batch(p, true); });
var collapse = button('全部收起', function () { batch(p, false); });
p.select.title = 'KB 按正负数值排序;缺失与复合数值排在末尾。';
var sorting = document.createElement('div'); sorting.className = 'pd-card-ui-sort-controls';
var bulk = document.createElement('div'); bulk.className = 'pd-card-ui-bulk-controls';
sorting.append(label, p.directionButton); bulk.append(expand, collapse); controls.append(sorting, bulk);
p.states.forEach(function (s) { toggle(s, false, true); });
root.classList.add('pd-card-ui-ready'); root.dataset.pdCardsReady = 'true'; packs.push(p);
} catch (error) {
p.states.forEach(function (s) {
s.open = true; settle(s);
s.button.remove(); if (s.icons) s.icons.remove();
s.summary.removeAttribute('data-expanded'); s.summary.classList.remove('pd-card-ui-has-skills');
});
controls.replaceChildren(); root.classList.remove('pd-card-ui-ready');
console.error('PD card demo initialization failed; full content retained.', error);
}
}
function locate() {
var id; try { id = decodeURIComponent(location.hash.slice(1)); } catch (_) { return; }
var target = document.getElementById(id);
selectSkill(target ? ownSkill(target) : null);
if (!target) return;
packs.forEach(function (p) { p.states.forEach(function (s) {
if (s.card === target || s.card.contains(target)) {
toggle(s, true, true); requestAnimationFrame(function () { target.scrollIntoView({ block: 'start', behavior: 'instant' }); });
}
}); });
}
function init() { document.querySelectorAll('.pd-card-ui-pack-root').forEach(initPack); locate(); }
window.pdCards = { init: init, resolveAnchors: resolveAnchors, dispose: function (container) { packs = packs.filter(function (p) { if (!container.contains(p.root)) return true; p.states.forEach(settle); return false; }); } };
window.addEventListener('hashchange', locate);
window.addEventListener('resize', function () { packs.forEach(function (p) { p.states.forEach(function (s) { settle(s); placeIcons(s); }); }); });
reduce.addEventListener('change', function () { packs.forEach(function (p) { p.states.forEach(settle); }); });
window.addEventListener('beforeprint', function () { packs.forEach(function (p) { p.states.forEach(function (s) { settle(s); s.detail.inert = false; }); }); });
window.addEventListener('afterprint', function () { packs.forEach(function (p) { p.states.forEach(settle); }); });
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true }); else init();
})();
</script>
