微件:GameSwitcher
来自OGAS数据中枢
更多操作
<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) {
heroWrap.style.opacity = '1';
firstBtn.classList.add('gs-active');
firstBtn.setAttribute('aria-selected', 'true');
if (heroImg && !heroImg.getAttribute('src')) {
heroImg.src = firstBtn.dataset.hero;
}
}
// ============ 点击 ============
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');
});
var panel = document.getElementById(panelId);
if (!panel) {
panel = document.createElement('div');
panel.id = panelId;
panel.className = 'gs-content-panel gs-active';
switcher.querySelector('.gs-content').appendChild(panel);
loadContent(panel, panelId, pageName);
} else {
panel.classList.add('gs-active');
}
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.onerror = function () {};
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>