MediaWiki:Common.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/* ============================================
TOON WIKI - INTERACTIVE FEATURES
============================================ */
(function() {
'use strict';
// Wait for DOM ready
document.addEventListener('DOMContentLoaded', function() {
// ===== Smooth Scroll for TOC links =====
document.querySelectorAll('.toc a, a[href^="#"]').forEach(function(link) {
link.addEventListener('click', function(e) {
var targetId = this.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
var target = document.querySelector(targetId);
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
history.pushState(null, null, targetId);
}
}
});
});
// ===== Lazy load images =====
if ('IntersectionObserver' in window) {
var imageObserver = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
var img = entry.target;
if (img.dataset.src) {
img.src = img.dataset.src;
img.removeAttribute('data-src');
}
imageObserver.unobserve(img);
}
});
}, { rootMargin: '50px' });
document.querySelectorAll('img[data-src]').forEach(function(img) {
imageObserver.observe(img);
});
}
// ===== Image lightbox effect =====
document.querySelectorAll('.mw-parser-output figure img').forEach(function(img) {
img.style.cursor = 'zoom-in';
img.addEventListener('click', function(e) {
e.preventDefault();
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.9);z-index:10000;display:flex;align-items:center;justify-content:center;cursor:zoom-out;opacity:0;transition:opacity 0.3s';
var largeImg = document.createElement('img');
largeImg.src = this.closest('a') ? this.closest('a').href : this.src;
largeImg.style.cssText = 'max-width:90vw;max-height:90vh;border-radius:8px;box-shadow:0 4px 32px rgba(0,0,0,0.5)';
overlay.appendChild(largeImg);
document.body.appendChild(overlay);
document.body.style.overflow = 'hidden';
requestAnimationFrame(function() { overlay.style.opacity = '1'; });
overlay.addEventListener('click', function() {
overlay.style.opacity = '0';
setTimeout(function() {
overlay.remove();
document.body.style.overflow = '';
}, 300);
});
});
});
// ===== Collapsible sections =====
document.querySelectorAll('.mw-parser-output h2, .mw-parser-output h3').forEach(function(header) {
header.style.cursor = 'pointer';
header.title = 'Click to collapse/expand';
var collapseBtn = document.createElement('span');
collapseBtn.textContent = ' ▼';
collapseBtn.style.cssText = 'font-size:0.7em;opacity:0.5;transition:transform 0.2s';
header.appendChild(collapseBtn);
header.addEventListener('click', function() {
var content = [];
var next = this.nextElementSibling;
var nextHeaderLevel = this.tagName;
while (next && !next.matches(nextHeaderLevel + ', h2')) {
content.push(next);
next = next.nextElementSibling;
}
var isCollapsed = content[0] && content[0].style.display === 'none';
content.forEach(function(el) {
el.style.display = isCollapsed ? '' : 'none';
});
collapseBtn.style.transform = isCollapsed ? '' : 'rotate(-90deg)';
});
});
// ===== Reading time estimate =====
var content = document.querySelector('.mw-parser-output');
if (content) {
var text = content.textContent;
var words = text.trim().split(/\s+/).length;
var minutes = Math.ceil(words / 200);
var readingTime = document.createElement('div');
readingTime.style.cssText = 'background:linear-gradient(135deg,#f8f9fa,#eaecf0);padding:8px 16px;border-radius:8px;margin-bottom:1em;font-size:0.9em;color:#555;display:flex;align-items:center;gap:8px';
readingTime.innerHTML = '<span style="font-size:1.2em">📖</span> <strong>' + minutes + ' min read</strong> · ' + words.toLocaleString() + ' words';
var firstElement = content.firstElementChild;
if (firstElement) {
content.insertBefore(readingTime, firstElement);
}
}
// ===== Highlight current section while scrolling =====
var headings = document.querySelectorAll('.mw-parser-output h2[id], .mw-parser-output h3[id]');
var tocLinks = document.querySelectorAll('.toc a');
if (headings.length > 0 && tocLinks.length > 0) {
var highlightCurrentSection = function() {
var scrollPos = window.scrollY + 100;
var current = null;
headings.forEach(function(heading) {
if (heading.offsetTop <= scrollPos) {
current = heading.id;
}
});
tocLinks.forEach(function(link) {
link.style.fontWeight = '';
link.style.color = '';
if (link.getAttribute('href') === '#' + current) {
link.style.fontWeight = 'bold';
link.style.color = '#1a4d7a';
}
});
};
window.addEventListener('scroll', highlightCurrentSection);
highlightCurrentSection();
}
// ===== Back to top button =====
var backToTop = document.createElement('button');
backToTop.textContent = '↑';
backToTop.style.cssText = 'position:fixed;bottom:20px;right:20px;width:50px;height:50px;border-radius:50%;background:linear-gradient(135deg,#1a4d7a,#2c5aa0);color:white;border:none;font-size:24px;cursor:pointer;opacity:0;transition:all 0.3s;z-index:1000;box-shadow:0 4px 12px rgba(0,0,0,0.3)';
backToTop.title = 'Back to top';
document.body.appendChild(backToTop);
backToTop.addEventListener('click', function() {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
window.addEventListener('scroll', function() {
backToTop.style.opacity = window.scrollY > 300 ? '1' : '0';
backToTop.style.pointerEvents = window.scrollY > 300 ? 'auto' : 'none';
});
});
})();