Updated the core site style and removed AI fuzz.
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initTheme();
|
||||
initFooterYear();
|
||||
initMobileMenu();
|
||||
fetchPageData();
|
||||
});
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Theme / Dark Mode Management */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
function initTheme() {
|
||||
const isDarkStored = localStorage.theme === 'dark';
|
||||
const noThemeStored = !('theme' in localStorage);
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
if (isDarkStored || (noThemeStored && prefersDark)) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
|
||||
updateThemeUI();
|
||||
|
||||
document.querySelectorAll('.theme-toggle').forEach(button => {
|
||||
button.addEventListener('click', toggleDarkMode);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleDarkMode() {
|
||||
const isDark = document.documentElement.classList.toggle('dark');
|
||||
localStorage.theme = isDark ? 'dark' : 'light';
|
||||
updateThemeUI();
|
||||
}
|
||||
|
||||
function updateThemeUI() {
|
||||
const isDark = document.documentElement.classList.contains('dark');
|
||||
|
||||
document.querySelectorAll('.icon-sun').forEach(el => el.classList.toggle('hidden', !isDark));
|
||||
document.querySelectorAll('.icon-moon').forEach(el => el.classList.toggle('hidden', isDark));
|
||||
|
||||
document.querySelectorAll('.theme-text').forEach(el => {
|
||||
el.textContent = isDark ? '☀️ Light Mode' : '🌙 Dark Mode';
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Footer Year Handler */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
function initFooterYear() {
|
||||
const yearEl = document.getElementById('current-year');
|
||||
if (yearEl) {
|
||||
yearEl.textContent = new Date().getFullYear();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Mobile Menu Toggle */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
function initMobileMenu() {
|
||||
const menuToggleBtn = document.getElementById('menu-toggle');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
const iconHamburger = document.getElementById('icon-hamburger');
|
||||
const iconClose = document.getElementById('icon-close');
|
||||
|
||||
if (!menuToggleBtn || !mobileMenu) return;
|
||||
|
||||
menuToggleBtn.setAttribute('aria-expanded', 'false');
|
||||
|
||||
menuToggleBtn.addEventListener('click', () => {
|
||||
const isHidden = mobileMenu.classList.toggle('hidden');
|
||||
menuToggleBtn.setAttribute('aria-expanded', String(!isHidden));
|
||||
iconHamburger.classList.toggle('hidden', !isHidden);
|
||||
iconClose.classList.toggle('hidden', isHidden);
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Async Data Fetching (Pages, Banner & Exam Schedule) */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
async function fetchPageData() {
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
// 1. Fetch Banner Data
|
||||
try {
|
||||
const bannerResp = await fetch(`/assets/banner.json?t=${Date.now()}`);
|
||||
if (bannerResp.ok) {
|
||||
const banner = await bannerResp.json();
|
||||
if (banner && banner.title && banner.content) {
|
||||
document.getElementById('banner-title').textContent = banner.title;
|
||||
document.getElementById('banner-content').textContent = banner.content;
|
||||
document.getElementById('banner').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load banner data:', err);
|
||||
}
|
||||
|
||||
// 2. Fetch Navigation Links
|
||||
try {
|
||||
const navResp = await fetch('/assets/pages.json');
|
||||
if (navResp.ok) {
|
||||
const pages = await navResp.json();
|
||||
renderNavigation(pages, currentPath);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load navigation data:', err);
|
||||
}
|
||||
|
||||
// 3. Fetch Exam Schedule (only runs if the #exams-list element exists)
|
||||
const examsContainer = document.getElementById('exams-list');
|
||||
if (examsContainer) {
|
||||
try {
|
||||
const examResp = await fetch(`/assets/exams.json?t=${Date.now()}`);
|
||||
if (examResp.ok) {
|
||||
const exams = await examResp.json();
|
||||
renderExams(exams, examsContainer);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load exam data:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Fetch Net Check-In Data (only runs on pages containing #callsigns-list or #weekly-list)
|
||||
const callsignsContainer = document.getElementById('callsigns-list');
|
||||
const weeklyContainer = document.getElementById('weekly-list');
|
||||
|
||||
if (callsignsContainer || weeklyContainer) {
|
||||
try {
|
||||
const netResp = await fetch('/net/net.json');
|
||||
if (netResp.ok) {
|
||||
const data = await netResp.json();
|
||||
renderNetStats(data, callsignsContainer, weeklyContainer);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load net statistics data:', err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function renderNavigation(pages, currentPath) {
|
||||
const desktopContainer = document.getElementById('desktop-links');
|
||||
const mobileContainer = document.getElementById('mobile-links');
|
||||
|
||||
if (!desktopContainer || !mobileContainer) return;
|
||||
|
||||
desktopContainer.innerHTML = '';
|
||||
mobileContainer.innerHTML = '';
|
||||
|
||||
pages.forEach(page => {
|
||||
const desktopLink = document.createElement('a');
|
||||
desktopLink.href = page.path;
|
||||
desktopLink.textContent = page.name;
|
||||
if (currentPath === page.path) desktopLink.classList.add('active');
|
||||
desktopContainer.appendChild(desktopLink);
|
||||
|
||||
const mobileLink = document.createElement('a');
|
||||
mobileLink.href = page.path;
|
||||
mobileLink.textContent = page.name;
|
||||
if (currentPath === page.path) mobileLink.classList.add('active');
|
||||
mobileContainer.appendChild(mobileLink);
|
||||
});
|
||||
}
|
||||
|
||||
function renderExams(exams, container) {
|
||||
container.innerHTML = '';
|
||||
|
||||
if (Array.isArray(exams) && exams.length > 0) {
|
||||
exams.forEach(exam => {
|
||||
const li = document.createElement('li');
|
||||
li.append(`${exam.date}, ${exam.time} – ${exam.location} – `);
|
||||
const link = document.createElement('a');
|
||||
link.href = exam.register;
|
||||
link.className = 'link';
|
||||
link.target = '_blank';
|
||||
link.rel = 'noopener';
|
||||
link.textContent = 'Register here';
|
||||
li.appendChild(link);
|
||||
container.appendChild(li);
|
||||
});
|
||||
} else {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = "We don't have any sessions scheduled right now, but if you're ready to test let us know and we'll set one up!";
|
||||
container.appendChild(li);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user