MediaWiki:Common.js: Difference between revisions
From Ragnafied Wiki
No edit summary Tag: Manual revert |
No edit summary Tag: Reverted |
||
| Line 1: | Line 1: | ||
$(document).ready(function() { | $(document).ready(function() { | ||
// 1. | // =========================================== | ||
// Configuration | |||
// =========================================== | |||
const CONFIG = { | |||
scrollThreshold: 300, | |||
menuHideThreshold: 500, | |||
desktopBreakpoint: 768, | |||
progressBar: true, | |||
backToTop: true, | |||
floatingMenu: true, | |||
smoothScroll: true, | |||
stickyHeader: true, | |||
readingTime: true, | |||
tableOfContents: true | |||
}; | |||
// =========================================== | |||
// 1. Initialize UI Elements | |||
// =========================================== | |||
function initializeUI() { | |||
// Progress Bar | |||
if (CONFIG.progressBar) { | |||
$('body').append('<div id="scroll-progress"></div>'); | |||
} | |||
// Back to Top Button | |||
if (CONFIG.backToTop) { | |||
var topButtonHTML = '<div class="back-to-top-fixed" style="display:none;"><a href="#">↑ TOP</a></div>'; | |||
$('body').append(topButtonHTML); | |||
} | |||
// Floating Menu | |||
if (CONFIG.floatingMenu) { | |||
var menuHTML = ` | |||
<div class="floating-menu" id="floatingMenu"> | |||
<div class="floating-menu-header" id="menuHeader"> | |||
<span>📋 QUICK NAV</span> | |||
<span class="arrow">▼</span> | |||
</div> | |||
<div class="floating-menu-items"> | |||
<a href="/index.php/Main_Page">🏠 Main Page</a> | |||
<a href="/index.php/First_Steps">🚀 First Steps</a> | |||
<a href="/index.php/VIP">👑 VIP</a> | |||
<a href="/index.php/Enchant_Stones">💎 Enchant Stones</a> | |||
<a href="/index.php/Nyangvines">🐱 Nyangvines</a> | |||
<a href="/index.php/Custom_Systems">⚙️ Custom Systems</a> | |||
<a href="/index.php/Monthly_Kachua">📅 Monthly Kachua</a> | |||
<a href="/index.php/Troubleshooting">🔧 Troubleshooting</a> | |||
<a href="/index.php/Card_Trader_and_Kachua_Tokens">🃏 Card and Tokens</a> | |||
<a href="/index.php/Equipment_Enhancement">🛡️ EQ Enhancement</a> | |||
</div> | |||
</div> | |||
<div class="floating-menu-toggle" id="menuToggle">☰</div> | |||
`; | |||
$('body').append(menuHTML); | |||
} | |||
} | |||
initializeUI(); | |||
// =========================================== | |||
// 2. Scroll Event Handler | |||
// =========================================== | |||
var lastScrollTop = 0; | var lastScrollTop = 0; | ||
var scrollTimer = null; | |||
$(window).scroll(function() { | $(window).scroll(function() { | ||
var st = $(this).scrollTop(); | var st = $(this).scrollTop(); | ||
// A. Progress Bar | // Throttle scroll events for better performance | ||
if (scrollTimer) { | |||
clearTimeout(scrollTimer); | |||
} | |||
scrollTimer = setTimeout(function() { | |||
// A. Progress Bar | |||
if (CONFIG.progressBar) { | |||
var docHeight = $(document).height() - $(window).height(); | |||
var scrolled = (st / docHeight) * 100; | |||
$('#scroll-progress').css("width", scrolled + "%"); | |||
} | |||
// B. Top Button Fade | |||
if (CONFIG.backToTop) { | |||
if (st > CONFIG.scrollThreshold) { | |||
$('.back-to-top-fixed').fadeIn(); | |||
} else { | |||
$('.back-to-top-fixed').fadeOut(); | |||
} | |||
} | |||
// C. Hide Menu on Scroll Down (Desktop Only) | |||
if (CONFIG.floatingMenu && $(window).width() > CONFIG.desktopBreakpoint) { | |||
if (st > lastScrollTop && st > CONFIG.menuHideThreshold) { | |||
$('#floatingMenu').css('right', '-220px'); | |||
} else { | |||
$('#floatingMenu').css('right', '20px'); | |||
} | |||
} | |||
lastScrollTop = st; | |||
}, 10); // 10ms throttle | |||
// | // D. Sticky Header | ||
if ( | if (CONFIG.stickyHeader) { | ||
if (st > | if (st > 100) { | ||
$('# | $('#mw-head').addClass('sticky-header'); | ||
} else { | } else { | ||
$('# | $('#mw-head').removeClass('sticky-header'); | ||
} | } | ||
} | } | ||
}); | |||
// =========================================== | |||
// 3. Section Tracker (run on load and scroll) | |||
// =========================================== | |||
function updateActiveSection() { | |||
var currentPath = window.location.pathname; | var currentPath = window.location.pathname; | ||
$('.floating-menu-items a').each(function() { | $('.floating-menu-items a').each(function() { | ||
var href = $(this).attr('href'); | |||
if (currentPath.includes(href) || currentPath === href) { | |||
$(this).addClass('reading-now'); | $(this).addClass('reading-now'); | ||
} else { | } else { | ||
| Line 60: | Line 126: | ||
} | } | ||
}); | }); | ||
} | |||
// Run on load and scroll | |||
updateActiveSection(); | |||
$(window).on('scroll', updateActiveSection); | |||
// =========================================== | |||
// 4. Toggle Events | |||
// =========================================== | |||
$('#menuHeader').click(function() { | |||
$('#floatingMenu').toggleClass('collapsed'); | |||
}); | }); | ||
$('#menuToggle').click(function() { | |||
$('# | $('#floatingMenu').toggleClass('mobile-visible'); | ||
// Close menu when clicking outside | |||
$(document).one('click', function(e) { | |||
if (!$(e.target).closest('#floatingMenu, #menuToggle').length) { | |||
$('#floatingMenu').removeClass('mobile-visible'); | |||
} | |||
}); | |||
}); | |||
// Close menu with Escape key | |||
$(document).keyup(function(e) { | |||
if (e.key === "Escape") { | |||
$('#floatingMenu').removeClass('mobile-visible'); | |||
} | |||
}); | |||
// =========================================== | |||
// 5. Back to Top Button | |||
// =========================================== | |||
$('.back-to-top-fixed a').click(function(e) { | $('.back-to-top-fixed a').click(function(e) { | ||
e.preventDefault(); | e.preventDefault(); | ||
$('html, body').animate({scrollTop: 0}, 400); | $('html, body').animate({scrollTop: 0}, 400, 'swing'); | ||
}); | }); | ||
// =========================================== | |||
// | // 6. Smooth Scrolling for Anchor Links | ||
// =========================================== | |||
if (CONFIG.smoothScroll) { | |||
$('a[href^="#"]').not('.no-smooth').on('click', function(e) { | |||
e.preventDefault(); | |||
var target = $(this.hash); | |||
if (target.length) { | |||
$('html, body').animate({ | |||
}, | scrollTop: target.offset().top - 60 | ||
}, 500, 'swing', function() { | |||
// Update URL hash without jumping | |||
if (history.pushState) { | |||
history.pushState(null, null, this.hash); | |||
} | |||
}); | |||
} | |||
}); | |||
} | |||
// =========================================== | |||
// 7. Reading Time Estimator | |||
// =========================================== | |||
if (CONFIG.readingTime) { | |||
var content = $('#mw-content-text').text(); | |||
var wordCount = content.split(/\s+/).length; | |||
var readingTime = Math.ceil(wordCount / 200); | |||
if (wordCount > 50) { // Only show for longer articles | |||
$('#firstHeading').append( | |||
'<span class="reading-time-badge" style="' + | |||
'font-size: 14px; ' + | |||
'font-weight: normal; ' + | |||
'margin-left: 15px; ' + | |||
'padding: 3px 10px; ' + | |||
'background: linear-gradient(135deg, #FF6A00, #D93800); ' + | |||
'color: white; ' + | |||
'border-radius: 20px; ' + | |||
'display: inline-block;' + | |||
'">📖 ' + readingTime + ' min read</span>' | |||
); | |||
} | |||
} | |||
// =========================================== | |||
// 8. Table of Contents Improvements | |||
// =========================================== | |||
if (CONFIG.tableOfContents && $('#toc').length) { | |||
// Add sticky TOC toggle | |||
$('#toc').before( | |||
'<div id="toc-controls" style="margin-bottom: 10px;">' + | |||
'<button id="toggle-toc" class="btn" style="' + | |||
'background: linear-gradient(135deg, #FF6A00, #D93800); ' + | |||
'color: white; ' + | |||
'border: none; ' + | |||
'padding: 5px 15px; ' + | |||
'border-radius: 5px; ' + | |||
'cursor: pointer;' + | |||
'">Hide Table of Contents</button>' + | |||
'</div>' | |||
); | |||
$('#toggle-toc').click(function() { | |||
$('#toc ul').slideToggle(200); | |||
$(this).text(function(i, text) { | |||
return text === 'Hide Table of Contents' ? | |||
'Show Table of Contents' : 'Hide Table of Contents'; | |||
}); | |||
}); | |||
// Add "Back to Top" links after each section | |||
$('h2, h3').each(function() { | |||
if ($(this).attr('id')) { | |||
$(this).append( | |||
' <a href="#top" class="section-top-link" style="' + | |||
'font-size: 12px; ' + | |||
'margin-left: 10px; ' + | |||
'text-decoration: none; ' + | |||
'opacity: 0.5; ' + | |||
'transition: opacity 0.3s;' + | |||
'">↑ top</a>' | |||
); | |||
$(this).find('.section-top-link').hover( | |||
function() { $(this).css('opacity', '1'); }, | |||
function() { $(this).css('opacity', '0.5'); } | |||
); | |||
} | |||
}); | |||
} | |||
// =========================================== | |||
// 9. Keyboard Navigation | |||
// =========================================== | |||
$(document).on('keydown', function(e) { | |||
// Alt + Q - Toggle floating menu | |||
if (e.altKey && e.key === 'q') { | |||
e.preventDefault(); | |||
$('#floatingMenu').toggleClass('collapsed'); | |||
} | |||
// Alt + T - Back to top | |||
if (e.altKey && e.key === 't') { | |||
e.preventDefault(); | |||
$('html, body').animate({scrollTop: 0}, 400); | |||
} | |||
// Alt + H - Go to Main Page | |||
if (e.altKey && e.key === 'h') { | |||
e.preventDefault(); | |||
window.location.href = '/index.php/Main_Page'; | |||
} | |||
}); | |||
// =========================================== | |||
// 10. Responsive Handling | |||
// =========================================== | |||
$(window).resize(function() { | |||
if ($(window).width() > CONFIG.desktopBreakpoint) { | |||
$('#floatingMenu').removeClass('mobile-visible'); | |||
$('#floatingMenu').css('right', '20px'); | |||
} else { | |||
$('#floatingMenu').css('right', ''); | |||
} | |||
}); | |||
// =========================================== | |||
// 11. Page Load Performance | |||
// =========================================== | |||
// Lazy load images if any | |||
$('img').each(function() { | |||
var img = $(this); | |||
var src = img.attr('src'); | |||
if (src && !img.hasClass('loaded')) { | |||
img.on('load', function() { | |||
$(this).addClass('loaded'); | |||
}); | |||
} | } | ||
}); | |||
// =========================================== | |||
// 12. Error Handling | |||
// =========================================== | |||
$(window).on('error', function(e) { | |||
console.log('JavaScript error:', e.message); | |||
}); | }); | ||
}); | }); | ||
// Sticky | // =========================================== | ||
// 13. Sticky Header CSS (add to your CSS file) | |||
// =========================================== | |||
/* | |||
.sticky-header { | |||
position: fixed !important; | |||
top: 0 !important; | |||
left: 0 !important; | |||
right: 0 !important; | |||
z-index: 1000 !important; | |||
background: white !important; | |||
box-shadow: 0 2px 10px rgba(0,0,0,0.1) !important; | |||
animation: slideDown 0.3s ease; | |||
} | |||
@keyframes slideDown { | |||
from { transform: translateY(-100%); } | |||
to { transform: translateY(0); } | |||
} | |||
*/ | |||
Revision as of 10:57, 21 February 2026
$(document).ready(function() {
// ===========================================
// Configuration
// ===========================================
const CONFIG = {
scrollThreshold: 300,
menuHideThreshold: 500,
desktopBreakpoint: 768,
progressBar: true,
backToTop: true,
floatingMenu: true,
smoothScroll: true,
stickyHeader: true,
readingTime: true,
tableOfContents: true
};
// ===========================================
// 1. Initialize UI Elements
// ===========================================
function initializeUI() {
// Progress Bar
if (CONFIG.progressBar) {
$('body').append('<div id="scroll-progress"></div>');
}
// Back to Top Button
if (CONFIG.backToTop) {
var topButtonHTML = '<div class="back-to-top-fixed" style="display:none;"><a href="#">↑ TOP</a></div>';
$('body').append(topButtonHTML);
}
// Floating Menu
if (CONFIG.floatingMenu) {
var menuHTML = `
<div class="floating-menu" id="floatingMenu">
<div class="floating-menu-header" id="menuHeader">
<span>📋 QUICK NAV</span>
<span class="arrow">▼</span>
</div>
<div class="floating-menu-items">
<a href="/index.php/Main_Page">🏠 Main Page</a>
<a href="/index.php/First_Steps">🚀 First Steps</a>
<a href="/index.php/VIP">👑 VIP</a>
<a href="/index.php/Enchant_Stones">💎 Enchant Stones</a>
<a href="/index.php/Nyangvines">🐱 Nyangvines</a>
<a href="/index.php/Custom_Systems">⚙️ Custom Systems</a>
<a href="/index.php/Monthly_Kachua">📅 Monthly Kachua</a>
<a href="/index.php/Troubleshooting">🔧 Troubleshooting</a>
<a href="/index.php/Card_Trader_and_Kachua_Tokens">🃏 Card and Tokens</a>
<a href="/index.php/Equipment_Enhancement">🛡️ EQ Enhancement</a>
</div>
</div>
<div class="floating-menu-toggle" id="menuToggle">☰</div>
`;
$('body').append(menuHTML);
}
}
initializeUI();
// ===========================================
// 2. Scroll Event Handler
// ===========================================
var lastScrollTop = 0;
var scrollTimer = null;
$(window).scroll(function() {
var st = $(this).scrollTop();
// Throttle scroll events for better performance
if (scrollTimer) {
clearTimeout(scrollTimer);
}
scrollTimer = setTimeout(function() {
// A. Progress Bar
if (CONFIG.progressBar) {
var docHeight = $(document).height() - $(window).height();
var scrolled = (st / docHeight) * 100;
$('#scroll-progress').css("width", scrolled + "%");
}
// B. Top Button Fade
if (CONFIG.backToTop) {
if (st > CONFIG.scrollThreshold) {
$('.back-to-top-fixed').fadeIn();
} else {
$('.back-to-top-fixed').fadeOut();
}
}
// C. Hide Menu on Scroll Down (Desktop Only)
if (CONFIG.floatingMenu && $(window).width() > CONFIG.desktopBreakpoint) {
if (st > lastScrollTop && st > CONFIG.menuHideThreshold) {
$('#floatingMenu').css('right', '-220px');
} else {
$('#floatingMenu').css('right', '20px');
}
}
lastScrollTop = st;
}, 10); // 10ms throttle
// D. Sticky Header
if (CONFIG.stickyHeader) {
if (st > 100) {
$('#mw-head').addClass('sticky-header');
} else {
$('#mw-head').removeClass('sticky-header');
}
}
});
// ===========================================
// 3. Section Tracker (run on load and scroll)
// ===========================================
function updateActiveSection() {
var currentPath = window.location.pathname;
$('.floating-menu-items a').each(function() {
var href = $(this).attr('href');
if (currentPath.includes(href) || currentPath === href) {
$(this).addClass('reading-now');
} else {
$(this).removeClass('reading-now');
}
});
}
// Run on load and scroll
updateActiveSection();
$(window).on('scroll', updateActiveSection);
// ===========================================
// 4. Toggle Events
// ===========================================
$('#menuHeader').click(function() {
$('#floatingMenu').toggleClass('collapsed');
});
$('#menuToggle').click(function() {
$('#floatingMenu').toggleClass('mobile-visible');
// Close menu when clicking outside
$(document).one('click', function(e) {
if (!$(e.target).closest('#floatingMenu, #menuToggle').length) {
$('#floatingMenu').removeClass('mobile-visible');
}
});
});
// Close menu with Escape key
$(document).keyup(function(e) {
if (e.key === "Escape") {
$('#floatingMenu').removeClass('mobile-visible');
}
});
// ===========================================
// 5. Back to Top Button
// ===========================================
$('.back-to-top-fixed a').click(function(e) {
e.preventDefault();
$('html, body').animate({scrollTop: 0}, 400, 'swing');
});
// ===========================================
// 6. Smooth Scrolling for Anchor Links
// ===========================================
if (CONFIG.smoothScroll) {
$('a[href^="#"]').not('.no-smooth').on('click', function(e) {
e.preventDefault();
var target = $(this.hash);
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top - 60
}, 500, 'swing', function() {
// Update URL hash without jumping
if (history.pushState) {
history.pushState(null, null, this.hash);
}
});
}
});
}
// ===========================================
// 7. Reading Time Estimator
// ===========================================
if (CONFIG.readingTime) {
var content = $('#mw-content-text').text();
var wordCount = content.split(/\s+/).length;
var readingTime = Math.ceil(wordCount / 200);
if (wordCount > 50) { // Only show for longer articles
$('#firstHeading').append(
'<span class="reading-time-badge" style="' +
'font-size: 14px; ' +
'font-weight: normal; ' +
'margin-left: 15px; ' +
'padding: 3px 10px; ' +
'background: linear-gradient(135deg, #FF6A00, #D93800); ' +
'color: white; ' +
'border-radius: 20px; ' +
'display: inline-block;' +
'">📖 ' + readingTime + ' min read</span>'
);
}
}
// ===========================================
// 8. Table of Contents Improvements
// ===========================================
if (CONFIG.tableOfContents && $('#toc').length) {
// Add sticky TOC toggle
$('#toc').before(
'<div id="toc-controls" style="margin-bottom: 10px;">' +
'<button id="toggle-toc" class="btn" style="' +
'background: linear-gradient(135deg, #FF6A00, #D93800); ' +
'color: white; ' +
'border: none; ' +
'padding: 5px 15px; ' +
'border-radius: 5px; ' +
'cursor: pointer;' +
'">Hide Table of Contents</button>' +
'</div>'
);
$('#toggle-toc').click(function() {
$('#toc ul').slideToggle(200);
$(this).text(function(i, text) {
return text === 'Hide Table of Contents' ?
'Show Table of Contents' : 'Hide Table of Contents';
});
});
// Add "Back to Top" links after each section
$('h2, h3').each(function() {
if ($(this).attr('id')) {
$(this).append(
' <a href="#top" class="section-top-link" style="' +
'font-size: 12px; ' +
'margin-left: 10px; ' +
'text-decoration: none; ' +
'opacity: 0.5; ' +
'transition: opacity 0.3s;' +
'">↑ top</a>'
);
$(this).find('.section-top-link').hover(
function() { $(this).css('opacity', '1'); },
function() { $(this).css('opacity', '0.5'); }
);
}
});
}
// ===========================================
// 9. Keyboard Navigation
// ===========================================
$(document).on('keydown', function(e) {
// Alt + Q - Toggle floating menu
if (e.altKey && e.key === 'q') {
e.preventDefault();
$('#floatingMenu').toggleClass('collapsed');
}
// Alt + T - Back to top
if (e.altKey && e.key === 't') {
e.preventDefault();
$('html, body').animate({scrollTop: 0}, 400);
}
// Alt + H - Go to Main Page
if (e.altKey && e.key === 'h') {
e.preventDefault();
window.location.href = '/index.php/Main_Page';
}
});
// ===========================================
// 10. Responsive Handling
// ===========================================
$(window).resize(function() {
if ($(window).width() > CONFIG.desktopBreakpoint) {
$('#floatingMenu').removeClass('mobile-visible');
$('#floatingMenu').css('right', '20px');
} else {
$('#floatingMenu').css('right', '');
}
});
// ===========================================
// 11. Page Load Performance
// ===========================================
// Lazy load images if any
$('img').each(function() {
var img = $(this);
var src = img.attr('src');
if (src && !img.hasClass('loaded')) {
img.on('load', function() {
$(this).addClass('loaded');
});
}
});
// ===========================================
// 12. Error Handling
// ===========================================
$(window).on('error', function(e) {
console.log('JavaScript error:', e.message);
});
});
// ===========================================
// 13. Sticky Header CSS (add to your CSS file)
// ===========================================
/*
.sticky-header {
position: fixed !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
z-index: 1000 !important;
background: white !important;
box-shadow: 0 2px 10px rgba(0,0,0,0.1) !important;
animation: slideDown 0.3s ease;
}
@keyframes slideDown {
from { transform: translateY(-100%); }
to { transform: translateY(0); }
}
*/
