Adds a quality-of-life menu to quickly navigate pages
// ==UserScript==
// @name Battle Cats Wiki - Easy Navigation
// @namespace https://battlecats.miraheze.org/
// @version 1.0
// @description Adds a quality-of-life menu to quickly navigate pages
// @author ProfessionalScriptKiddie
// @license MIT
// @match https://battlecats.miraheze.org/wiki/*
// @icon https://files.catbox.moe/7srjk6.png
// @grant none
// @run-at document-idle
// ==/UserScript==
function waitForLocationBox(callback) {
const check = () => {
const el = document.querySelector('.pi-item[data-source="next stage"]');
if (el) {
callback();
return true;
}
return false;
};
if (check()) return;
const observer = new MutationObserver(() => {
if (check()) observer.disconnect();
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => {
if (!check()) observer.disconnect();
}, 5000);
}
waitForLocationBox(() => {
const getLinkFromSource = (source) => {
const container = document.querySelector(`.pi-item[data-source="${source}"]`);
if (!container) return null;
const link = container.querySelector('a');
return link ? { href: link.href, text: link.textContent.trim() } : null;
};
const findNextSubChapterFirstStage = (currentSubChapterName) => {
const navboxes = document.querySelectorAll('.navbox');
for (const navbox of navboxes) {
const rows = navbox.querySelectorAll('tr');
let foundCurrentChapter = false;
for (const row of rows) {
const th = row.querySelector('th');
if (!th) continue;
const chapterLink = th.querySelector('a');
if (!chapterLink) continue;
const chapterName = chapterLink.textContent.trim();
if (foundCurrentChapter) {
const td = row.querySelector('td');
if (td) {
const firstStageLink = td.querySelector('a');
if (firstStageLink) {
return {
href: firstStageLink.href,
text: firstStageLink.textContent.trim()
};
}
}
}
if (chapterName === currentSubChapterName) {
foundCurrentChapter = true;
}
}
}
return null;
};
const prevStage = getLinkFromSource("prev stage");
let nextStage = getLinkFromSource("next stage");
const chapter = getLinkFromSource("sub-chapter");
if (!nextStage && chapter) {
const nextSubChapterStage = findNextSubChapterFirstStage(chapter.text);
if (nextSubChapterStage) {
nextStage = nextSubChapterStage;
}
}
if (!prevStage && !nextStage && !chapter) return;
const originalHeader = document.querySelector('#citizen-page-header');
if (!originalHeader) return;
const navBar = document.createElement('div');
navBar.style.position = 'sticky';
navBar.style.top = '0';
navBar.style.zIndex = '1000';
navBar.style.background = 'transparent';
navBar.style.borderBottom = 'none';
navBar.style.boxShadow = 'none';
const navContainer = document.createElement('div');
navContainer.style.display = 'flex';
navContainer.style.justifyContent = 'center';
navContainer.style.alignItems = 'center';
navContainer.style.gap = '1em';
navContainer.style.padding = '12px 20px';
navContainer.style.maxWidth = '1200px';
navContainer.style.margin = '0 auto';
const makeLinkButton = (text, href) => {
const a = document.createElement('a');
a.href = href;
a.textContent = text;
a.style.color = '#fff';
a.style.textDecoration = 'none';
a.style.padding = '8px 16px';
a.style.border = '1px solid #555';
a.style.borderRadius = '4px';
a.style.background = '#333';
a.style.transition = 'background 0.2s, border-color 0.2s';
a.style.fontSize = '14px';
a.style.fontWeight = '500';
a.style.whiteSpace = 'nowrap';
a.addEventListener('mouseenter', () => {
a.style.background = '#555';
a.style.borderColor = '#777';
});
a.addEventListener('mouseleave', () => {
a.style.background = '#333';
a.style.borderColor = '#555';
});
return a;
};
if (prevStage) navContainer.appendChild(makeLinkButton(`← ${prevStage.text}`, prevStage.href));
if (chapter) navContainer.appendChild(makeLinkButton(`↗️ ${chapter.text}`, chapter.href));
if (nextStage) navContainer.appendChild(makeLinkButton(`${nextStage.text} →`, nextStage.href));
navBar.appendChild(navContainer);
originalHeader.parentNode.insertBefore(navBar, originalHeader.nextSibling);
});