Widget:GameSwitcher:修订间差异
来自OGAS数据中枢
更多操作
无编辑摘要 |
无编辑摘要 |
||
| 第13行: | 第13行: | ||
var firstBtn = switcher.querySelector('.gs-tab-btn'); | var firstBtn = switcher.querySelector('.gs-tab-btn'); | ||
if (firstBtn) { | if (firstBtn) { | ||
firstBtn.classList.add('gs-active'); | firstBtn.classList.add('gs-active'); | ||
firstBtn.setAttribute('aria-selected', 'true'); | firstBtn.setAttribute('aria-selected', 'true'); | ||
| 第20行: | 第19行: | ||
} | } | ||
} | } | ||
if (heroWrap) heroWrap.style.opacity = '1'; | |||
// ============ 点击 ============ | // ============ 点击 ============ | ||
| 第54行: | 第54行: | ||
} | } | ||
}, true); | }, true); | ||
// ============ 激活面板 ============ | // ============ 激活面板 ============ | ||
| 第64行: | 第63行: | ||
var pageName = btn.dataset.page; | var pageName = btn.dataset.page; | ||
// 头图 | |||
switchHero(heroSrc); | switchHero(heroSrc); | ||
// 按钮高亮 | |||
switcher.querySelectorAll('.gs-tab-btn').forEach(function (b) { | switcher.querySelectorAll('.gs-tab-btn').forEach(function (b) { | ||
b.classList.remove('gs-active'); | b.classList.remove('gs-active'); | ||
| 第73行: | 第74行: | ||
btn.setAttribute('aria-selected', 'true'); | btn.setAttribute('aria-selected', 'true'); | ||
// 面板切换 | |||
switcher.querySelectorAll('.gs-content-panel').forEach(function (p) { | switcher.querySelectorAll('.gs-content-panel').forEach(function (p) { | ||
p.classList.remove('gs-active'); | |||
p.classList.remove('gs-anim'); | |||
}); | }); | ||
if (!panel) { | var panel = document.getElementById(panelId); | ||
if (!panel) { | |||
panel = document.createElement('div'); | |||
panel.id = panelId; | |||
panel.className = 'gs-content-panel'; | |||
switcher.querySelector('.gs-content').appendChild(panel); | |||
} | loadContent(panel, panelId, pageName); | ||
} | |||
panel.classList.add('gs-active'); | panel.classList.add('gs-active'); | ||
panel.offsetWidth; // 强制重排, | panel.offsetWidth; // 强制重排,确保动画触发 | ||
panel.classList.add('gs-anim'); | panel.classList.add('gs-anim'); | ||
schedulePrefetchOthers(); | schedulePrefetchOthers(); | ||
| 第94行: | 第97行: | ||
// ============ 头图切换 ============ | // ============ 头图切换 ============ | ||
function switchHero(url) { | function switchHero(url) { | ||
if (!heroWrap || !heroImg || !url) return; | |||
if (heroImg.src === url) return; | |||
var next = new Image(); | |||
next.onload = function () { | |||
heroWrap.style.opacity = '0'; | |||
setTimeout(function () { | |||
heroImg.src = url; | |||
heroWrap.style.opacity = '1'; | |||
}, 300); | |||
}; | |||
next.src = url; | |||
} | |||
} | |||
// ============ 内容加载 ============ | // ============ 内容加载 ============ | ||
function loadContent(panel, panelId, pageName) { | function loadContent(panel, panelId, pageName) { | ||
if (loaded[panelId]) { panel.innerHTML = loaded[panelId]; return; } | if (loaded[panelId]) { | ||
panel.innerHTML = loaded[panelId]; | |||
return; | |||
} | |||
try { | try { | ||
var stored = localStorage.getItem(storageKey + panelId); | var stored = localStorage.getItem(storageKey + panelId); | ||
if (stored) { loaded[panelId] = stored; panel.innerHTML = stored; return; } | if (stored) { | ||
loaded[panelId] = stored; | |||
panel.innerHTML = stored; | |||
return; | |||
} | |||
} catch (e) {} | } catch (e) {} | ||
| 第136行: | 第144行: | ||
try { | try { | ||
var stored = localStorage.getItem(storageKey + panelId); | var stored = localStorage.getItem(storageKey + panelId); | ||
if (stored) { loaded[panelId] = stored; prefetching[panelId] = false; return; } | if (stored) { | ||
loaded[panelId] = stored; | |||
prefetching[panelId] = false; | |||
return; | |||
} | |||
} catch (e) {} | } catch (e) {} | ||
| 第171行: | 第183行: | ||
}); | }); | ||
} | } | ||
}); | |||
</script> | </script> | ||
2026年6月20日 (六) 11:10的版本
<script type="text/javascript"> document.addEventListener('DOMContentLoaded', function () {
var switcher = document.querySelector('.game-switcher');
if (!switcher) return;
var heroWrap = document.getElementById('gs-hero-wrap');
var heroImg = heroWrap ? heroWrap.querySelector('img') : null;
var loaded = {};
var prefetching = {};
var storageKey = 'gs-cache-';
// ============ 初始化 ============
var firstBtn = switcher.querySelector('.gs-tab-btn');
if (firstBtn) {
firstBtn.classList.add('gs-active');
firstBtn.setAttribute('aria-selected', 'true');
if (heroImg && !heroImg.getAttribute('src')) {
heroImg.src = firstBtn.dataset.hero;
}
}
if (heroWrap) heroWrap.style.opacity = '1';
// ============ 点击 ============
switcher.addEventListener('click', function (e) {
var btn = e.target.closest('.gs-tab-btn');
if (btn) activate(btn);
});
// ============ 键盘 ============
switcher.addEventListener('keydown', function (e) {
var btn = e.target.closest('.gs-tab-btn');
if (!btn) return;
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
activate(btn);
}
if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
e.preventDefault();
var btns = Array.from(switcher.querySelectorAll('.gs-tab-btn'));
var idx = btns.indexOf(btn);
var next = e.key === 'ArrowRight' ? idx + 1 : idx - 1;
if (next >= 0 && next < btns.length) btns[next].focus();
}
});
// ============ 悬停预加载 ============
switcher.addEventListener('mouseenter', function (e) {
var btn = e.target.closest('.gs-tab-btn');
if (!btn) return;
var panelId = btn.dataset.panel;
var pageName = btn.dataset.page;
if (pageName && !loaded[panelId] && !prefetching[panelId]) {
prefetch(panelId, pageName);
}
}, true);
// ============ 激活面板 ============
function activate(btn) {
if (btn.classList.contains('gs-active')) return;
var panelId = btn.dataset.panel; var heroSrc = btn.dataset.hero; var pageName = btn.dataset.page;
// 头图 switchHero(heroSrc);
// 按钮高亮
switcher.querySelectorAll('.gs-tab-btn').forEach(function (b) {
b.classList.remove('gs-active');
b.setAttribute('aria-selected', 'false');
});
btn.classList.add('gs-active');
btn.setAttribute('aria-selected', 'true');
// 面板切换
switcher.querySelectorAll('.gs-content-panel').forEach(function (p) {
p.classList.remove('gs-active');
p.classList.remove('gs-anim');
});
var panel = document.getElementById(panelId);
if (!panel) {
panel = document.createElement('div');
panel.id = panelId;
panel.className = 'gs-content-panel';
switcher.querySelector('.gs-content').appendChild(panel);
loadContent(panel, panelId, pageName);
}
panel.classList.add('gs-active');
panel.offsetWidth; // 强制重排,确保动画触发
panel.classList.add('gs-anim');
schedulePrefetchOthers(); }
// ============ 头图切换 ============
function switchHero(url) {
if (!heroWrap || !heroImg || !url) return;
if (heroImg.src === url) return;
var next = new Image();
next.onload = function () {
heroWrap.style.opacity = '0';
setTimeout(function () {
heroImg.src = url;
heroWrap.style.opacity = '1';
}, 300);
};
next.src = url;
}
// ============ 内容加载 ============
function loadContent(panel, panelId, pageName) {
if (loaded[panelId]) {
panel.innerHTML = loaded[panelId];
return;
}
try {
var stored = localStorage.getItem(storageKey + panelId);
if (stored) {
loaded[panelId] = stored;
panel.innerHTML = stored;
return;
}
} catch (e) {}
if (!pageName) return;
panel.innerHTML = '
加载中...
';
fetchPage(pageName).then(function (html) {
loaded[panelId] = html;
try { localStorage.setItem(storageKey + panelId, html); } catch (e) {}
panel.innerHTML = html;
}).catch(function () {
panel.innerHTML = '
加载失败,<a href="javascript:location.reload()">刷新</a>重试
';
}); }
// ============ 预加载 ============
function prefetch(panelId, pageName) {
prefetching[panelId] = true;
try {
var stored = localStorage.getItem(storageKey + panelId);
if (stored) {
loaded[panelId] = stored;
prefetching[panelId] = false;
return;
}
} catch (e) {}
fetchPage(pageName).then(function (html) {
loaded[panelId] = html;
try { localStorage.setItem(storageKey + panelId, html); } catch (e) {}
}).finally(function () {
prefetching[panelId] = false;
});
}
function schedulePrefetchOthers() {
setTimeout(function () {
switcher.querySelectorAll('.gs-tab-btn').forEach(function (btn) {
var panelId = btn.dataset.panel;
var pageName = btn.dataset.page;
if (!loaded[panelId] && !prefetching[panelId] && pageName) {
prefetch(panelId, pageName);
}
});
}, 500);
}
// ============ API 请求 ============
function fetchPage(pageName) {
var url = mw.util.wikiScript('api') +
'?action=parse&page=' + encodeURIComponent(pageName) +
'&prop=text&format=json&disablelimitreport=1&origin=*';
return fetch(url)
.then(function (r) { return r.json(); })
.then(function (data) {
if (data.parse && data.parse.text) return data.parse.text['*'];
throw new Error('empty');
});
}
}); </script>