Common.js: Difference between revisions
From Dune Awakening DB
mNo edit summary Tag: Reverted |
mNo edit summary |
||
| (43 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
/* ======================================== | /* ======================================== | ||
MediaWiki:Common.js - Fixed Header Spacing | MediaWiki:Common.js - Fixed Header Spacing | ||
FIXED VERSION - Addresses all positioning issues | |||
======================================== */ | ======================================== */ | ||
/* ░ MOBILE DISCLAIMER BANNER ░ */ | |||
$( function () { | |||
if ( window.innerWidth > 768 ) return; // desktop? abort. | |||
// already injected? abort. | |||
if ( $('#mobile-disclaimer').length ) return; | |||
// Build & inject | |||
const $banner = $( '<div>', { | |||
id: 'mobile-disclaimer', | |||
html: 'Heads-up: this section is optimised for desktop. Smaller layouts are experimental 👀' | |||
}); | |||
// insert right after the site header / before main content. | |||
// Adjust selector to your skin; Vector uses #content, Timeless uses #mw-site. | |||
$( '#mw-content-text' ).prepend( $banner ); | |||
// If you prefer it at absolute top, use $('body').prepend( $banner ); | |||
}); | |||
/* util: "Fabricator Basics" → "fabricator-basics" */ | |||
function makeSlug(str){ | |||
return str.toLowerCase().trim() | |||
.replace(/[^\\w\\s-]/g,'') // drop punctuation | |||
.replace(/\\s+/g,'-'); // spaces → dashes | |||
} | |||
$(document).ready(function() { | $(document).ready(function() { | ||
// FIXED: Check if page has breadcrumb navigation | |||
var hasBreadcrumb = $('.dune-breadcrumb-nav').length > 0; | |||
if (hasBreadcrumb) { | |||
$('body').addClass('has-breadcrumb'); | |||
} | |||
// HEADER FIX - Wait for page to load then force header | // HEADER FIX - Wait for page to load then force header | ||
setTimeout(function() { | setTimeout(function() { | ||
| Line 11: | Line 48: | ||
// Hide the page title and extra elements completely | // Hide the page title and extra elements completely | ||
$('.firstHeading, h1.title, .mw-page-title-main, #firstHeading, #tagline, h3#tagline, #contentSub, .mw-content-subtitle').remove(); | $('.firstHeading, h1.title, .mw-page-title-main, #firstHeading, #tagline, h3#tagline, #contentSub, .mw-content-subtitle').remove(); | ||
// Remove any MediaWiki notices that might appear | |||
$('#siteNotice, .mw-indicators, .printfooter, .catlinks').remove(); | |||
// Create the navigation bar HTML with inline styles | // Create the navigation bar HTML with inline styles | ||
var headerHTML = ` | var headerHTML = ` | ||
<div id="dune-header" style="position: fixed; top: 0; left: 0; right: 0; height: 60px; background: linear-gradient(180deg, rgba(20, 18, 28, 0.95) 0%, rgba(10, 8, 16, 0.98) 100%); border-bottom: 3px solid rgba(252, 231, 200, 0.4); box-shadow: 0 2px 20px rgba(0,0,0,0.8); z-index: 99999; display: flex; align-items: center;"> | <div id="dune-header" style="position: fixed; top: 0; left: 0; right: 0; height: 60px; background: linear-gradient(180deg, rgba(20, 18, 28, 0.95) 0%, rgba(10, 8, 16, 0.98) 100%); border-bottom: 3px solid rgba(252, 231, 200, 0.4); box-shadow: 0 2px 20px rgba(0,0,0,0.8); z-index: 99999; display: flex; align-items: center;"> | ||
<div | <div style="width: 100%; max-width: 1600px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; height: 100%;"> | ||
<a href="/wiki/Main_Page | <a href="/wiki/Main_Page" style="font-family: 'Orbitron', sans-serif; font-size: 22px; color: #fce7c8; text-transform: uppercase; letter-spacing: 3px; font-weight: 700; text-shadow: 0 0 15px rgba(252, 231, 200, 0.4); text-decoration: none; white-space: nowrap;">DUNE DB</a> | ||
<nav | <nav style="display: flex; gap: 0; margin: 0 20px; height: 100%;"> | ||
<a href=" | <a href="/Items" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-left: 1px solid rgba(252, 231, 200, 0.1); border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">◇ Items</a> | ||
<a href=" | <a href="/Crafting" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">⚒ Crafting</a> | ||
<a href=" | <a href="/Building" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">⌂ Building</a> | ||
<a href=" | <a href="/Tech_Tree" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">⬢ Tech Tree</a> | ||
<a href=" | <a href="/Journeys" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">➤ Journeys</a> | ||
<a href=" | <a href="/Skills" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">★ Skills</a> | ||
<a href=" | <a href="/Map" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">🗺 Map</a> | ||
</nav> | </nav> | ||
<div | <div style="display: flex; align-items: center;"> | ||
<form action="/index.php" method="get" style="display: flex; align-items: center; gap: 0;"> | <form action="/index.php" method="get" style="display: flex; align-items: center; gap: 0; height: 38px;"> | ||
<input type="search" name="search" placeholder="Search wiki..." style="background: rgba(0, 0, 2, 0.8); border: 2px solid rgba(252, 231, 200, 0.3); border-radius: 0; color: #fce7c8; padding: | <input type="search" name="search" placeholder="Search wiki..." style="background: rgba(0, 0, 2, 0.8); border: 2px solid rgba(252, 231, 200, 0.3); border-radius: 0; color: #fce7c8; padding: 0 12px; width: 200px; font-size: 13px; font-family: 'Rajdhani', sans-serif; transition: all 0.3s ease; outline: none; height: 38px; box-sizing: border-box; margin: 0; vertical-align: middle;" onfocus="this.style.borderColor='#fce7c8'; this.style.boxShadow='0 0 10px rgba(252, 231, 200, 0.3)'; this.style.width='250px';" onblur="this.style.borderColor='rgba(252, 231, 200, 0.3)'; this.style.boxShadow='none'; this.style.width='200px';"> | ||
<button type="submit" style="background: rgba(252, 231, 200, 0.1); border: 2px solid rgba(252, 231, 200, 0.3); border-left: none; color: #fce7c8; padding: | <button type="submit" style="background: rgba(252, 231, 200, 0.1); border: 2px solid rgba(252, 231, 200, 0.3); border-left: none; color: #fce7c8; padding: 0 12px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; height: 38px; box-sizing: border-box; margin: 0; vertical-align: middle; display: flex; align-items: center; justify-content: center;" onmouseover="this.style.background='rgba(252, 231, 200, 0.2)'; this.style.borderColor='#fce7c8';" onmouseout="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.borderColor='rgba(252, 231, 200, 0.3)';"><span>🔍</span></button> | ||
</form> | </form> | ||
</div> | </div> | ||
| Line 38: | Line 78: | ||
`; | `; | ||
$('body').prepend(headerHTML); | // Check if header already exists to avoid duplicates | ||
if ($('#dune-header').length === 0) { | |||
$('body').prepend(headerHTML); | |||
} | |||
// CRITICAL: Force proper spacing | // CRITICAL: Force proper spacing | ||
$('body').css({ | $('body').css({ | ||
'padding-top': '60px', | 'padding-top': '60px', | ||
'margin-top': '0' | 'margin-top': '0', | ||
'overflow-y': 'auto', | |||
'height': 'auto' | |||
}); | }); | ||
// | // FIXED: Different spacing for pages with/without breadcrumb | ||
if (hasBreadcrumb) { | |||
// Pages with breadcrumb - content starts immediately after header | |||
$('#content, .mw-body, #mw-content-text, .mw-body-content, .mw-parser-output, #main-section, .main-section, #page-content').css({ | |||
'padding-top': '0', | |||
'margin-top': '0' | |||
}); | |||
// Breadcrumb should have proper spacing from header | |||
$('.dune-breadcrumb-nav').css({ | |||
'margin-top': '20px', | |||
'margin-bottom': '20px' | |||
}); | |||
} else { | |||
// Pages without breadcrumb - add padding to content | |||
$('#content, .mw-body, #mw-content-text, .mw-body-content, .mw-parser-output, #main-section, .main-section, #page-content').css({ | |||
'padding-top': '20px', | |||
'margin-top': '0' | |||
}); | |||
} | |||
// Force first element to start at top | // Force first element to start at top (unless it's breadcrumb) | ||
$('.mw-parser-output > *:first-child, .mw-body-content > *:first-child').css({ | $('.mw-parser-output > *:first-child:not(.dune-breadcrumb-nav), .mw-body-content > *:first-child:not(.dune-breadcrumb-nav)').css({ | ||
'margin-top': '0', | 'margin-top': '0', | ||
'padding-top': '0' | 'padding-top': '0' | ||
| Line 74: | Line 127: | ||
}); | }); | ||
// Handle Actions button | // Handle Actions button positioning | ||
$('#p-cactions').css({ | $('#p-cactions').css({ | ||
'margin | 'position': 'fixed', | ||
'padding | 'top': '11px', | ||
'right': '20px', | |||
'z-index': '100001', | |||
'margin': '0', | |||
'padding': '0', | |||
'height': '38px' | |||
}); | }); | ||
| Line 85: | Line 143: | ||
'margin-top': '0' | 'margin-top': '0' | ||
}); | }); | ||
// FIXED: Ensure page content can scroll | |||
$('#content').css({ | |||
'min-height': 'calc(100vh - 60px)', | |||
'position': 'relative', | |||
'z-index': '1' | |||
}); | |||
// Remove any floating MediaWiki elements | |||
$('.mw-jump-link, .mw-redirectedfrom, #siteNotice').remove(); | |||
}, 100); | }, 100); | ||
}); | }); | ||
/* ===== RADIAL MENU CODE ===== */ | |||
/* ===== | |||
function waitForRadialData(callback, attempts = 0) { | function waitForRadialData(callback, attempts = 0) { | ||
const dataTag = document.getElementById('radialMenuData'); | const dataTag = document.getElementById('radialMenuData'); | ||
| Line 404: | Line 413: | ||
radial.classList.toggle('is-fixed', window.scrollY > y); | radial.classList.toggle('is-fixed', window.scrollY > y); | ||
}); | }); | ||
}); | |||
/** | |||
* Resource Page Module Loader | |||
*/ | |||
$(function() { | |||
// Only on resource pages | |||
if ($('.crafting-section, .recipe-table, [class*="crafted-"]').length > 0) { | |||
// Load dependencies first | |||
mw.loader.using(['jquery', 'mediawiki.api', 'mediawiki.util'], function() { | |||
// Load resource page module | |||
$.getScript('/index.php?title=MediaWiki:ResourcePage.js&action=raw&ctype=text/javascript') | |||
.done(function() { | |||
console.log('Resource page module loaded'); | |||
}) | |||
.fail(function() { | |||
console.error('Failed to load resource page module'); | |||
}); | |||
}); | |||
} | |||
}); | |||
$(function () { | |||
const $drop = $('#drop'); | |||
const $menu = $('#drop1'); | |||
if ($drop.length && $menu.length) { | |||
// Move Actions button into the footer visually | |||
$('#footer').append($drop); | |||
$('#footer').append($menu); | |||
// Style the button like a footer element | |||
$drop.css({ | |||
position: 'relative', | |||
display: 'inline-block', | |||
marginTop: '12px', | |||
background: 'rgba(252,231,200,0.08)', | |||
border: '1px solid rgba(252,231,200,0.2)', | |||
color: '#fce7c8', | |||
fontFamily: 'Rajdhani, sans-serif', | |||
padding: '6px 12px', | |||
boxShadow: '0 0 6px rgba(0,0,0,0.3)', | |||
cursor: 'pointer' | |||
}); | |||
$drop.hover( | |||
() => $drop.css({ background: 'rgba(252,231,200,0.15)', color: '#fff' }), | |||
() => $drop.css({ background: 'rgba(252,231,200,0.08)', color: '#fce7c8' }) | |||
); | |||
// Ensure dropdown menu opens below and is styled cleanly | |||
$menu.css({ | |||
position: 'absolute', | |||
top: '100%', | |||
right: '0', | |||
zIndex: '9999', | |||
background: '#1a1a1a', | |||
boxShadow: '0 2px 6px rgba(0,0,0,0.5)', | |||
marginTop: '4px' | |||
}); | |||
} | |||
// Footer message logic | |||
if (!$('#custom-footer-note').length) { | |||
const $customLine = $('<div>', { | |||
id: 'custom-footer-note', | |||
html: `This is an experimental solo project exploring what’s possible in gaming UI and data experiences. Things may break—thank you for being part of the push forward.<br> | |||
<a href="${mw.util.getUrl('Disclaimer')}" class="footer-link">Legal & Disclaimer</a>` | |||
}); | |||
$('#footer').prepend($customLine); | |||
$('#footer-left').hide(); | |||
} | |||
}); | }); | ||
Latest revision as of 01:45, 4 June 2025
/* ========================================
MediaWiki:Common.js - Fixed Header Spacing
FIXED VERSION - Addresses all positioning issues
======================================== */
/* ░ MOBILE DISCLAIMER BANNER ░ */
$( function () {
if ( window.innerWidth > 768 ) return; // desktop? abort.
// already injected? abort.
if ( $('#mobile-disclaimer').length ) return;
// Build & inject
const $banner = $( '<div>', {
id: 'mobile-disclaimer',
html: 'Heads-up: this section is optimised for desktop. Smaller layouts are experimental 👀'
});
// insert right after the site header / before main content.
// Adjust selector to your skin; Vector uses #content, Timeless uses #mw-site.
$( '#mw-content-text' ).prepend( $banner );
// If you prefer it at absolute top, use $('body').prepend( $banner );
});
/* util: "Fabricator Basics" → "fabricator-basics" */
function makeSlug(str){
return str.toLowerCase().trim()
.replace(/[^\\w\\s-]/g,'') // drop punctuation
.replace(/\\s+/g,'-'); // spaces → dashes
}
$(document).ready(function() {
// FIXED: Check if page has breadcrumb navigation
var hasBreadcrumb = $('.dune-breadcrumb-nav').length > 0;
if (hasBreadcrumb) {
$('body').addClass('has-breadcrumb');
}
// HEADER FIX - Wait for page to load then force header
setTimeout(function() {
// Remove ALL existing headers and nav attempts
$('.mw-header, #mw-header-container, nav.tab-bar, .tab-bar').remove();
// Hide the page title and extra elements completely
$('.firstHeading, h1.title, .mw-page-title-main, #firstHeading, #tagline, h3#tagline, #contentSub, .mw-content-subtitle').remove();
// Remove any MediaWiki notices that might appear
$('#siteNotice, .mw-indicators, .printfooter, .catlinks').remove();
// Create the navigation bar HTML with inline styles
var headerHTML = `
<div id="dune-header" style="position: fixed; top: 0; left: 0; right: 0; height: 60px; background: linear-gradient(180deg, rgba(20, 18, 28, 0.95) 0%, rgba(10, 8, 16, 0.98) 100%); border-bottom: 3px solid rgba(252, 231, 200, 0.4); box-shadow: 0 2px 20px rgba(0,0,0,0.8); z-index: 99999; display: flex; align-items: center;">
<div style="width: 100%; max-width: 1600px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; height: 100%;">
<a href="/wiki/Main_Page" style="font-family: 'Orbitron', sans-serif; font-size: 22px; color: #fce7c8; text-transform: uppercase; letter-spacing: 3px; font-weight: 700; text-shadow: 0 0 15px rgba(252, 231, 200, 0.4); text-decoration: none; white-space: nowrap;">DUNE DB</a>
<nav style="display: flex; gap: 0; margin: 0 20px; height: 100%;">
<a href="/Items" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-left: 1px solid rgba(252, 231, 200, 0.1); border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">◇ Items</a>
<a href="/Crafting" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">⚒ Crafting</a>
<a href="/Building" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">⌂ Building</a>
<a href="/Tech_Tree" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">⬢ Tech Tree</a>
<a href="/Journeys" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">➤ Journeys</a>
<a href="/Skills" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">★ Skills</a>
<a href="/Map" style="display: flex; align-items: center; padding: 0 18px; height: 100%; color: rgba(252, 231, 200, 0.8); font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; text-decoration: none; border-right: 1px solid rgba(252, 231, 200, 0.1); transition: all 0.3s ease; background: transparent;" onmouseover="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.color='#fce7c8';" onmouseout="this.style.background='transparent'; this.style.color='rgba(252, 231, 200, 0.8)';">🗺 Map</a>
</nav>
<div style="display: flex; align-items: center;">
<form action="/index.php" method="get" style="display: flex; align-items: center; gap: 0; height: 38px;">
<input type="search" name="search" placeholder="Search wiki..." style="background: rgba(0, 0, 2, 0.8); border: 2px solid rgba(252, 231, 200, 0.3); border-radius: 0; color: #fce7c8; padding: 0 12px; width: 200px; font-size: 13px; font-family: 'Rajdhani', sans-serif; transition: all 0.3s ease; outline: none; height: 38px; box-sizing: border-box; margin: 0; vertical-align: middle;" onfocus="this.style.borderColor='#fce7c8'; this.style.boxShadow='0 0 10px rgba(252, 231, 200, 0.3)'; this.style.width='250px';" onblur="this.style.borderColor='rgba(252, 231, 200, 0.3)'; this.style.boxShadow='none'; this.style.width='200px';">
<button type="submit" style="background: rgba(252, 231, 200, 0.1); border: 2px solid rgba(252, 231, 200, 0.3); border-left: none; color: #fce7c8; padding: 0 12px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; height: 38px; box-sizing: border-box; margin: 0; vertical-align: middle; display: flex; align-items: center; justify-content: center;" onmouseover="this.style.background='rgba(252, 231, 200, 0.2)'; this.style.borderColor='#fce7c8';" onmouseout="this.style.background='rgba(252, 231, 200, 0.1)'; this.style.borderColor='rgba(252, 231, 200, 0.3)';"><span>🔍</span></button>
</form>
</div>
</div>
</div>
`;
// Check if header already exists to avoid duplicates
if ($('#dune-header').length === 0) {
$('body').prepend(headerHTML);
}
// CRITICAL: Force proper spacing
$('body').css({
'padding-top': '60px',
'margin-top': '0',
'overflow-y': 'auto',
'height': 'auto'
});
// FIXED: Different spacing for pages with/without breadcrumb
if (hasBreadcrumb) {
// Pages with breadcrumb - content starts immediately after header
$('#content, .mw-body, #mw-content-text, .mw-body-content, .mw-parser-output, #main-section, .main-section, #page-content').css({
'padding-top': '0',
'margin-top': '0'
});
// Breadcrumb should have proper spacing from header
$('.dune-breadcrumb-nav').css({
'margin-top': '20px',
'margin-bottom': '20px'
});
} else {
// Pages without breadcrumb - add padding to content
$('#content, .mw-body, #mw-content-text, .mw-body-content, .mw-parser-output, #main-section, .main-section, #page-content').css({
'padding-top': '20px',
'margin-top': '0'
});
}
// Force first element to start at top (unless it's breadcrumb)
$('.mw-parser-output > *:first-child:not(.dune-breadcrumb-nav), .mw-body-content > *:first-child:not(.dune-breadcrumb-nav)').css({
'margin-top': '0',
'padding-top': '0'
});
// Remove sidebar space
$('#sidebar, .columns.large-2.medium-3').css('display', 'none');
$('#page-content, .columns.large-10.medium-9').css({
'width': '100%',
'max-width': '100%',
'margin': '0',
'padding': '0'
});
// Handle Actions button positioning
$('#p-cactions').css({
'position': 'fixed',
'top': '11px',
'right': '20px',
'z-index': '100001',
'margin': '0',
'padding': '0',
'height': '38px'
});
// Remove spacing from all column wrappers
$('.row > .columns').css({
'padding-top': '0',
'margin-top': '0'
});
// FIXED: Ensure page content can scroll
$('#content').css({
'min-height': 'calc(100vh - 60px)',
'position': 'relative',
'z-index': '1'
});
// Remove any floating MediaWiki elements
$('.mw-jump-link, .mw-redirectedfrom, #siteNotice').remove();
}, 100);
});
/* ===== RADIAL MENU CODE ===== */
function waitForRadialData(callback, attempts = 0) {
const dataTag = document.getElementById('radialMenuData');
if (dataTag) {
try {
const menuItems = JSON.parse(dataTag.innerText || dataTag.textContent);
console.log("✅ Loaded radialMenuData:", menuItems);
callback(menuItems);
} catch (e) {
console.error("❌ Failed to parse radialMenuData", e);
}
} else if (attempts < 20) {
setTimeout(() => waitForRadialData(callback, attempts + 1), 100);
} else {
console.warn("⚠️ radialMenuData tag not found after timeout.");
}
}
$(document).ready(function () {
waitForRadialData(function (menuItems) {
const isMobile = () => window.innerWidth <= 768;
let radialItemsHTML = '';
menuItems.forEach((item, index) => {
const id = item.category.toLowerCase().replace(/\s+/g, '-');
item.id = id;
radialItemsHTML += `
<div class="dune-radial-item-container ${item.position}">
<a data-id="${id}" class="dune-radial-item">
<img src="${item.icon}" alt="${item.name}" class="dune-radial-icon">
<span class="dune-radial-tooltip">${item.name}</span>
</a>
</div>
`;
});
const centerButtonHTML = `
<a href="https://dunedb.com/Main_Page" class="dune-radial-center">
<img src="https://dunedb.com/images/9/99/HomeNavIcon.png" alt="Home" class="dune-radial-icon">
<span class="dune-radial-tooltip">Main Page</span>
</a>
`;
const radialMenuHTML = `
<div id="duneRadialMenu" class="dune-radial-menu">
<div class="dune-radial-background">
<div class="dune-radial-circle outer"></div>
<div class="dune-radial-circle middle"></div>
<div class="dune-radial-circle inner"></div>
</div>
${centerButtonHTML}
${radialItemsHTML}
</div>
<div id="duneRadialOverlay" class="dune-radial-overlay"></div>
`;
const subcategoryContainerHTML = `<div id="duneSubcategoryContainer" class="dune-subcategory-container"></div>`;
$('body').append(radialMenuHTML);
$('body').append(subcategoryContainerHTML);
if (isMobile()) {
$('#duneRadialMenu').addClass('mobile-grid');
}
const showSubcategories = (itemId, event) => {
const item = menuItems.find(i => i.id === itemId);
if (!item || !item.subcategories) return;
$('.dune-radial-item').removeClass('selected');
$(`.dune-radial-item[data-id="${itemId}"]`).addClass('selected');
let subcategoryHTML = `
<div class="dune-subcategory-header">
<img src="${item.icon}" alt="${item.name}" class="dune-subcategory-icon">
<span>${item.name}</span>
</div>
<div class="dune-subcategory-items">
`;
item.subcategories.forEach((sub, index) => {
subcategoryHTML += `
<a href="${sub.url}" class="dune-subcategory-item" style="--item-index: ${index}">
<span class="dune-subcategory-name">${sub.name}</span>
</a>
`;
});
subcategoryHTML += `
</div>
<div class="dune-subcategory-footer">
<a href="${item.url}" class="dune-subcategory-all">View All ${item.name}</a>
</div>
`;
const $subcategoryContainer = $('#duneSubcategoryContainer');
$subcategoryContainer.html(subcategoryHTML);
$subcategoryContainer.removeClass((index, className) => {
return (className.match(/from-\S+/g) || []).join(' ');
});
$subcategoryContainer.addClass(`from-${item.position}`);
$subcategoryContainer.addClass('active');
event.stopPropagation();
};
const hideSubcategories = () => {
$('#duneSubcategoryContainer').removeClass('active');
$('.dune-radial-item').removeClass('selected');
};
const toggleRadialMenu = () => {
if ($('#duneRadialMenu').hasClass('active')) {
hideSubcategories();
$('#duneRadialMenu').removeClass('active');
$('#duneRadialOverlay').removeClass('active');
} else {
$('#duneRadialMenu').addClass('active');
$('#duneRadialOverlay').addClass('active');
$('.dune-radial-item-container').each(function (index) {
const $item = $(this);
setTimeout(() => {
$item.addClass('animated');
}, index * 50);
});
setTimeout(() => {
$('.dune-radial-center').addClass('animated');
}, menuItems.length * 50);
}
};
$(document).on('click', '#duneLogoBtn, #menuRadialTrigger img', function (e) {
console.log("✅ Radial trigger clicked");
e.preventDefault();
e.stopPropagation();
toggleRadialMenu();
});
$(document).on('click', '.dune-radial-item', function (e) {
e.preventDefault();
e.stopPropagation();
const itemId = $(this).data('id');
if ($(this).hasClass('selected')) {
hideSubcategories();
} else {
showSubcategories(itemId, e);
}
});
$(document).on('click', '#duneRadialOverlay', function () {
hideSubcategories();
$('#duneRadialMenu').removeClass('active');
$('#duneRadialOverlay').removeClass('active');
});
$(document).on('click', 'li.name.logo a[href="/Main_Page"]', function (e) {
e.preventDefault();
toggleRadialMenu();
});
$(document).on('keydown', function (e) {
if (e.key === 'Escape') {
if ($('#duneSubcategoryContainer').hasClass('active')) {
hideSubcategories();
} else if ($('#duneRadialMenu').hasClass('active')) {
$('#duneRadialMenu').removeClass('active');
$('#duneRadialOverlay').removeClass('active');
}
}
});
$(window).on('resize', function () {
if (isMobile()) {
$('#duneRadialMenu').addClass('mobile-grid');
} else {
$('#duneRadialMenu').removeClass('mobile-grid');
}
});
});
});
/* Used-In dynamic filters & search */
mw.hook( 'wikipage.content' ).add( function ( $content ) {
const $holder = $content.find( '#usedInFilterHolder' );
const $table = $content.find( '#usedInTable' );
if ( !$holder.length || !$table.length ) return;
const rowsData = [];
const stations = new Set();
const types = new Set();
$table.find( 'tbody tr' ).each( function () {
const $tds = $( this ).children( 'td' );
const output = $tds.eq( 0 ).text().trim();
const type = $tds.eq( 1 ).text().trim();
const station = $tds.last().text().trim();
rowsData.push( { tr: this, output, type, station } );
stations.add( station );
types.add( type );
} );
const makeSel = ( id, label, opts ) => {
const $sel = $( '<select>', { id, class: 'game-button', css:{margin:'6px 4px 6px 0'} } )
.append( $( '<option>', { value:'', text:label } ) );
opts.forEach( o => $sel.append( $( '<option>', { value:o, text:o } ) ) );
return $sel;
};
const $stationSel = makeSel( 'filterStation', 'All Stations', [ ...stations ].sort() );
const $typeSel = makeSel( 'filterType', 'All Types', [ ...types ].sort() );
const $search = $( '<input>', {
type:'text',
placeholder:'Search…',
css:{ margin:'6px 0', padding:'4px', width:'140px',
'background':'#111', color:'#fff', border:'1px solid #555' }
} );
$holder.append( $stationSel, $typeSel, $search );
function applyFilters() {
const sVal = $stationSel.val();
const tVal = $typeSel.val();
const q = $search.val().toLowerCase();
rowsData.forEach( ({ tr, output, type, station }) => {
const show =
(!sVal || station === sVal) &&
(!tVal || type === tVal) &&
(!q || output.toLowerCase().includes( q ));
tr.style.display = show ? '' : 'none';
} );
}
$stationSel.on( 'change', applyFilters );
$typeSel .on( 'change', applyFilters );
$search .on( 'input', applyFilters );
} );
/* Lazy-load background image Blur */
document.addEventListener('DOMContentLoaded', () => {
const hero = document.querySelector('.dune-hero');
if (hero && !hero.style.backgroundImage) {
hero.style.backgroundImage =
'url(/images/7/70/Arrakis_dunes.jpg?2025)';
}
const radial = document.querySelector('.radial-menu-wrapper');
if (!radial) return;
const y = radial.offsetTop;
window.addEventListener('scroll', () => {
radial.classList.toggle('is-fixed', window.scrollY > y);
});
});
/**
* Resource Page Module Loader
*/
$(function() {
// Only on resource pages
if ($('.crafting-section, .recipe-table, [class*="crafted-"]').length > 0) {
// Load dependencies first
mw.loader.using(['jquery', 'mediawiki.api', 'mediawiki.util'], function() {
// Load resource page module
$.getScript('/index.php?title=MediaWiki:ResourcePage.js&action=raw&ctype=text/javascript')
.done(function() {
console.log('Resource page module loaded');
})
.fail(function() {
console.error('Failed to load resource page module');
});
});
}
});
$(function () {
const $drop = $('#drop');
const $menu = $('#drop1');
if ($drop.length && $menu.length) {
// Move Actions button into the footer visually
$('#footer').append($drop);
$('#footer').append($menu);
// Style the button like a footer element
$drop.css({
position: 'relative',
display: 'inline-block',
marginTop: '12px',
background: 'rgba(252,231,200,0.08)',
border: '1px solid rgba(252,231,200,0.2)',
color: '#fce7c8',
fontFamily: 'Rajdhani, sans-serif',
padding: '6px 12px',
boxShadow: '0 0 6px rgba(0,0,0,0.3)',
cursor: 'pointer'
});
$drop.hover(
() => $drop.css({ background: 'rgba(252,231,200,0.15)', color: '#fff' }),
() => $drop.css({ background: 'rgba(252,231,200,0.08)', color: '#fce7c8' })
);
// Ensure dropdown menu opens below and is styled cleanly
$menu.css({
position: 'absolute',
top: '100%',
right: '0',
zIndex: '9999',
background: '#1a1a1a',
boxShadow: '0 2px 6px rgba(0,0,0,0.5)',
marginTop: '4px'
});
}
// Footer message logic
if (!$('#custom-footer-note').length) {
const $customLine = $('<div>', {
id: 'custom-footer-note',
html: `This is an experimental solo project exploring what’s possible in gaming UI and data experiences. Things may break—thank you for being part of the push forward.<br>
<a href="${mw.util.getUrl('Disclaimer')}" class="footer-link">Legal & Disclaimer</a>`
});
$('#footer').prepend($customLine);
$('#footer-left').hide();
}
});