69 lines
2.7 KiB
JavaScript
69 lines
2.7 KiB
JavaScript
/* OpenStats 官网 · 页面外壳:主题切换、菜单栏下拉菜单与时钟 */
|
|
(() => {
|
|
"use strict";
|
|
|
|
const root = document.documentElement;
|
|
const THEME_KEY = "os-theme";
|
|
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
|
|
function saved() {
|
|
try { return localStorage.getItem(THEME_KEY); } catch { return null; }
|
|
}
|
|
function applyTheme(theme, persist) {
|
|
root.dataset.theme = theme;
|
|
if (!persist) return;
|
|
try { localStorage.setItem(THEME_KEY, theme); } catch { /* 隐私模式下不可用,忽略 */ }
|
|
}
|
|
|
|
applyTheme(saved() || (media.matches ? "dark" : "light"), false);
|
|
// 没有手动选过时跟随系统
|
|
media.addEventListener("change", (e) => { if (!saved()) applyTheme(e.matches ? "dark" : "light", false); });
|
|
|
|
window.OpenStatsSite = {
|
|
toggleTheme() { applyTheme(root.dataset.theme === "dark" ? "light" : "dark", true); },
|
|
};
|
|
document.getElementById("themeToggle")?.addEventListener("click", (e) => {
|
|
e.stopPropagation();
|
|
window.OpenStatsSite.toggleTheme();
|
|
});
|
|
|
|
// ── 菜单栏下拉菜单:点击展开,展开后悬停切换,点外部或 Esc 收起 ──
|
|
const menus = [...document.querySelectorAll(".mb-menu")];
|
|
let openMenu = null;
|
|
|
|
function setMenu(menu) {
|
|
for (const m of menus) {
|
|
const open = m === menu;
|
|
m.classList.toggle("is-open", open);
|
|
m.querySelector(".mb-title")?.setAttribute("aria-expanded", String(open));
|
|
}
|
|
openMenu = menu;
|
|
}
|
|
|
|
for (const menu of menus) {
|
|
const title = menu.querySelector(".mb-title");
|
|
title?.addEventListener("click", (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
setMenu(openMenu === menu ? null : menu);
|
|
});
|
|
menu.addEventListener("mouseenter", () => { if (openMenu && openMenu !== menu) setMenu(menu); });
|
|
menu.querySelector(".mb-drop")?.addEventListener("click", () => setMenu(null));
|
|
}
|
|
document.addEventListener("click", (e) => { if (openMenu && !openMenu.contains(e.target)) setMenu(null); });
|
|
document.addEventListener("keydown", (e) => { if (e.key === "Escape") setMenu(null); });
|
|
|
|
// ── 时钟:按访客本地时间显示 ──
|
|
const clock = document.getElementById("menubarClock");
|
|
const format = new Intl.DateTimeFormat("zh-CN", { month: "numeric", day: "numeric", weekday: "short", hour: "2-digit", minute: "2-digit", hour12: false });
|
|
function renderClock() {
|
|
if (!clock) return;
|
|
const now = new Date();
|
|
const parts = Object.fromEntries(format.formatToParts(now).map((p) => [p.type, p.value]));
|
|
clock.textContent = `${parts.month}月${parts.day}日 ${parts.weekday} ${parts.hour}:${parts.minute}`;
|
|
clock.dateTime = now.toISOString();
|
|
}
|
|
renderClock();
|
|
setInterval(renderClock, 15000);
|
|
})();
|