补充主题静态资源与归档模板
This commit is contained in:
1 parent
1268a55dd0
commit
3247db7ed1
265 files changed
+59174
No files matched your search
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
* AKSRT Search Panel — desktop panel, mobile overlay, history, suggestions
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initSearchPanel() {
|
||||
var btn = document.getElementById("search-toggle");
|
||||
var panel = document.getElementById("nav-search-panel");
|
||||
var mobileOverlay = document.getElementById("tabbar-search-overlay");
|
||||
var mobileInput = document.getElementById("tabbar-search-input");
|
||||
var mobileClose = document.getElementById("tabbar-search-close");
|
||||
var mobileForm = mobileOverlay ? mobileOverlay.querySelector("form") : null;
|
||||
var mobileTypeInput = document.getElementById("tabbar-search-type");
|
||||
var mobileTypeButtons = document.querySelectorAll("#tabbar-search-types [data-search-type]");
|
||||
var historyWrap = document.getElementById("tabbar-search-history");
|
||||
var historySection = document.getElementById("tabbar-search-history-section");
|
||||
var historyClear = document.getElementById("tabbar-search-history-clear");
|
||||
var suggestionsWrap = document.getElementById("tabbar-search-suggestions");
|
||||
var suggestionsSection = document.getElementById("tabbar-search-suggestions-section");
|
||||
if (!btn || !panel) return;
|
||||
var HISTORY_KEY = "aksrt-mobile-search-history";
|
||||
var suggestTimer = null;
|
||||
var searchConfig = (window.aksrtData && aksrtData.search) || {};
|
||||
var historyEnabled = searchConfig.historyEnabled !== false;
|
||||
var suggestionsEnabled = !!searchConfig.suggestionsEnabled;
|
||||
|
||||
if (historySection && !historyEnabled) {
|
||||
historySection.hidden = true;
|
||||
}
|
||||
if (suggestionsSection && !suggestionsEnabled) {
|
||||
suggestionsSection.hidden = true;
|
||||
}
|
||||
|
||||
function getSearchType() {
|
||||
return mobileTypeInput ? (mobileTypeInput.value || "post") : "post";
|
||||
}
|
||||
|
||||
function setSearchType(type) {
|
||||
if (!mobileTypeInput) return;
|
||||
mobileTypeInput.value = type;
|
||||
mobileTypeButtons.forEach(function (button) {
|
||||
button.classList.toggle("is-active", button.getAttribute("data-search-type") === type);
|
||||
});
|
||||
requestSuggestions();
|
||||
}
|
||||
|
||||
function readHistory() {
|
||||
if (!historyEnabled) return [];
|
||||
if (aksrtData.isLoggedIn) return [];
|
||||
try {
|
||||
var raw = localStorage.getItem(HISTORY_KEY);
|
||||
var list = raw ? JSON.parse(raw) : [];
|
||||
return Array.isArray(list) ? list : [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function writeHistory(items) {
|
||||
if (!historyEnabled) return;
|
||||
if (aksrtData.isLoggedIn) return;
|
||||
try {
|
||||
localStorage.setItem(HISTORY_KEY, JSON.stringify(items.slice(0, 8)));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function requestHistorySync(mode, items, callback) {
|
||||
if (!historyEnabled) {
|
||||
if (historySection) historySection.hidden = true;
|
||||
if (typeof callback === "function") callback([]);
|
||||
return;
|
||||
}
|
||||
if (!aksrtData.isLoggedIn) {
|
||||
if (typeof callback === "function") callback(mode === "save" ? (items || []) : readHistory());
|
||||
return;
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aksrtData.ajaxUrl, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
xhr.onload = function () {
|
||||
if (typeof callback !== "function") return;
|
||||
if (xhr.status < 200 || xhr.status >= 300) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
callback(json.success && json.data && Array.isArray(json.data.items) ? json.data.items : []);
|
||||
} catch (e) {
|
||||
callback([]);
|
||||
}
|
||||
};
|
||||
var body = "action=aksrt_search_history&nonce=" + encodeURIComponent(aksrtData.nonce) + "&mode=" + encodeURIComponent(mode);
|
||||
if (mode === "save") {
|
||||
body += "&items=" + encodeURIComponent(JSON.stringify(items || []));
|
||||
}
|
||||
xhr.send(body);
|
||||
}
|
||||
|
||||
function pushHistory(keyword, type) {
|
||||
if (!historyEnabled) return;
|
||||
if (!keyword) return;
|
||||
if (aksrtData.isLoggedIn) {
|
||||
requestHistorySync("get", null, function (remoteItems) {
|
||||
var nextRemote = (remoteItems || []).filter(function (item) {
|
||||
return !(item && item.keyword === keyword && item.type === type);
|
||||
});
|
||||
nextRemote.unshift({ keyword: keyword, type: type });
|
||||
requestHistorySync("save", nextRemote.slice(0, 8), function (savedItems) {
|
||||
renderHistory(savedItems);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
var next = readHistory().filter(function (item) {
|
||||
return !(item && item.keyword === keyword && item.type === type);
|
||||
});
|
||||
next.unshift({ keyword: keyword, type: type });
|
||||
writeHistory(next);
|
||||
renderHistory();
|
||||
}
|
||||
|
||||
function renderHistory(providedItems) {
|
||||
if (!historyWrap) return;
|
||||
if (!historyEnabled) {
|
||||
if (historySection) historySection.hidden = true;
|
||||
historyWrap.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (historySection) {
|
||||
historySection.hidden = false;
|
||||
}
|
||||
var items = Array.isArray(providedItems) ? providedItems : readHistory();
|
||||
if (!items.length) {
|
||||
historyWrap.innerHTML = '<div class="tabbar-search-overlay__empty">暂无搜索历史</div>';
|
||||
if (historyClear) historyClear.style.display = "none";
|
||||
return;
|
||||
}
|
||||
if (historyClear) historyClear.style.display = "inline-flex";
|
||||
historyWrap.innerHTML = items.map(function (item) {
|
||||
return '<button type="button" class="tabbar-search-overlay__history-item" data-history-keyword="' + encodeURIComponent(item.keyword) + '" data-history-type="' + encodeURIComponent(item.type || 'post') + '">' +
|
||||
'<i class="fas fa-history"></i><span>' + item.keyword + '</span>' +
|
||||
'</button>';
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function renderSuggestions(items) {
|
||||
if (!suggestionsWrap || !suggestionsSection) return;
|
||||
if (!suggestionsEnabled) {
|
||||
suggestionsSection.hidden = true;
|
||||
suggestionsWrap.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
if (!items || !items.length) {
|
||||
suggestionsWrap.innerHTML = '<div class="tabbar-search-overlay__empty">暂无匹配结果</div>';
|
||||
suggestionsSection.hidden = false;
|
||||
return;
|
||||
}
|
||||
suggestionsWrap.innerHTML = items.map(function (item) {
|
||||
var meta = item.meta ? '<small>' + item.meta + '</small>' : '';
|
||||
return '<a href="' + item.url + '" class="tabbar-search-overlay__suggestion-item">' +
|
||||
'<span>' + item.title + '</span>' + meta +
|
||||
'</a>';
|
||||
}).join("");
|
||||
suggestionsSection.hidden = false;
|
||||
}
|
||||
|
||||
function requestSuggestions() {
|
||||
if (!mobileInput || !suggestionsWrap || !suggestionsSection) return;
|
||||
if (!suggestionsEnabled) {
|
||||
suggestionsSection.hidden = true;
|
||||
return;
|
||||
}
|
||||
var keyword = (mobileInput.value || "").trim();
|
||||
if (suggestTimer) clearTimeout(suggestTimer);
|
||||
if (keyword.length < 2) {
|
||||
suggestionsSection.hidden = true;
|
||||
return;
|
||||
}
|
||||
suggestTimer = setTimeout(function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aksrtData.ajaxUrl, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
xhr.onload = function () {
|
||||
if (xhr.status < 200 || xhr.status >= 300) return;
|
||||
try {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
if (json.success && json.data && json.data.items) {
|
||||
renderSuggestions(json.data.items);
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
xhr.send(
|
||||
"action=aksrt_search_suggestions&nonce=" + encodeURIComponent(aksrtData.nonce) +
|
||||
"&q=" + encodeURIComponent(keyword) +
|
||||
"&type=" + encodeURIComponent(getSearchType())
|
||||
);
|
||||
}, 180);
|
||||
}
|
||||
|
||||
function isMobileSearchMode() {
|
||||
return window.innerWidth < 768 && !!mobileOverlay;
|
||||
}
|
||||
|
||||
function setOpen(open) {
|
||||
if (isMobileSearchMode()) {
|
||||
if (open) {
|
||||
mobileOverlay.removeAttribute("hidden");
|
||||
document.body.classList.add("tabbar-search-open");
|
||||
if (mobileInput) mobileInput.focus();
|
||||
if (historyEnabled) renderHistory();
|
||||
if (suggestionsEnabled) requestSuggestions();
|
||||
} else {
|
||||
mobileOverlay.setAttribute("hidden", "");
|
||||
document.body.classList.remove("tabbar-search-open");
|
||||
if (suggestionsSection) suggestionsSection.hidden = true;
|
||||
}
|
||||
btn.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
return;
|
||||
}
|
||||
|
||||
panel.classList.toggle("is-open", open);
|
||||
btn.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
if (open) {
|
||||
var input = panel.querySelector('input[type="search"]');
|
||||
if (input) input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
btn.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
if (isMobileSearchMode()) {
|
||||
setOpen(!mobileOverlay || mobileOverlay.hasAttribute("hidden"));
|
||||
return;
|
||||
}
|
||||
setOpen(!panel.classList.contains("is-open"));
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (isMobileSearchMode()) return;
|
||||
if (!panel.classList.contains("is-open")) return;
|
||||
if (panel.contains(e.target) || btn.contains(e.target)) return;
|
||||
setOpen(false);
|
||||
});
|
||||
|
||||
if (mobileOverlay) {
|
||||
mobileOverlay.addEventListener("click", function (e) {
|
||||
if (e.target === mobileOverlay) setOpen(false);
|
||||
});
|
||||
}
|
||||
if (mobileClose) {
|
||||
mobileClose.addEventListener("click", function () {
|
||||
setOpen(false);
|
||||
});
|
||||
}
|
||||
|
||||
if (historyClear) {
|
||||
historyClear.addEventListener("click", function () {
|
||||
if (aksrtData.isLoggedIn) {
|
||||
requestHistorySync("save", [], function (savedItems) {
|
||||
renderHistory(savedItems);
|
||||
});
|
||||
return;
|
||||
}
|
||||
writeHistory([]);
|
||||
renderHistory();
|
||||
});
|
||||
}
|
||||
|
||||
if (historyWrap) {
|
||||
historyWrap.addEventListener("click", function (e) {
|
||||
var item = e.target.closest("[data-history-keyword]");
|
||||
if (!item || !mobileInput) return;
|
||||
mobileInput.value = decodeURIComponent(item.getAttribute("data-history-keyword") || "");
|
||||
setSearchType(decodeURIComponent(item.getAttribute("data-history-type") || "post"));
|
||||
requestSuggestions();
|
||||
});
|
||||
}
|
||||
|
||||
mobileTypeButtons.forEach(function (button) {
|
||||
button.addEventListener("click", function () {
|
||||
setSearchType(button.getAttribute("data-search-type") || "post");
|
||||
});
|
||||
});
|
||||
|
||||
if (mobileInput) {
|
||||
mobileInput.addEventListener("input", requestSuggestions);
|
||||
}
|
||||
|
||||
if (mobileForm) {
|
||||
mobileForm.addEventListener("submit", function () {
|
||||
if (mobileInput) {
|
||||
pushHistory((mobileInput.value || "").trim(), getSearchType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-aksrt-search-form]").forEach(function (form) {
|
||||
if (form === mobileForm) return;
|
||||
form.addEventListener("submit", function () {
|
||||
if (!historyEnabled) return;
|
||||
var input = form.querySelector('input[name="s"]');
|
||||
var typeInput = form.querySelector('input[name="aksrt_search_type"]');
|
||||
var keyword = input ? (input.value || "").trim() : "";
|
||||
var type = typeInput ? (typeInput.value || "post") : "post";
|
||||
pushHistory(keyword, type);
|
||||
});
|
||||
});
|
||||
|
||||
setSearchType(getSearchType());
|
||||
if (historyEnabled && aksrtData.isLoggedIn) {
|
||||
requestHistorySync("get", null, function (items) {
|
||||
renderHistory(items);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
|
||||
e.preventDefault();
|
||||
setOpen(true);
|
||||
}
|
||||
if (e.key === "Escape" && panel.classList.contains("is-open")) {
|
||||
setOpen(false);
|
||||
btn.focus();
|
||||
}
|
||||
if (e.key === "Escape" && isMobileSearchMode() && mobileOverlay && !mobileOverlay.hasAttribute("hidden")) {
|
||||
setOpen(false);
|
||||
btn.focus();
|
||||
}
|
||||
});
|
||||
|
||||
window.__aksrtOpenSearchPanel = function () { setOpen(true); };
|
||||
window.__aksrtCloseSearchPanel = function () { setOpen(false); };
|
||||
}
|
||||
|
||||
window.AksrtFrontend.register("aksrt-search-panel", function () { initSearchPanel(); });
|
||||
})();
|
||||
Reference in new issue
Block a user