89 lines
3.0 KiB
JavaScript
89 lines
3.0 KiB
JavaScript
"use strict";
|
|
|
|
class S_ThemeSwitcher {
|
|
static attach() {
|
|
window.S_ThemeSwitcher = new S_ThemeSwitcher();
|
|
}
|
|
|
|
constructor() {
|
|
this.setTheme(this.getStoredTheme() || this.getPreferredTheme());
|
|
this.showActiveTheme();
|
|
|
|
document.querySelectorAll("[data-bs-theme-value]").forEach(function (button) {
|
|
button.addEventListener("click", () => this.manageThemeClick(button, true));
|
|
}, this);
|
|
|
|
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
|
|
const storedTheme = this.getStoredTheme();
|
|
if (storedTheme !== "light" && storedTheme !== "dark") {
|
|
const theme = this.getColorTheme();
|
|
const themeButton = document.querySelector("[data-bs-theme-value=\"" + theme + "\"]");
|
|
this.manageThemeClick(themeButton);
|
|
}
|
|
});
|
|
|
|
const breakpointMd = window.getComputedStyle(document.body).getPropertyValue("--bs-breakpoint-md");
|
|
const matchMd = window.matchMedia("(min-width: " + breakpointMd + ")");
|
|
this.manageThemeText(matchMd.matches);
|
|
matchMd.addEventListener("change", (ev) => this.manageThemeText(ev.matches));
|
|
}
|
|
|
|
getStoredTheme() {
|
|
return localStorage.getItem("theme");
|
|
}
|
|
|
|
setStoredTheme(theme) {
|
|
localStorage.setItem("theme", theme);
|
|
}
|
|
|
|
getPreferredTheme() {
|
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
}
|
|
|
|
getColorTheme() {
|
|
const theme = this.getStoredTheme();
|
|
return ('auto' === theme) ? this.getPreferredTheme() : theme;
|
|
}
|
|
|
|
setTheme(theme) {
|
|
document.documentElement.setAttribute("data-bs-theme", ("auto" === theme) ? this.getPreferredTheme() : theme);
|
|
}
|
|
|
|
showActiveTheme(focus = false) {
|
|
const themeSwitcher = document.querySelector("#theme");
|
|
if (!themeSwitcher) { return; }
|
|
|
|
const themeSwitcherIcon = themeSwitcher.querySelector("i");
|
|
|
|
const activeTheme = this.getColorTheme();
|
|
const activeThemeButton = document.querySelector("[data-bs-theme-value=\"" + activeTheme + "\"]");
|
|
const activeThemeButtonIcon = activeThemeButton.querySelector("i");
|
|
|
|
themeSwitcherIcon.classList = activeThemeButtonIcon.classList;
|
|
|
|
if (focus) {
|
|
themeSwitcher.focus();
|
|
}
|
|
}
|
|
|
|
manageThemeClick(button, focus = false) {
|
|
const theme = button.getAttribute("data-bs-theme-value");
|
|
this.setStoredTheme(theme);
|
|
this.setTheme(theme);
|
|
this.showActiveTheme(focus);
|
|
}
|
|
|
|
manageThemeText(matches) {
|
|
const themeSwitcher = document.querySelector("#theme");
|
|
if (!themeSwitcher) { return; }
|
|
|
|
const themeSwitcherText = themeSwitcher.querySelector("span");
|
|
themeSwitcherText.classList.toggle("visually-hidden", matches);
|
|
}
|
|
}
|
|
|
|
if (document.readyState !== "loading") {
|
|
S_ThemeSwitcher.attach();
|
|
} else {
|
|
document.addEventListener("DOMContentLoaded", S_ThemeSwitcher.attach);
|
|
} |