/**
* Theme loading, dynamic stylesheet injection, and page loader transitions.
*/
import { queryEl, queryAll } from './dom-utils.js';
export const VALID_THEMES = ['theme_dark', 'theme_light'];
export const DEFAULT_THEME = 'theme_dark';
/**
* Fades out and hides the page loader element.
* @param {HTMLElement|null} [loaderEl=null] - Optional loader element reference.
*/
export function fadeOutLoader(loaderEl = null) {
const loader = loaderEl || queryEl('.page-loader');
if (loader) {
loader.style.opacity = '0';
loader.addEventListener('transitionend', () => {
loader.style.display = 'none';
}, { once: true });
}
}
/**
* Applies a theme by swapping dynamic stylesheet link tags and updating highlight.js theme if specified.
* @param {string} theme - The theme identifier ('theme_dark' | 'theme_light').
* @param {boolean} [includeHljs=true] - Whether to also swap the Highlight.js theme stylesheet.
* @param {Function} [onComplete] - Optional callback once theme stylesheets finish loading.
*/
export function applyTheme(theme, includeHljs = true, onComplete = null) {
const activeTheme = VALID_THEMES.includes(theme) ? theme : DEFAULT_THEME;
const loader = queryEl('.page-loader');
const requiredHrefs = [
'dynamic.php?s=base&t=' + activeTheme,
'dynamic.php?s=style&t=' + activeTheme
];
if (includeHljs) {
const hljsTheme = activeTheme.includes('light')
? 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css'
: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/dark.min.css';
requiredHrefs.unshift(hljsTheme);
}
const existingLinks = queryAll('link[rel="stylesheet"]');
const currentHrefs = existingLinks.map(link => link.getAttribute('href'));
const isAlreadyApplied = requiredHrefs.every(href => currentHrefs.includes(href));
if (isAlreadyApplied) {
fadeOutLoader(loader);
if (typeof onComplete === 'function') onComplete(activeTheme);
return;
}
if (loader) {
loader.style.display = 'block';
loader.style.opacity = '0';
// Force reflow for transition
void loader.offsetHeight;
loader.style.opacity = '1';
}
const oldLinks = existingLinks.filter(link => {
const href = link.getAttribute('href') || '';
return href.includes('dynamic.php?s=') || href.includes('highlight.js/11.11.1/styles/');
});
let loadedCount = 0;
const onLinkLoad = () => {
loadedCount++;
if (loadedCount === requiredHrefs.length) {
oldLinks.forEach(link => link.remove());
fadeOutLoader(loader);
if (typeof onComplete === 'function') onComplete(activeTheme);
}
};
requiredHrefs.forEach(href => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
link.onload = onLinkLoad;
link.onerror = onLinkLoad;
document.head.appendChild(link);
});
}
theme-utils.js
×
Type: Web, text/x-java
2.75 Kilobytes
Last Modified 2026-09-04 14:23:31
⬇ Download File
Type: Web, text/x-java
2.75 Kilobytes
Last Modified 2026-09-04 14:23:31
⬇ Download File