(function () { var header = document.querySelector(".site-header"); var drawer = document.querySelector("[data-drawer]"); var openBtn = document.querySelector("[data-drawer-open]"); if (header) { var threshold = 48; var ticking = false; function measure() { document.documentElement.style.setProperty("--site-header-height", header.getBoundingClientRect().height + "px"); } function update() { ticking = false; header.classList.toggle("is-scrolled", window.scrollY > threshold); } function onScroll() { if (ticking) return; ticking = true; window.requestAnimationFrame(update); } measure(); update(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", measure); if ("ResizeObserver" in window) new ResizeObserver(measure).observe(header); } // 左侧抽屉 if (drawer && openBtn) { var closeEls = drawer.querySelectorAll("[data-drawer-close]"); function openDrawer() { drawer.classList.add("is-open"); document.body.classList.add("drawer-open"); openBtn.setAttribute("aria-expanded", "true"); } function closeDrawer() { drawer.classList.remove("is-open"); document.body.classList.remove("drawer-open"); openBtn.setAttribute("aria-expanded", "false"); } openBtn.setAttribute("aria-expanded", "false"); openBtn.setAttribute("aria-controls", "site-drawer"); openBtn.addEventListener("click", openDrawer); closeEls.forEach(function (el) { el.addEventListener("click", closeDrawer); }); document.addEventListener("keydown", function (e) { if (e.key === "Escape" && drawer.classList.contains("is-open")) { closeDrawer(); } }); } // 搜索表单:走路径 /search/{q},不用 query;同时写入本地搜索历史 var SEARCH_HISTORY_KEY = "hgdj_search_history"; var SEARCH_HISTORY_MAX = 10; function searchResultsPath(q) { q = String(q || "").trim(); if (!q) return "/search"; return "/search/" + encodeURIComponent(q).replace(/%20/g, "%20"); } function readSearchHistory() { try { var raw = window.localStorage.getItem(SEARCH_HISTORY_KEY); var list = raw ? JSON.parse(raw) : []; if (!Array.isArray(list)) return []; return list .map(function (item) { return String(item || "").trim(); }) .filter(Boolean) .slice(0, SEARCH_HISTORY_MAX); } catch (_) { return []; } } function writeSearchHistory(list) { try { window.localStorage.setItem( SEARCH_HISTORY_KEY, JSON.stringify(list.slice(0, SEARCH_HISTORY_MAX)) ); } catch (_) { /* ignore quota / private mode */ } } function pushSearchHistory(q) { q = String(q || "").trim(); if (!q) return; var list = readSearchHistory().filter(function (item) { return item !== q; }); list.unshift(q); writeSearchHistory(list); } function clearSearchHistory() { try { window.localStorage.removeItem(SEARCH_HISTORY_KEY); } catch (_) { /* ignore */ } } document.querySelectorAll("form[data-path-search]").forEach(function (form) { form.addEventListener("submit", function (event) { event.preventDefault(); var input = form.querySelector('input[type="search"], input[name="q"]'); var q = input ? String(input.value || "").trim() : ""; if (!q) { if (input) input.focus(); return; } pushSearchHistory(q); window.location.href = searchResultsPath(q); }); var input = form.querySelector("[data-header-search-input], input[type='search'], input[name='q']"); var clear = form.querySelector("[data-header-search-clear]"); if (input && clear) { function syncClear() { clear.hidden = !String(input.value || "").trim(); } input.addEventListener("input", syncClear); clear.addEventListener("click", function () { input.value = ""; syncClear(); input.dispatchEvent(new Event("input", { bubbles: true })); input.focus(); }); syncClear(); } // PC header 搜索下拉:聚焦展开历史 + 热搜;输入时切换联想 var dropdown = form.querySelector("[data-header-search-dropdown]"); if (!dropdown || !input) return; var historyBox = form.querySelector("[data-header-search-history]"); var historyChips = form.querySelector("[data-header-history-chips]"); var historyClear = form.querySelector("[data-header-history-clear]"); var idleBox = form.querySelector("[data-header-search-idle]"); var suggestBox = form.querySelector("[data-header-search-suggest]"); var closeTimer = null; var suggestTimer = null; var suggestSeq = 0; var PLACEHOLDER_IMG = "/static/images/placeholder.png?v=2"; function escapeHtml(text) { return String(text || "") .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } function highlightHTML(text, keyword) { var raw = String(text || ""); var key = String(keyword || "").trim(); if (!raw) return ""; if (!key) return escapeHtml(raw); var lowerRaw = raw.toLowerCase(); var lowerKey = key.toLowerCase(); var idx = lowerRaw.indexOf(lowerKey); if (idx < 0) return escapeHtml(raw); var before = raw.slice(0, idx); var hit = raw.slice(idx, idx + key.length); var after = raw.slice(idx + key.length); return ( escapeHtml(before) + '' + escapeHtml(hit) + "" + escapeHtml(after) ); } function renderHistory() { if (!historyBox || !historyChips) return; var list = readSearchHistory(); historyChips.innerHTML = ""; if (!list.length) { historyBox.hidden = true; return; } historyBox.hidden = false; list.forEach(function (term) { var link = document.createElement("a"); link.className = "search-dropdown__chip"; link.href = searchResultsPath(term); link.textContent = term; historyChips.appendChild(link); }); } function showIdlePanel() { if (idleBox) idleBox.hidden = false; if (suggestBox) { suggestBox.hidden = true; suggestBox.innerHTML = ""; } } function showSuggestPanel() { if (idleBox) idleBox.hidden = true; if (suggestBox) suggestBox.hidden = false; } function renderSuggest(data, keyword) { if (!suggestBox) return; var html = ""; var feature = data && data.feature; var items = (data && data.items) || []; if (feature && feature.url) { html += '
' + '' + '' +
          escapeHtml(feature.title || ' + "" + '
' + '

' + highlightHTML(feature.title, keyword) + "

" + (feature.meta ? '

' + escapeHtml(feature.meta) + "

" : "") + "
" + '' + '播放播放' + "
"; } if (items.length) { html += '
'; items.forEach(function (item) { if (!item || !item.url) return; html += '' + '' + '' + highlightHTML(item.title || item.query || "", keyword) + "" + '' + escapeHtml(item.kind || "") + "" + ""; }); html += "
"; } else if (!feature) { html += '

暂无相关结果,回车搜索“' + escapeHtml(keyword) + '”

'; } suggestBox.innerHTML = html; showSuggestPanel(); if (typeof window.initLazyImages === "function") { window.initLazyImages(suggestBox, { eager: true }); } } function fetchSuggest(keyword) { var q = String(keyword || "").trim(); if (!q || !suggestBox) { showIdlePanel(); openDropdown(); return; } var seq = ++suggestSeq; showSuggestPanel(); suggestBox.innerHTML = '

搜索中…

'; openDropdown(); var req; if (window.HttpRequest && typeof window.HttpRequest.get === "function") { req = window.HttpRequest.get("/api/web/search/suggest", { params: { keyword: q }, }); } else { req = fetch( "/api/web/search/suggest?keyword=" + encodeURIComponent(q), { credentials: "include", headers: { Accept: "application/json" } } ).then(function (res) { return res.json(); }); } Promise.resolve(req) .then(function (data) { if (seq !== suggestSeq) return; renderSuggest(data || {}, q); }) .catch(function () { if (seq !== suggestSeq) return; renderSuggest( { feature: null, items: [ { title: q, kind: "搜索", query: q, url: searchResultsPath(q), }, ], }, q ); }); } function scheduleSuggest() { var q = String(input.value || "").trim(); if (suggestTimer) clearTimeout(suggestTimer); if (!q) { suggestSeq += 1; showIdlePanel(); openDropdown(); return; } suggestTimer = setTimeout(function () { suggestTimer = null; fetchSuggest(q); }, 220); } function openDropdown() { if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; } var q = String(input.value || "").trim(); if (q) { if (suggestBox && suggestBox.hidden) { scheduleSuggest(); } dropdown.hidden = false; form.classList.add("is-open"); input.setAttribute("aria-expanded", "true"); return; } showIdlePanel(); renderHistory(); var hasHistory = historyBox && !historyBox.hidden; var hasHot = !!(idleBox && idleBox.querySelector(".search-dropdown__hot")); if (!hasHistory && !hasHot) { dropdown.hidden = true; form.classList.remove("is-open"); input.setAttribute("aria-expanded", "false"); return; } dropdown.hidden = false; form.classList.add("is-open"); input.setAttribute("aria-expanded", "true"); } function closeDropdown() { dropdown.hidden = true; form.classList.remove("is-open"); input.setAttribute("aria-expanded", "false"); } function scheduleClose() { if (closeTimer) clearTimeout(closeTimer); closeTimer = setTimeout(function () { closeTimer = null; if (!form.contains(document.activeElement)) { closeDropdown(); } }, 120); } input.addEventListener("focus", openDropdown); input.addEventListener("click", openDropdown); input.addEventListener("input", function () { if (clear) clear.hidden = !String(input.value || "").trim(); scheduleSuggest(); }); input.addEventListener("blur", scheduleClose); dropdown.addEventListener("mousedown", function (event) { // 点击下拉内链接/按钮时先阻止 input blur 抢先关闭 event.preventDefault(); }); dropdown.addEventListener("click", function (event) { var chip = event.target.closest ? event.target.closest( ".search-dropdown__chip, .search-dropdown__link, .search-dropdown__feature-play, .search-dropdown__feature-cover, .search-dropdown__suggest-item" ) : null; if (chip && chip.href) { var q = ""; if (chip.classList.contains("search-dropdown__chip")) { q = String(chip.textContent || "").trim(); } else if (chip.classList.contains("search-dropdown__link")) { var name = chip.querySelector(".search-dropdown__name"); if (name) q = String(name.textContent || "").trim(); } else if (chip.getAttribute("data-suggest-query")) { q = String(chip.getAttribute("data-suggest-query") || "").trim(); } else { q = String(input.value || "").trim(); } if (q) pushSearchHistory(q); window.location.href = chip.href; } }); if (historyClear) { historyClear.addEventListener("click", function (event) { event.preventDefault(); event.stopPropagation(); clearSearchHistory(); renderHistory(); openDropdown(); input.focus(); }); } document.addEventListener("keydown", function (event) { if (event.key === "Escape" && !dropdown.hidden) { closeDropdown(); input.blur(); } }); document.addEventListener("mousedown", function (event) { if (dropdown.hidden) return; if (form.contains(event.target)) return; closeDropdown(); }); }); })();