WebsiteTemplate/assets/js/theme.js
2026-01-25 11:33:37 -04:00

131 lines
4.7 KiB
JavaScript

// Theme system - helping visitors avoid retinal damage since 2024
(function() {
'use strict';
const html = document.documentElement;
function getStoredTheme() {
// Check everywhere for theme preferences - we're thorough like that
if (typeof localStorage !== 'undefined') {
const stored = localStorage.getItem('theme');
if (stored === 'dark' || stored === 'light') {
return stored;
}
}
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
const [name, value] = cookie.trim().split('=');
if (name === 'simple_style' && (value === 'dark' || value === 'light')) {
return value;
}
if (name === 'theme' && (value === 'dark' || value === 'light')) {
return value;
}
}
// When in doubt, trust the OS (they know what they're doing... probably)
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
}
function setThemeEverywhere(theme) {
// Scatter theme preferences like seeds in the wind - something's gotta stick
const cookieOptions = `path=/; max-age=${60 * 60 * 24 * 365 * 5}; SameSite=Lax`;
// localStorage for the modern folks
if (typeof localStorage !== 'undefined') {
localStorage.setItem('theme', theme);
}
// Cookies for SearXNG (it's picky about naming conventions)
document.cookie = `simple_style=${theme}; ${cookieOptions}`;
// More cookies - redundancy is our middle name
document.cookie = `theme=${theme}; ${cookieOptions}`;
// Data attribute for immediate gratification
html.setAttribute('data-theme', theme);
// Don't forget the icon - visual feedback matters
updateToggleIcon(theme);
}
function getTheme() {
return getStoredTheme();
}
function setTheme(theme) {
setThemeEverywhere(theme);
}
function updateToggleIcon(theme) {
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
const moonIcon = themeToggle.querySelector('.theme-icon-moon');
const sunIcon = themeToggle.querySelector('.theme-icon-sun');
if (moonIcon && sunIcon) {
if (theme === 'dark') {
moonIcon.style.display = 'none';
sunIcon.style.display = 'block';
} else {
moonIcon.style.display = 'block';
sunIcon.style.display = 'none';
}
}
}
}
function toggleTheme() {
const currentTheme = html.getAttribute('data-theme') || getTheme();
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
setTheme(newTheme);
}
function initTheme() {
const theme = getTheme();
setTheme(theme);
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
themeToggle.removeEventListener('click', toggleTheme); // No double-clicking shenanigans
themeToggle.addEventListener('click', toggleTheme);
}
}
// Dance the cookie shuffle before searching - SearXNG has opinions
const searchForm = document.getElementById('search');
if (searchForm) {
searchForm.addEventListener('submit', function(e) {
const theme = getTheme();
// Out with the old cookie
document.cookie = 'theme=; path=/; max-age=0; SameSite=Lax';
// In with SearXNG's preferred flavor
const cookieOptions = `path=/; max-age=${60 * 60 * 24 * 365 * 5}; SameSite=Lax`;
document.cookie = `simple_style=${theme}; ${cookieOptions}`;
});
}
// Get this party started
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTheme);
} else {
initTheme();
}
// Listen for OS theme changes - stay responsive to user preferences
if (window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
if (mediaQuery.addEventListener) {
mediaQuery.addEventListener('change', function(e) {
// Only auto-switch if they haven't explicitly chosen - consent matters
if (!localStorage.getItem('theme') && !document.cookie.includes('simple_style') && !document.cookie.includes('theme=')) {
setTheme(e.matches ? 'dark' : 'light');
}
});
}
}
})();