// 前台普通页面交互入口,集中管理确认弹窗、聊天室弹窗和说明页导航高亮。 let frontControlsBound = false; /** * 读取元素上声明的确认文案,并在用户取消时拦截默认行为。 * * @param {Event} event * @param {Element} element * @param {string} attribute * @returns {boolean} */ function confirmBeforeAction(event, element, attribute) { const message = element.getAttribute(attribute); if (!message || window.confirm(message)) { return true; } event.preventDefault(); return false; } /** * 打开独立聊天室窗口,并尽量铺满当前可用屏幕。 * * @param {string} url * @param {string} roomName * @returns {void} */ function openChatRoomWindow(url, roomName) { const chatWindow = window.open( url, `chatroom_${roomName}`, "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes", ); if (!chatWindow) { return; } chatWindow.moveTo(0, 0); chatWindow.resizeTo(window.screen.availWidth, window.screen.availHeight); chatWindow.focus(); } /** * 绑定说明页右侧导航的可视区高亮。 * * @returns {void} */ function bindGuideNavigation() { const aside = document.getElementById("guide-aside"); const nav = document.getElementById("guide-nav"); if (!aside || !nav) { return; } const checkWidth = () => { aside.style.display = window.innerWidth >= 1024 ? "block" : "none"; }; checkWidth(); window.addEventListener("resize", checkWidth); const links = Array.from(nav.querySelectorAll("a")); const sections = links .map((link) => { const id = link.getAttribute("href")?.slice(1); const element = id ? document.getElementById(id) : null; return element ? { element, link } : null; }) .filter(Boolean); const onScroll = () => { let current = sections[0]; sections.forEach((section) => { if (section.element.getBoundingClientRect().top <= 120) { current = section; } }); links.forEach((link) => link.classList.remove("active")); current?.link.classList.add("active"); }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); } /** * 绑定前台普通页面的轻量事件代理。 * * @returns {void} */ function bindFrontControls() { if (frontControlsBound || typeof document === "undefined") { return; } frontControlsBound = true; document.addEventListener("click", (event) => { if (!(event.target instanceof Element)) { return; } const submitButton = event.target.closest("[data-front-submit-confirm]"); if (submitButton && !confirmBeforeAction(event, submitButton, "data-front-submit-confirm")) { return; } const roomLink = event.target.closest("[data-chat-room-window-url]"); if (roomLink) { event.preventDefault(); openChatRoomWindow( roomLink.getAttribute("data-chat-room-window-url") ?? "", roomLink.getAttribute("data-chat-room-window-name") ?? "room", ); } }); document.addEventListener("submit", (event) => { if (!(event.target instanceof HTMLFormElement)) { return; } confirmBeforeAction(event, event.target, "data-front-confirm"); }); bindGuideNavigation(); } bindFrontControls();