var jasmine = (function (P) { "use strict"; const le = ""; const ue = ""; /** * Sticky Sidebar JavaScript Plugin. * @version 3.3.2 * @author SHITOUCUO * @license The MIT License (MIT) */ const G = (() => { const c = ".stickySidebar"; const m = { topSpacing: 0, bottomSpacing: 0, containerSelector: !1, innerWrapperSelector: ".inner-wrapper-sticky", stickyClass: "is-affixed", resizeSensor: !0, minWidth: !1 }; class l { constructor(e, r = {}) { if (this.options = l.extend(m, r), this.sidebar = typeof e == "string" ? document.querySelector(e) : e, typeof this.sidebar > "u") throw new Error("There is no specific sidebar element."); this.sidebarInner = !1, this.container = this.sidebar.parentElement, this.affixedType = "STATIC", this.direction = "down", this.support = { transform: !1, transform3d: !1 }, this._initialized = !1, this._reStyle = !1, this._breakpoint = !1, this._resizeListeners = [], this.dimensions = { translateY: 0, topSpacing: 0, lastTopSpacing: 0, bottomSpacing: 0, lastBottomSpacing: 0, sidebarHeight: 0, sidebarWidth: 0, containerTop: 0, containerHeight: 0, viewportHeight: 0, viewportTop: 0, lastViewportTop: 0 }, ["handleEvent"].forEach(n => { this[n] = this[n].bind(this) }), this.initialize() } initialize() { if (this._setSupportFeatures(), this.options.innerWrapperSelector && (this.sidebarInner = this.sidebar.querySelector(this.options.innerWrapperSelector), this.sidebarInner === null && (this.sidebarInner = !1)), !this.sidebarInner) { let e = document.createElement("div"); for (e.setAttribute("class", "inner-wrapper-sticky"), this.sidebar.appendChild(e); this.sidebar.firstChild != e;) e.appendChild(this.sidebar.firstChild); this.sidebarInner = this.sidebar.querySelector(".inner-wrapper-sticky") } if (this.options.containerSelector) { let e = document.querySelectorAll(this.options.containerSelector); if (e = Array.prototype.slice.call(e), e.forEach((r, n) => { r.contains(this.sidebar) && (this.container = r) }), !e.length) throw new Error("The container does not contains on the sidebar.") } typeof this.options.topSpacing != "function" && (this.options.topSpacing = parseInt(this.options.topSpacing) || 0), typeof this.options.bottomSpacing != "function" && (this.options.bottomSpacing = parseInt(this.options.bottomSpacing) || 0), this._widthBreakpoint(), this.calcDimensions(), this.stickyPosition(), this.bindEvents(), this._initialized = !0 } bindEvents() { window.addEventListener("resize", this, { passive: !0, capture: !1 }), window.addEventListener("scroll", this, { passive: !0, capture: !1 }), this.sidebar.addEventListener("update" + c, this) } handleEvent(e) { this.updateSticky(e) } calcDimensions() { if (!this._breakpoint) { var e = this.dimensions; e.containerTop = l.offsetRelative(this.container).top, e.containerHeight = this.container.clientHeight, e.containerBottom = e.containerTop + e.containerHeight, e.sidebarHeight = this.sidebarInner.offsetHeight, e.sidebarWidth = this.sidebar.offsetWidth, e.viewportHeight = window.innerHeight, this._calcDimensionsWithScroll() } } _calcDimensionsWithScroll() { var e = this.dimensions; e.sidebarLeft = l.offsetRelative(this.sidebar).left, e.viewportTop = document.documentElement.scrollTop || document.body.scrollTop, e.viewportBottom = e.viewportTop + e.viewportHeight, e.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft, e.topSpacing = this.options.topSpacing, e.bottomSpacing = this.options.bottomSpacing, typeof e.topSpacing == "function" && (e.topSpacing = parseInt(e.topSpacing(this.sidebar)) || 0), typeof e.bottomSpacing == "function" && (e.bottomSpacing = parseInt(e.bottomSpacing(this.sidebar)) || 0), this.affixedType === "VIEWPORT-TOP" ? e.topSpacing < e.lastTopSpacing && (e.translateY += e.lastTopSpacing - e.topSpacing, this._reStyle = !0) : this.affixedType === "VIEWPORT-BOTTOM" && e.bottomSpacing < e.lastBottomSpacing && (e.translateY += e.lastBottomSpacing - e.bottomSpacing, this._reStyle = !0), e.lastTopSpacing = e.topSpacing, e.lastBottomSpacing = e.bottomSpacing } isSidebarFitsViewport() { return this.dimensions.sidebarHeight < this.dimensions.viewportHeight } observeScrollDir() { var e = this.dimensions; if (e.lastViewportTop !== e.viewportTop) { var r = this.direction === "down" ? Math.min : Math.max; e.viewportTop === r(e.viewportTop, e.lastViewportTop) && (this.direction = this.direction === "down" ? "up" : "down") } } getAffixType() { var e = this.dimensions, r = !1; this._calcDimensionsWithScroll(); var n = e.sidebarHeight + e.containerTop, t = e.viewportTop + e.topSpacing, s = e.viewportBottom - e.bottomSpacing; return this.direction === "up" ? t <= e.containerTop ? (e.translateY = 0, r = "STATIC") : t <= e.translateY + e.containerTop ? (e.translateY = t - e.containerTop, r = "VIEWPORT-TOP") : !this.isSidebarFitsViewport() && e.containerTop <= t && (r = "VIEWPORT-UNBOTTOM") : this.isSidebarFitsViewport() ? e.sidebarHeight + t >= e.containerBottom ? (e.translateY = e.containerBottom - n, r = "CONTAINER-BOTTOM") : t >= e.containerTop && (e.translateY = t - e.containerTop, r = "VIEWPORT-TOP") : e.containerBottom <= s ? (e.translateY = e.containerBottom - n, r = "CONTAINER-BOTTOM") : n + e.translateY <= s ? (e.translateY = s - n, r = "VIEWPORT-BOTTOM") : e.containerTop + e.translateY <= t && (r = "VIEWPORT-UNBOTTOM"), e.translateY = Math.max(0, e.translateY), e.translateY = Math.min(e.containerHeight, e.translateY), e.lastViewportTop = e.viewportTop, r } _getStyle(e) { if (!(typeof e > "u")) { var r = { inner: {}, outer: {} }, n = this.dimensions; switch (e) { case "VIEWPORT-TOP": r.inner = { position: "fixed", top: n.topSpacing, left: n.sidebarLeft - n.viewportLeft, width: n.sidebarWidth }; break; case "VIEWPORT-BOTTOM": r.inner = { position: "fixed", top: "auto", left: n.sidebarLeft, bottom: n.bottomSpacing, width: n.sidebarWidth }; break; case "CONTAINER-BOTTOM": case "VIEWPORT-UNBOTTOM": let t = this._getTranslate(0, n.translateY + "px"); t ? r.inner = { transform: t } : r.inner = { position: "absolute", top: n.translateY, width: n.sidebarWidth }; break } switch (e) { case "VIEWPORT-TOP": case "VIEWPORT-BOTTOM": case "VIEWPORT-UNBOTTOM": case "CONTAINER-BOTTOM": r.outer = { height: n.sidebarHeight, position: "relative" }; break } return r.outer = l.extend({ height: "", position: "" }, r.outer), r.inner = l.extend({ position: "relative", top: "", left: "", bottom: "", width: "", transform: this._getTranslate() }, r.inner), r } } stickyPosition(e) { if (!this._breakpoint) { e = this._reStyle || e || !1, this.options.topSpacing, this.options.bottomSpacing; var r = this.getAffixType(), n = this._getStyle(r); if ((this.affixedType != r || e) && r) { let t = "affix." + r.toLowerCase().replace("viewport-", "") + c; l.eventTrigger(this.sidebar, t), r === "STATIC" ? l.removeClass(this.sidebar, this.options.stickyClass) : l.addClass(this.sidebar, this.options.stickyClass); for (let d in n.outer) n.outer[d], this.sidebar.style[d] = n.outer[d]; for (let d in n.inner) { let g = typeof n.inner[d] == "number" ? "px" : ""; this.sidebarInner.style[d] = n.inner[d] + g } let s = "affixed." + r.toLowerCase().replace("viewport-", "") + c; l.eventTrigger(this.sidebar, s) } else this._initialized && (this.sidebarInner.style.left = n.inner.left); this.affixedType = r } } _widthBreakpoint() { window.innerWidth <= this.options.minWidth ? (this._breakpoint = !0, this.affixedType = "STATIC", this.sidebar.removeAttribute("style"), l.removeClass(this.sidebar, this.options.stickyClass), this.sidebarInner.removeAttribute("style")) : this._breakpoint = !1 } updateSticky(e = {}) { this._running || (this._running = !0, (r => { requestAnimationFrame(() => { switch (r) { case "scroll": this._calcDimensionsWithScroll(), this.observeScrollDir(), this.stickyPosition(); break; case "resize": default: this._widthBreakpoint(), this.calcDimensions(), this.stickyPosition(!0); break } this._running = !1 }) })(e.type)) } _setSupportFeatures() { var e = this.support; e.transform = l.supportTransform(), e.transform3d = l.supportTransform(!0) } _getTranslate(e = 0, r = 0, n = 0) { return this.support.transform3d ? "translate3d(" + e + ", " + r + ", " + n + ")" : this.support.translate ? "translate(" + e + ", " + r + ")" : !1 } destroy() { window.removeEventListener("resize", this, { caption: !1 }), window.removeEventListener("scroll", this, { caption: !1 }), this.sidebar.classList.remove(this.options.stickyClass), this.sidebar.style.minHeight = "", this.sidebar.removeEventListener("update" + c, this); var e = { inner: {}, outer: {} }; e.inner = { position: "", top: "", left: "", bottom: "", width: "", transform: "" }, e.outer = { height: "", position: "" }; for (let r in e.outer) this.sidebar.style[r] = e.outer[r]; for (let r in e.inner) this.sidebarInner.style[r] = e.inner[r]; } static supportTransform(e) { var r = !1, n = e ? "perspective" : "transform", t = n.charAt(0).toUpperCase() + n.slice(1), s = ["Webkit", "Moz", "O", "ms"], d = document.createElement("support"), g = d.style; return (n + " " + s.join(t + " ") + t).split(" ").forEach(function (E, y) { if (g[E] !== void 0) return r = E, !1 }), r } static eventTrigger(e, r, n) { try { var t = new CustomEvent(r, { detail: n }) } catch { var t = document.createEvent("CustomEvent"); t.initCustomEvent(r, !0, !0, n) } e.dispatchEvent(t) } static extend(e, r) { var n = {}; for (let t in e) typeof r[t] < "u" ? n[t] = r[t] : n[t] = e[t]; return n } static offsetRelative(e) { var r = { left: 0, top: 0 }; do { let n = e.offsetTop, t = e.offsetLeft; isNaN(n) || (r.top += n), isNaN(t) || (r.left += t), e = e.tagName === "BODY" ? e.parentElement : e.offsetParent } while (e); return r } static addClass(e, r) { l.hasClass(e, r) || (e.classList ? e.classList.add(r) : e.className += " " + r) } static removeClass(e, r) { l.hasClass(e, r) && (e.classList ? e.classList.remove(r) : e.className = e.className.replace(new RegExp("(^|\\b)" + r.split(" ").join("|") + "(\\b|$)", "gi"), " ")) } static hasClass(e, r) { return e.classList ? e.classList.contains(r) : new RegExp("(^| )" + r + "( |$)", "gi").test(e.className) } } return l })(); window.StickySidebar = G; /** * 主题管理功能 - 修改为默认深色模式 */ function switchDark() { // 切换主题并保存到localStorage if (!localStorage.theme) { // 首次设置,设为深色模式 localStorage.theme = "dark"; } else if (localStorage.theme === "light") { localStorage.theme = "dark"; } else if (localStorage.theme === "dark") { localStorage.theme = "light"; } loadTheme(); updateThemeIcon(); } function loadTheme() { // 移除系统主题变化监听器,不再自动跟随系统主题 // 应用当前主题 if (!localStorage.theme) { // 首次访问:默认设为深色模式 localStorage.theme = "dark"; document.documentElement.classList.add("dark"); } else if (localStorage.theme === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } updateThemeIcon(); } // 获取当前主题状态 function getCurrentTheme() { if (!localStorage.theme) { // 首次访问:默认返回深色模式 return "dark"; } return localStorage.theme; } // 更新主题图标 function updateThemeIcon() { const currentTheme = getCurrentTheme(); const iconElement = document.querySelector('[title="日夜模式"] iconify-icon'); if (iconElement) { // 根据当前主题更新图标 if (currentTheme === "dark") { iconElement.setAttribute('icon', 'tabler:sun'); // 深色模式显示太阳图标(切换后变为浅色) } else { iconElement.setAttribute('icon', 'tabler:moon'); // 浅色模式显示月亮图标(切换后变为深色) } } } /** * 其他工具函数 */ function backtop() { document.body.scrollTop = 0; document.documentElement.scrollTop = 0; } function clickSearch() { const searchInput = document.getElementById("search-input"); if (searchInput) { searchInput.blur(); } } function toggleMobileMenu() { const mobileMenusBg = document.querySelector("#mobile-menus-bg"); const mobileMenus = document.querySelector("#mobile-menus"); if (mobileMenus.classList.contains("!translate-x-0")) { if (mobileMenusBg) mobileMenusBg.classList.add("hidden"); if (mobileMenus) mobileMenus.classList.remove("!translate-x-0"); } else { if (mobileMenusBg) mobileMenusBg.classList.remove("hidden"); if (mobileMenus) mobileMenus.classList.add("!translate-x-0"); } } /** * 初始化函数 */ function initializeJasmine() { // 初始化主题 - 默认深色模式 loadTheme(); // 初始化粘性侧边栏 if (document.querySelector("#sidebar-right")) { new G("#sidebar-right", { innerWrapperSelector: ".sidebar__right__inner" }); } // 初始化导航项悬停效果 Array.from(document.getElementsByClassName("nav-li")).forEach(item => { item.addEventListener("mouseover", () => { const span = item.getElementsByTagName("span")[0]; if (span) span.classList.add("!block"); }); item.addEventListener("mouseout", () => { const span = item.getElementsByTagName("span")[0]; if (span) span.classList.remove("!block"); }); }); // 初始化移动菜单背景点击事件 const mobileMenusBg = document.querySelector("#mobile-menus-bg"); if (mobileMenusBg) { mobileMenusBg.addEventListener("click", toggleMobileMenu); } // 初始化主题图标 updateThemeIcon(); console.log("%c Jasmine ", "background:#000;color:#fff", "https://www.shitoucuo.com"); } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializeJasmine); } else { initializeJasmine(); } // 导出函数到全局对象 return { backtop: backtop, clickSearch: clickSearch, loadTheme: loadTheme, switchDark: switchDark, toggleMobileMenu: toggleMobileMenu, getCurrentTheme: getCurrentTheme, updateThemeIcon: updateThemeIcon }; })({});