/* source: assets/js/lazy-image-attr.js */ /** * Build lazy-image attributes for dynamically rendered AKSRT markup. * legacy owns the lazySizes runtime; this file only provides the shared bridge. */ (function (window) { 'use strict'; function escapeAttribute(value) { return String(value == null ? '' : value) .replace(/&/g, '&') .replace(/"/g, '"') .replace(//g, '>'); } window.aksrtGetLazyImageAttr = function (key, src, className, size) { var config = window.aksrtData || {}; var scopes = config.lazyScopes || {}; var classes = String(className || '').trim(); var realSrc = escapeAttribute(src); if (!src || scopes[key] === false) { return ' class="' + escapeAttribute(classes) + '" src="' + realSrc + '"'; } var thumbs = config.lazyThumbs || {}; var placeholder = key === 'lazy_avatar' ? (config.lazyAvatar || thumbs.sm || '') : (thumbs[size || 'default'] || thumbs.default || ''); return ' class="lazyload ' + escapeAttribute(classes) + '" src="' + escapeAttribute(placeholder) + '" data-src="' + realSrc + '"'; }; })(window); ; /* source: assets/js/rehydrate.js */ /** * AKSRT Rehydrate System * * Centralized component initialization and re-initialization system. * Components register their init functions, and rehydrate() is called * to initialize or re-initialize them on a given root element. * * Usage: * AksrtFrontend.register('name', initFn); // Register a component * AksrtFrontend.rehydrate(root, 'init'); // Initialize all components * * @package AKSRT * @since 5.0.0 */ (function () { 'use strict'; var _registry = []; var _initialized = []; window.AksrtFrontend = { /** * Register a component's init function. * * @param {string} name Unique component name * @param {Function} initFn Function(root, reason) - root defaults to document */ register: function (name, initFn) { if (typeof name !== 'string' || typeof initFn !== 'function') return; // Prevent duplicate registrations for (var i = 0; i < _registry.length; i++) { if (_registry[i].name === name) { _registry[i].initFn = initFn; return; } } _registry.push({ name: name, initFn: initFn }); }, /** * Initialize or re-initialize all registered components on a root element. * * @param {Element|Document} root The root DOM element to search within * @param {string} reason Why rehydrate is called: * 'init' = initial page load * 'ajax' = after AJAX content injection * 'modal' = after modal content loads * Custom string for other triggers */ rehydrate: function (root, reason) { root = root || document; reason = reason || 'init'; for (var i = 0; i < _registry.length; i++) { var entry = _registry[i]; try { entry.initFn(root, reason); } catch (err) { console.error('[AKSRT Rehydrate] Error initializing "' + entry.name + '":', err); } } // Dispatch event so external scripts can hook in try { root.dispatchEvent(new CustomEvent('aksrt:rehydrated', { bubbles: true, detail: { reason: reason } })); } catch (e) { /* IE fallback */ } }, /** * Get the list of registered component names (for debugging). */ getRegistered: function () { return _registry.map(function (r) { return r.name; }); } }; })(); ; /* source: assets/js/notyf.js */ /** * legacy-compatible frontend notifications. * * @package AKSRT */ (function ($, window, document) { 'use strict'; function closeNotyf($element) { $element.addClass('notyn-out'); window.setTimeout(function () { $element.remove(); }, 1000); } function notyf(message, type, time, id) { var $body = $(document.body); if (!$('.notyn').length) { $body.append('
'); } type = type || 'success'; if (type === 'error') { type = 'danger'; } time = time || 5000; time = time < 100 ? time * 1000 : time; var idAttribute = id ? ' id="' + id + '"' : ''; var $notification = $('错误信息
var match = html.match(/]*>([^<]+)<\/p>/i); return match ? match[1].trim() : '未知错误'; } // 从错误消息中提取等待时间(秒) function extractWaitTime(msg) { var match = msg.match(/(\d+)\s*秒/); return match ? parseInt(match[1]) : 0; } // 启动倒计时(用于频率限制) function startCountdown(seconds) { if (countdownTimer) clearInterval(countdownTimer); submitBtn.classList.add('countdown-active'); submitBtn.disabled = true; var remaining = seconds; countdownTimer = setInterval(function () { setSubmitBtnContent( ' 请等待 ' + remaining + 's', '请等待 ' + remaining + 's' ); if (--remaining <= 0) { clearInterval(countdownTimer); countdownTimer = null; submitBtn.classList.remove('countdown-active', 'is-loading'); submitBtn.disabled = false; setSubmitBtnContent(originalBtnHTML, originalBtnHTML); isSubmitting = false; } }, 1000); } function updateCommentCount(delta) { var countEl = document.querySelector('#comments .title-theme small'); if (!countEl) return; var text = countEl.textContent || ''; var match = text.match(/(\d+)/); if (!match) return; var nextCount = Math.max(0, parseInt(match[1], 10) + delta); countEl.textContent = text.replace(match[1], String(nextCount)); } function handleResponse(responseText, statusCode) { try { // 情况1: 成功提交 - 包含评论ID或成功标记 if (statusCode === 200 || statusCode === 201) { if (responseText.includes('comment-submitted') || responseText.indexOf('id="comment-') !== -1 || responseText.indexOf('awaiting-moderation') !== -1) { // 区分是否需要审核 if (responseText.indexOf('审核') !== -1 || responseText.indexOf('moderation') !== -1 || responseText.includes('awaiting-moderation')) { notyf('评论已提交,等待管理员审核', 'info'); } else { notyf('评论发布成功', 'success'); } // 清空文本框 var textarea = form.querySelector('#comment'); if (textarea) textarea.value = ''; // 重置回复状态 var replyInfo = document.getElementById('comment-reply-info'); if (replyInfo) replyInfo.style.display = 'none'; // 刷新评论列表(延迟执行,确保后端处理完成) setTimeout(function () { reloadCommentList(); }, 500); setLoading(false); return true; } } // 情况2: HTTP 429 频率限制 if (statusCode === 429) { var errorMsg = extractErrorMessage(responseText); var waitSeconds = extractWaitTime(errorMsg); notyf(errorMsg, 'warning'); if (waitSeconds > 0) { startCountdown(waitSeconds); } else { setLoading(false); // 无具体等待时间时恢复按钮 } return false; } // 情况3: HTTP 403 权限不足(地区/IP/关键词等) if (statusCode === 403) { var forbiddenMsg = extractErrorMessage(responseText); notyf(forbiddenMsg, 'danger'); setLoading(false); return false; } // 情况4: 包含WordPress错误信息 var errorMatch = responseText.match(/
]*>([^<]*(?:错误|失败|error|Error)[^<]*)<\/p>/i); if (errorMatch) { notyf(errorMatch[1].trim(), 'danger'); setLoading(false); return false; } // 默认情况:可能是成功或其他 notyf('评论已提交', 'success'); var textarea2 = form.querySelector('#comment'); if (textarea2) textarea2.value = ''; // 局部刷新评论列表(不再整页 reload) setTimeout(function () { reloadCommentList(); }, 500); setLoading(false); return true; } catch (e) { console.error('[AKSRT Comment] 解析响应失败:', e); notyf('响应解析异常,请重试', 'danger'); setLoading(false); return false; } } // 执行实际的 AJAX 请求 — local insert instead of full-page re-fetch function performSubmit() { setLoading(true); var formData = collectFormData(); var restRoot = (window.aksrtData && aksrtData.siteUrl) ? String(aksrtData.siteUrl).replace(/\/$/, '') : ''; var editId = form.querySelector('[name="edit_comment_ID"]'); var isEdit = editId && parseInt(editId.value, 10) > 0; var restBase = (restRoot || '') + '/wp-json/aksrt/v1/comment/' + (isEdit ? 'edit' : 'submit'); // Try REST endpoint for local-insert HTML response var restBody = {}; formData.forEach(function (v, k) { restBody[k] = v; }); if (isEdit) { restBody.comment_id = parseInt(editId.value, 10); restBody.content = restBody.comment || restBody.content || ''; } fetch(restBase, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': (window.aksrtData && aksrtData.restNonce) || '' }, credentials: 'same-origin', body: JSON.stringify(restBody) }) .then(function (r) { return r.json(); }) .then(function (json) { if (isEdit && json && json.success) { var cid = restBody.comment_id; var contentEl = document.querySelector('#comment-content-' + cid + ', [data-comment-id="' + cid + '"] .comment-content'); var rendered = (json.data && json.data.content) || json.content || ''; if (contentEl && rendered) contentEl.innerHTML = rendered; var textarea = form.querySelector('#comment'); if (textarea) textarea.value = ''; if (editId) editId.remove(); restoreRespondPosition(); setLoading(false); notyf(json.message || '评论已更新', 'success'); var respondEl = document.getElementById('respond'); if (respondEl && window.AksrtFixedInput) window.AksrtFixedInput(respondEl, 'hide'); return; } if (json && json.success && json.html) { // Local insert: prepend new comment HTML localInsertComment(json.html, json.is_reply, json.parent_id, json.needs_moderation); var textarea = form.querySelector('#comment'); if (textarea) textarea.value = ''; var replyInfo = document.getElementById('comment-reply-info'); if (replyInfo) replyInfo.style.display = 'none'; // Reset captcha after successful submit try { var captchaScene = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes && window.AKSRTCaptchaState.scenes.comment; if (captchaScene && typeof captchaScene.reset === 'function') { captchaScene.reset(); } } catch (e) { /* ignore */ } // Wait time countdown if (json.wait_time && json.wait_time > 0) { startCountdown(json.wait_time); } else { setLoading(false); } // Move respond back to original position restoreRespondPosition(); // Hide mobile FixedInput after successful submit. var respondEl = document.getElementById('respond'); if (respondEl && window.AksrtFixedInput) { window.AksrtFixedInput(respondEl, 'hide'); } else if (respondEl) { respondEl.classList.remove('show'); } // If editing via moveForm, clear edit field. var editField = form.querySelector('[name="edit_comment_ID"]'); if (editField) editField.remove(); return; } if (json && json.code) { notyf(json.message || '评论提交失败', 'danger'); try { var failScene = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes && window.AKSRTCaptchaState.scenes.comment; if (failScene && typeof failScene.reset === 'function') { failScene.reset(); } } catch (e) { /* ignore */ } if (json.wait_time) startCountdown(json.wait_time); else setLoading(false); return; } notyf('评论已提交', 'success'); setLoading(false); setTimeout(function () { reloadCommentList(); }, 500); }) .catch(function () { // Fallback: submit to wp-comments-post.php directly performLegacySubmit(); }); } function localInsertComment(html, isReply, parentId, needsModeration) { var temp = document.createElement('div'); temp.innerHTML = html; var newComment = temp.firstElementChild; if (!newComment) { reloadCommentList(); return; } newComment.style.overflow = 'hidden'; newComment.style.maxHeight = '0'; newComment.style.opacity = '0'; newComment.style.transition = 'max-height 0.4s ease, opacity 0.3s ease'; if (isReply && parentId) { var parentComment = document.querySelector('#comment-' + parentId); if (parentComment) { var children = parentComment.querySelector(':scope > .children'); if (!children) { children = document.createElement('ol'); children.className = 'children'; parentComment.appendChild(children); } children.insertBefore(newComment, children.firstChild); } else { prependToCommentList(newComment); } } else { prependToCommentList(newComment); } // slideDown animation requestAnimationFrame(function () { newComment.style.maxHeight = newComment.scrollHeight + 100 + 'px'; newComment.style.opacity = '1'; setTimeout(function () { newComment.style.maxHeight = ''; newComment.style.overflow = ''; newComment.style.transition = ''; }, 500); }); if (needsModeration) { notyf('评论已提交,等待管理员审核', 'info'); } else { notyf('评论发布成功', 'success'); } if (window.AksrtFrontend) AksrtFrontend.rehydrate(newComment, 'ajax'); updateCommentCount(1); } function prependToCommentList(el) { var list = document.querySelector('#comments .commentlist'); if (!list) return; // 插到筛选栏之后、最新评论之前 var filter = list.querySelector('.comment-filter'); if (filter && filter.nextSibling) { list.insertBefore(el, filter.nextSibling); } else { list.insertBefore(el, list.firstChild); } } function restoreRespondPosition() { var respond = document.getElementById('respond'); var placeholder = document.getElementById('wp-temp-form-div'); if (respond && placeholder && placeholder.parentNode) { placeholder.parentNode.insertBefore(respond, placeholder); placeholder.remove(); } } // Legacy fallback: POST to wp-comments-post.php function performLegacySubmit() { var formData = collectFormData(); var actionUrl = form.getAttribute('action') || '/wp-comments-post.php'; fetch(actionUrl, { method: 'POST', body: formData, credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(function (response) { return response.text().then(function (text) { return { status: response.status, text: text, ok: response.ok }; }); }) .then(function (result) { handleResponse(result.text, result.status); }) .catch(function (error) { console.error('[AKSRT Comment] 提交失败:', error); if (error.message === 'Failed to fetch' || error.name === 'TypeError') { notyf('网络连接失败,请检查网络后重试', 'danger'); } else { notyf(error.message || '评论提交失败,请重试', 'danger'); } setLoading(false); }) .finally(function () { // 兜底:避免异常分支漏掉状态恢复导致按钮卡在"发送中" if (!countdownTimer && isSubmitting) { setLoading(false); } }); } // 核心表单提交事件处理器 function handleSubmit(e) { // 如果已经在提交中或倒计时中,防止重复提交 if (isSubmitting || countdownTimer) { e.preventDefault(); e.stopImmediatePropagation(); return false; } // 阻止默认表单提交 e.preventDefault(); e.stopImmediatePropagation(); // 检查验证码状态(如果有验证码组件) var captchaScene = window.AKSRTCaptchaState && window.AKSRTCaptchaState.scenes && window.AKSRTCaptchaState.scenes.comment; if (captchaScene && typeof captchaScene.verify === 'function') { // 有验证码:先触发验证流程 setLoading(true); captchaScene.verify(function (verified) { if (verified !== false) { // 验证通过,执行 AJAX 提交 performSubmit(); } else { // 验证失败 notyf('人机验证未通过,请重试', 'warning'); setLoading(false); } }); } else { // 无验证码或已经验证过:直接提交 performSubmit(); } return false; } // 绑定表单提交事件(使用捕获阶段,高优先级) form.addEventListener('submit', handleSubmit, true); } function getCommentsRestBase() { var root = (window.aksrtData && aksrtData.siteUrl) ? String(aksrtData.siteUrl).replace(/\/$/, "") : ""; return root + "/wp-json/aksrt/v1"; } function getCurrentCommentPostId() { var input = document.querySelector('input[name="comment_post_ID"]'); if (input && input.value) return parseInt(input.value, 10) || 0; var comments = document.getElementById("comments"); if (comments && comments.dataset.postId) return parseInt(comments.dataset.postId, 10) || 0; return 0; } function getCurrentCommentOrder() { var active = document.querySelector("#comments .comment-order-box li.active .comment-orderby"); if (active && active.dataset && active.dataset.order) return active.dataset.order; var url = new URL(window.location.href); return url.searchParams.get("aksrt_comment_order") || "newest"; } function getCurrentAuthorOnly() { var url = new URL(window.location.href); if (url.searchParams.get("aksrt_author_only") === "1") return true; var btn = document.querySelector("#comments .btn-only-author"); return !!(btn && btn.classList.contains("active") && btn.dataset.authorOnly === "0"); } function applyFragmentPayload(commentsArea, data, urlState) { if (!commentsArea || !data || !data.html) return; // data.html 是完整的
" + emptyText + "
"; wrap.appendChild(noResults); } function fetchPosts(pushState) { showLoading(); fetch(buildUrl(), { method: "GET", headers: { Accept: "application/json" }, credentials: "same-origin" }) .then(function (r) { if (!r.ok) throw new Error("HTTP " + r.status); return r.json(); }) .then(function (data) { hideLoading(); if (data.html !== undefined) { var children = Array.from(wrap.children); children.forEach(function (child) { if (child !== loading) wrap.removeChild(child); }); if (data.html) { var temp = document.createElement("div"); temp.innerHTML = data.html; while (temp.firstChild) wrap.appendChild(temp.firstChild); } else { rebuildEmptyState(); } if (window.AksrtFrontend) AksrtFrontend.rehydrate(wrap, "ajax"); } if (pushState !== false) { var url = new URL(window.location.href); url.searchParams.delete("orderby"); url.searchParams.delete("order"); url.searchParams.delete("paged"); url.searchParams.delete("aksrt_filter_cat"); url.searchParams.delete("aksrt_filter_tag"); if (state.filter_cat) url.searchParams.set("aksrt_filter_cat", state.filter_cat); if (state.filter_tag) url.searchParams.set("aksrt_filter_tag", state.filter_tag); if (state.sort) url.searchParams.set("orderby", state.sort); if (state.page > 1) url.searchParams.set("paged", String(state.page)); history.pushState({ aksrtArchive: true, state: Object.assign({}, state) }, "", url.toString()); } }) .catch(function () { hideLoading(); }); } bar.addEventListener("click", function (e) { var chip = e.target.closest("[data-filter-cat], [data-filter-tag], [data-filter-sort]"); if (!chip) return; e.preventDefault(); var changed = false; if (chip.dataset.filterCat !== undefined) { var newCat = chip.dataset.filterCat; if (newCat !== state.filter_cat) { state.filter_cat = newCat; changed = true; } } if (chip.dataset.filterTag !== undefined) { var newTag = chip.dataset.filterTag; if (newTag !== state.filter_tag) { state.filter_tag = newTag; changed = true; } } if (chip.dataset.filterSort !== undefined) { var newSort = chip.dataset.filterSort || "date"; if (newSort !== state.sort) { state.sort = newSort; changed = true; } } if (changed) { state.page = 1; updateActiveChips(); fetchPosts(true); } }); wrap.addEventListener("click", function (e) { var pageLink = e.target.closest(".pagination a, .nav-links a, a.page-numbers"); if (!pageLink || !wrap.contains(pageLink)) return; var href = pageLink.getAttribute("href"); if (!href) return; var match = href.match(/[?&]paged=(\d+)/); if (match) { e.preventDefault(); state.page = parseInt(match[1], 10) || 1; fetchPosts(true); } }); window.addEventListener("popstate", function (e) { if (e.state && e.state.aksrtArchive) { state = Object.assign(state, e.state.state); updateActiveChips(); fetchPosts(false); } }); } window.AksrtFrontend.register("aksrt-archive-filter", function (root) { initArchiveFilter(root); }); })(); ; /* source: assets/js/core/footer-tabbar.js */ /** * AKSRT Footer Tabbar */ (function () { "use strict"; function initFooterTabbar() { var tabbar = document.getElementById("footer-tabbar"); if (!tabbar) return; var addBackdrop = document.getElementById("tabbar-add-backdrop"); var ticking = false; var scrollThreshold = 100; var isHidden = false; // Use body scroll bus classes from aksrt-runtime.js function handleScrollDownHide() { var body = document.body; var scrollTop = window.pageYOffset || document.documentElement.scrollTop; if (scrollTop > scrollThreshold) { if (body.classList.contains("scroll-down") && !isHidden) { // 向下滚动 - 隐藏 tabbar.classList.add("is-hidden"); isHidden = true; } else if (body.classList.contains("scroll-up") && isHidden) { tabbar.classList.remove("is-hidden"); isHidden = false; } } else { tabbar.classList.remove("is-hidden"); isHidden = false; } } // 返回顶部按钮切换 function handleOntopWrap() { var ontopWraps = tabbar.querySelectorAll(".tabbar-ontop-wrap"); var scrollTop = window.pageYOffset || document.documentElement.scrollTop; ontopWraps.forEach(function (wrap) { if (scrollTop > scrollThreshold) { wrap.classList.add("is-scrolled"); } else { wrap.classList.remove("is-scrolled"); } }); } // 滚动事件处理 function onScroll() { if (!ticking) { requestAnimationFrame(function () { if (tabbar.classList.contains("scroll-down-hide")) { handleScrollDownHide(); } handleOntopWrap(); ticking = false; }); ticking = true; } } window.addEventListener("scroll", onScroll, { passive: true }); function closeAddPanels() { document.querySelectorAll(".tabbar-add-panel").forEach(function (panel) { panel.setAttribute("hidden", ""); }); if (addBackdrop) addBackdrop.setAttribute("hidden", ""); document.body.classList.remove("tabbar-add-open"); } function openAddPanel(panelId) { closeAddPanels(); var panel = document.getElementById(panelId); if (!panel) return; panel.removeAttribute("hidden"); if (addBackdrop) addBackdrop.removeAttribute("hidden"); document.body.classList.add("tabbar-add-open"); } if (addBackdrop) { addBackdrop.addEventListener("click", closeAddPanels); } document.addEventListener("keydown", function (e) { if (e.key === "Escape") closeAddPanels(); }); // 返回顶部点击事件 + 双击首页刷新 var homeClickTimer = null; tabbar.addEventListener("click", function (e) { var addBtn = e.target.closest('.tabbar-item[data-type="add"]'); if (addBtn) { e.preventDefault(); openAddPanel(addBtn.getAttribute("data-panel-id")); return; } var searchBtn = e.target.closest('.tabbar-item[data-type="search"]'); if (searchBtn) { e.preventDefault(); if (typeof window.__aksrtOpenSearchPanel === "function") { window.__aksrtOpenSearchPanel(); } return; } var ontopBtn = e.target.closest(".tabbar-ontop-btn"); if (ontopBtn) { e.preventDefault(); window.scrollTo({ top: 0, behavior: "smooth" }); return; } // 双击首页Tab刷新页面 var homeBtn = e.target.closest('.tabbar-item[data-type="home"]'); if (homeBtn && tabbar.classList.contains("has-animation")) { if (homeClickTimer) { clearTimeout(homeClickTimer); homeClickTimer = null; window.location.reload(); return; } homeClickTimer = setTimeout(function () { homeClickTimer = null; }, 350); } }); document.addEventListener("click", function (e) { if (e.target.closest("[data-close-tabbar-add-panel]")) { closeAddPanels(); } }); } window.AksrtFrontend.register("aksrt-footer-tabbar", function () { initFooterTabbar(); }); })(); ; /* source: assets/js/core/misc.js */ /** * AKSRT Misc — related swiper, slide covers, hidden content */ (function () { "use strict"; function renderGradientBackground(container) { if (!container || container.dataset.aksrtGradientState || typeof window.Grade !== "function") return; var source = container.querySelector("img"); if (!source || (!source.classList.contains("lazyloaded") && !(source.complete && source.naturalWidth > 0))) return; container.dataset.aksrtGradientState = "loading"; window.Grade(container, null, function (result) { var gradientData = result && result[0]; var colors = gradientData && gradientData.gradientData; if (!gradientData || !colors || !colors[0] || !colors[1]) { delete container.dataset.aksrtGradientState; return; } var opacity = container.getAttribute("data-opacity"); var colorName = opacity ? "rgba" : "rgb"; var alpha = opacity ? "," + opacity : ""; var color1 = colorName + "(" + colors[0].rgba.slice(0, 3).join(",") + alpha + ") 10%"; var color2 = colorName + "(" + colors[1].rgba.slice(0, 3).join(",") + alpha + ") 80%"; gradientData.element.classList.add("gradient-bg-loaded"); gradientData.element.style.backgroundImage = "linear-gradient(135deg, " + color1 + ", " + color2 + ")"; container.dataset.aksrtGradientState = "loaded"; }); } function initGradientBackgrounds(root) { var scope = root || document; if (scope.nodeType === 1 && scope.matches(".gradient-bg")) { renderGradientBackground(scope); } scope.querySelectorAll(".gradient-bg").forEach(renderGradientBackground); } document.addEventListener("lazyloaded", function (event) { if (!(event.target instanceof Element) || !event.target.matches(".gradient-bg img")) return; renderGradientBackground(event.target.closest(".gradient-bg")); }, true); function initPostThumbMedia(root) { var scope = root || document; scope.querySelectorAll("[data-post-thumb-video]").forEach(function (box) { if (box.dataset.aksrtThumbVideoBound === "1") return; box.dataset.aksrtThumbVideoBound = "1"; var video = box.querySelector("video"); if (!video) return; function loadVideo() { if (!video.getAttribute("src") && video.dataset.src) { video.setAttribute("src", video.dataset.src); video.load(); } } function playVideo() { loadVideo(); var result = video.play(); var postItem = box.closest(".posts-item"); if (postItem) postItem.classList.add("thumb-dplayer-playing"); if (result && typeof result.catch === "function") result.catch(function () {}); } function pauseVideo() { video.pause(); var postItem = box.closest(".posts-item"); if (postItem) postItem.classList.remove("thumb-dplayer-playing"); } var item = box.closest(".item-thumbnail") || box; item.addEventListener("mouseenter", playVideo); item.addEventListener("mouseleave", pauseVideo); item.addEventListener("focusin", playVideo); item.addEventListener("focusout", pauseVideo); }); } window.AksrtFrontend.register("aksrt-post-thumb-media", function (root) { initPostThumbMedia(root); initGradientBackgrounds(root); }); })(); (function () { "use strict"; function initSlideCovers() { var covers = document.querySelectorAll(".single-cover--slide"); covers.forEach(function (cover) { var slides = cover.querySelectorAll(".single-cover__slide"); var dots = cover.querySelectorAll(".single-cover__dot"); if (slides.length < 2) return; var current = 0; var interval = 5000; function goTo(idx) { slides[current].classList.remove("is-active"); if (dots[current]) dots[current].classList.remove("is-active"); current = idx; slides[current].classList.add("is-active"); if (dots[current]) dots[current].classList.add("is-active"); } var timer = setInterval(function () { goTo((current + 1) % slides.length); }, interval); dots.forEach(function (dot, i) { dot.addEventListener("click", function () { clearInterval(timer); goTo(i); timer = setInterval(function () { goTo((current + 1) % slides.length); }, interval); }); }); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initSlideCovers); } else { initSlideCovers(); } })(); (function () { "use strict"; function initHiddenContent() { document.addEventListener("click", function (e) { var btn = e.target.closest(".aksrt-hidden-content__submit-btn"); if (!btn) return; e.preventDefault(); var wrapper = btn.closest(".aksrt-hidden-content--locked"); if (!wrapper) return; var mode = wrapper.getAttribute("data-aksrt-visibility-mode"); var pid = wrapper.getAttribute("data-aksrt-visibility-pid"); var input = wrapper.querySelector(".aksrt-hidden-content__password-input"); var password = input ? input.value.trim() : ""; if (mode === "password" && !password) { if (input) input.focus(); return; } var formData = new FormData(); formData.append("action", "aksrt_check_visibility"); formData.append("_nonce", (window.aksrtData && aksrtData.visibilityNonce) || ""); formData.append("mode", mode); formData.append("pid", pid); if (password) formData.append("password", password); btn.disabled = true; btn.textContent = "..."; fetch((window.aksrtData && aksrtData.ajaxUrl) || "/wp-admin/admin-ajax.php", { method: "POST", body: formData, credentials: "same-origin", }) .then(function (res) { return res.json(); }) .then(function (data) { if (data.success) { window.location.reload(); } else { var msg = (data.data && data.data.message) ? data.data.message : "验证失败"; alert(msg); btn.disabled = false; btn.textContent = "验证"; } }) .catch(function () { alert("网络错误,请重试"); btn.disabled = false; btn.textContent = "验证"; }); }); // Handle Enter key on password input document.addEventListener("keydown", function (e) { if (e.key === "Enter" && e.target.classList.contains("aksrt-hidden-content__password-input")) { e.preventDefault(); var wrapper = e.target.closest(".aksrt-hidden-content--locked"); if (wrapper) { var btn = wrapper.querySelector(".aksrt-hidden-content__submit-btn"); if (btn) btn.click(); } } }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initHiddenContent); } else { initHiddenContent(); } })(); ; /* source: assets/js/follow.js */ /** * AKSRT Follow — 前台关注交互 * * 监听 [data-aksrt-follow] 按钮点击,切换关注状态。 * * @package AKSRT */ (function () { 'use strict'; var API_ROOT = (function () { var d = window.aksrtData || {}; var raw = d.apiUrl || d.restUrl || d.rest_url || '/index.php?rest_route=/aksrt/v1'; return String(raw).replace(/\/$/, ''); })(); var NONCE = (window.aksrtData && window.aksrtData.restNonce) || ''; // 初始关注状态由服务端渲染(is-following class + 文案),无需逐按钮查询。 function initFollowButtons() { document.addEventListener('click', function (e) { var btn = e.target.closest('[data-aksrt-follow]'); if (!btn) return; e.preventDefault(); var targetUserId = parseInt(btn.getAttribute('data-aksrt-follow')); if (!targetUserId) return; btn.disabled = true; fetch(API_ROOT + '/follow/toggle', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': NONCE, }, body: JSON.stringify({ target_user_id: targetUserId }), }) .then(function (res) { return res.json(); }) .then(function (result) { if (result.success && result.data) { var isFollowing = result.data.is_following; updateFollowButton(btn, isFollowing, result.data.follower_count); notyf(isFollowing ? '关注成功' : '已取消关注', 'success'); } else { notyf(result.message || '操作失败', 'danger'); } }) .catch(function () { notyf('网络错误,请重试', 'danger'); }) .finally(function () { btn.disabled = false; }); }); } function updateFollowButton(btn, isFollowing, count) { var icon = btn.querySelector('i'); var text = btn.querySelector('span'); function setLabel(label) { if (text) { text.textContent = label; return; } // Fallback when markup has bare text nodes next to the icon. var nodes = Array.prototype.slice.call(btn.childNodes); var textNode = nodes.filter(function (n) { return n.nodeType === 3 && n.textContent.trim() !== ''; })[0]; if (textNode) { textNode.textContent = ' ' + label + ' '; } } if (isFollowing) { btn.classList.add('is-following'); if (icon) icon.className = 'fa fas fa-heart'; setLabel('已关注'); btn.title = '点击取消关注'; } else { btn.classList.remove('is-following'); if (icon) icon.className = 'fa fas fa-heart'; setLabel('关注'); btn.title = '关注该用户'; } if (!isFollowing && btn.closest('.uc-follow-management__item')) { btn.closest('.uc-follow-management__item').remove(); } // Update follower count display if exists var countEl = document.querySelector('.aksrt-user-home__stat-value[data-followers]'); if (countEl && count !== undefined) { countEl.textContent = count; } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initFollowButtons); } else { initFollowButtons(); } })(); ; /* source: assets/js/enhancements.js */ /** * AKSRT Enhancements — 全局 UI 增强 * * 包含:图片灯箱、滚动方向感知 * * @package AKSRT */ (function () { 'use strict'; /* ============================================================ * 1. 图片灯箱 — zoom / thumbnails / slideshow / fullscreen / * mousewheel / origin animation / smart download * ============================================================ */ var lightboxEl = null; var lightboxImg = null; var lightboxCaption = null; var lightboxCounter = null; var lightboxThumbsWrap = null; var currentGallery = []; var currentIndex = 0; var currentZoom = 1; var autoplayTimer = null; var isAutoplay = false; var EXCLUDE_SEL = '.no-imgbox,.no-lightbox,.avatar,.img-icon,.avatar-badge,.smilie-icon,.aksrt-avatar'; var TRIGGER_SEL = '.entry-content img, .wp-posts-content img, .aksrt-lightbox-trigger img, [data-aksrt-lightbox] img, .imgbox-container img, .comment-content .box-img img, a[data-imgbox] img'; var CONTAINER_SEL = '.entry-content, .wp-posts-content, .aksrt-lightbox-trigger, [data-aksrt-lightbox], .imgbox-container, .comment-content'; var MAX_ZOOM_DESKTOP = 2; var MAX_ZOOM_MOBILE = 3; function lightboxFlag(key, fallback) { var w = window._win || (window.aksrtData && window.aksrtData.imgbox) || {}; if (w[key] === undefined || w[key] === null || w[key] === '') return fallback; return w[key] === true || w[key] === 1 || w[key] === '1'; } function lightboxEnabled() { return lightboxFlag('imgbox', true); } function resolveFullUrl(img) { var full = img.getAttribute('data-full-url') || img.getAttribute('data-src') || ''; if (full) return full; var src = img.src || ''; // thumbnail → original: strip -NNNxNNN suffix return src.replace(/-\d+x\d+(\.[a-z]+)$/i, '$1'); } function isNoLightbox(img) { if (img.closest(EXCLUDE_SEL)) return true; // parent anchor that does NOT point to an image var parentA = img.closest('a'); if (parentA) { var href = parentA.getAttribute('href') || ''; if (href && !/\.(jpe?g|png|gif|webp|avif|svg|bmp)(\?|$)/i.test(href) && !parentA.hasAttribute('data-imgbox')) { return true; } } return false; } function createLightbox() { if (!lightboxEnabled()) return; if (lightboxEl) return; lightboxEl = document.createElement('div'); lightboxEl.className = 'aksrt-lightbox'; lightboxEl.innerHTML = '' + '' + '