Files
wordpress-theme-aksrt/assets/js/core/comments.js
T
kate522 5fd7c212ed fix(runtime): 按参考主题硬切换为 loader/main/auto_fun 单一 DOM 生命周期
- 删除 AksrtFrontend registry/rehydrate 双路架构及 build/public.js 拼包入口,
  前台唯一初始路径为 PHP 本地栈(jQuery 1.9.1 → Bootstrap 3.4.1)
  → loader_js(_win/aksrtData 唯一注入)→ tbquire(['main']) → runtime/main.min.js
- window.auto_fun = debounce(z_auto_fun, 100) 为唯一重扫入口;所有模块改为
  执行一次 + off/on('auto_fun.aksrt-*') 命名空间重扫,data/class 标记幂等
- 局部更新协议统一:HTML 注入 → post_ajax.ed → auto_fun();
  远程 modal → loaded.bs.modal → auto_fun();JSON 成功 → zib_ajax.success
- 灯箱恢复 Miniimgbox/imgbox 唯一 owner(imgbox-container、a[data-imgbox]、
  imgbox_data),删除 AksrtLightbox/data-aksrt-lightbox 第二实现及 CSS/overlay,
  _win.imgbox* 重新接上 post-display 设置
- 死代码清理:runtime 下 11 组被自有实现替代的旧模块副本、无消费 vendored 库、
  顶层 grade.min.js、revenue.js、无调用方的 aksrt_get_win_runtime_config(),
  以及 loader 中 16 条死 mapping
- PHP 入队改为本地栈 + loader_js,routed/widget/submit 依赖统一换绑;
  用户卡片发布按钮恢复 nav_user_newposts_btn 设置门控
- 测试对齐:新增 frontend-lifecycle-contract,重写 navigation/lazyload/toast/
  auth-source/comment/page-display/post-visual 等断言为目标架构契约

验证:node --test widget-system+navigation 223 通过 0 失败;
构建脚本重建 main/imgbox min 与 CSS bundles;改动 PHP php -l、JS node --check
全部通过;git diff --check 干净;credits 重入 harness 通过。
2026-09-03 12:44:31 +08:00

742 lines
26 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* AKSRT Comment System — AJAX submit, captcha, ordering, author filter
*/
(function () {
"use strict";
function initCommentSystem() {
var form = document.querySelector("#commentform");
if (!form || form.dataset.aksrtCommentInit === "1") return;
form.dataset.aksrtCommentInit = "1";
// 修复:同时匹配 button 和 input 元素
var submitBtn = form.querySelector('[type="submit"]');
if (!submitBtn) return;
var isInputSubmit = submitBtn.tagName === 'INPUT';
// 保存原始按钮内容(用于恢复)
var originalBtnHTML = isInputSubmit ? submitBtn.value : submitBtn.innerHTML;
function setSubmitBtnContent(html, textFallback) {
if (isInputSubmit) {
submitBtn.value = textFallback;
} else {
submitBtn.innerHTML = html;
}
}
// 状态管理
var isSubmitting = false;
var countdownTimer = null;
// 显示/隐藏加载状态
function setLoading(loading) {
if (loading) {
isSubmitting = true;
submitBtn.classList.add("is-loading");
submitBtn.disabled = true;
var loadingText = (window.aksrtData && aksrtData.commentSubmittingText) || '发送中...';
setSubmitBtnContent('<i class="fa fas fa-spinner fa-spin"></i> ' + loadingText, loadingText);
} else {
isSubmitting = false;
submitBtn.classList.remove("is-loading");
submitBtn.classList.remove('countdown-active');
submitBtn.disabled = false;
setSubmitBtnContent(originalBtnHTML, originalBtnHTML);
}
}
// 收集表单数据(包含验证码字段)
function collectFormData() {
var formData = new FormData(form);
// 确保包含必要的隐藏字段
var postId = document.querySelector('input[name="comment_post_ID"]');
if (postId && !formData.get('comment_post_ID')) {
formData.append('comment_post_ID', postId.value);
}
return formData;
}
// 从 wp_die() HTML 中提取错误信息
function extractErrorMessage(html) {
// WordPress wp_die() 输出格式: <p>错误信息</p>
var match = html.match(/<p[^>]*>([^<]+)<\/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(
'<i class="fa fas fa-clock"></i> 请等待 ' + 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(/<p[^>]*>([^<]*(?:错误|失败|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;
}
}
// 执行实际的 REST 请求 — local insert instead of full-page re-fetch
function performSubmit(captchaPayload) {
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; });
Object.assign(restBody, captchaPayload || {});
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';
// 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');
if (json.wait_time) startCountdown(json.wait_time);
else setLoading(false);
return;
}
notyf('评论已提交', 'success');
setLoading(false);
setTimeout(function () { reloadCommentList(); }, 500);
})
.catch(function (error) {
console.error('[AKSRT Comment] 提交失败:', error);
notyf((error && error.message) || '网络连接失败,请检查网络后重试', 'danger');
setLoading(false);
})
.finally(function () {
if (window.AKSRTCaptcha) window.AKSRTCaptcha.reset('comment', form);
if (!countdownTimer && isSubmitting) setLoading(false);
});
}
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');
}
// legacy 事件顺序:先 post_ajax.ed,再全局 auto_fun 重扫
newComment.dispatchEvent(new CustomEvent('post_ajax.ed', { bubbles: true }));
if (typeof window.auto_fun === 'function') window.auto_fun();
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();
}
}
// 核心表单提交事件处理器
function handleSubmit(e) {
// 如果已经在提交中或倒计时中,防止重复提交
if (isSubmitting || countdownTimer) {
e.preventDefault();
e.stopImmediatePropagation();
return false;
}
// 阻止默认表单提交
e.preventDefault();
e.stopImmediatePropagation();
var captcha = window.AKSRTCaptcha;
setLoading(true);
(captcha ? captcha.run('comment', form) : Promise.resolve({})).then(function (captchaPayload) {
if (captchaPayload === null) {
notyf('人机验证未通过,请重试', 'warning');
setLoading(false);
return;
}
performSubmit(captchaPayload);
}).catch(function () {
notyf('人机验证未通过,请重试', 'warning');
setLoading(false);
if (captcha) captcha.reset('comment', form);
});
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 btn = document.querySelector("#comments .btn-only-author");
return !!(btn && btn.classList.contains("active") && btn.dataset.authorOnly === "0");
}
/* ====== 全局无参数加载:评论状态仅保存在客户端,地址栏不携带 ? 参数 ====== */
var COMMENT_URL_PARAMS = ["cpage", "aksrt_comment_order", "aksrt_author_only"];
var commentUrlStateCleaned = false;
function stripCommentUrlParams() {
if (commentUrlStateCleaned || !window.history || typeof window.history.replaceState !== "function") return;
commentUrlStateCleaned = true;
var url = new URL(window.location.href);
var changed = false;
COMMENT_URL_PARAMS.forEach(function (key) {
if (url.searchParams.has(key)) {
url.searchParams.delete(key);
changed = true;
}
});
if (changed) {
// 服务端首屏已按参数渲染完毕,落地后地址栏回到无参干净链接。
window.history.replaceState(null, "", url.toString());
}
}
function getMaxCommentPages() {
var pagenav = document.querySelector("#comments .pagenav[data-max-pages]");
if (pagenav) {
var max = parseInt(pagenav.dataset.maxPages, 10);
if (max > 0) return max;
}
var jumpInput = document.querySelector("#comments .jump-input[max]");
if (jumpInput) {
var maxAttr = parseInt(jumpInput.getAttribute("max"), 10);
if (maxAttr > 0) return maxAttr;
}
return 1;
}
function parseCommentPageFromHref(href) {
if (!href || href === "#" || href.indexOf("javascript:") === 0) return 0;
try {
var url = new URL(href, window.location.href);
var cpage = parseInt(url.searchParams.get("cpage"), 10);
if (cpage > 0) return cpage;
var match = url.pathname.match(/\/comment-page-([0-9]{1,})\/?$/);
return match ? parseInt(match[1], 10) : 0;
} catch (e) {
return 0;
}
}
function scrollCommentsIntoView() {
var commentsArea = document.getElementById("comments");
if (!commentsArea || typeof commentsArea.scrollIntoView !== "function") return;
var rect = commentsArea.getBoundingClientRect();
if (rect.top >= 0 && rect.top < window.innerHeight * 0.6) return;
commentsArea.scrollIntoView({ behavior: "smooth", block: "start" });
}
function loadCommentPage(page, opts) {
opts = opts || {};
var commentsArea = document.getElementById("comments");
if (!commentsArea) {
return Promise.reject(new Error("comments area missing"));
}
var maxPages = getMaxCommentPages();
page = parseInt(page, 10) || 1;
page = Math.max(1, page);
if (maxPages > 1) page = Math.min(page, maxPages);
showListLoading(commentsArea);
return fetchCommentFragment({
order: getCurrentCommentOrder(),
authorOnly: getCurrentAuthorOnly(),
page: page
}).then(function (json) {
if (json && json.success && json.data) {
applyFragmentPayload(commentsArea, json.data);
if (!opts.noScroll) scrollCommentsIntoView();
return true;
}
throw new Error("comment fragment failed");
});
}
function applyFragmentPayload(commentsArea, data) {
if (!commentsArea || !data || !data.html) return;
// data.html 是完整的 <div id="postcomments">(含筛选、列表、分页)
var tempList = document.createElement("div");
tempList.innerHTML = data.html;
var newListWrap = tempList.querySelector("#postcomments");
if (!newListWrap) return;
var currentListWrap = commentsArea.querySelector("#postcomments");
if (currentListWrap) {
currentListWrap.replaceWith(newListWrap);
} else {
commentsArea.appendChild(newListWrap);
}
var currentCount = commentsArea.querySelector(".title-theme small");
if (currentCount && data.count_text) currentCount.textContent = data.count_text;
// legacy 事件顺序:先 post_ajax.ed,再全局 auto_fun 重扫
newListWrap.dispatchEvent(new CustomEvent("post_ajax.ed", { bubbles: true }));
if (typeof window.auto_fun === "function") window.auto_fun();
}
function fetchCommentFragment(opts) {
opts = opts || {};
var postId = opts.postId || getCurrentCommentPostId();
if (!postId) return Promise.reject(new Error("missing post id"));
var order = opts.order || getCurrentCommentOrder() || "newest";
var authorOnly = !!opts.authorOnly;
var page = opts.page || 1;
var qs = new URLSearchParams();
qs.set("post_id", String(postId));
qs.set("order", order);
qs.set("page", String(page));
if (authorOnly) qs.set("author_only", "1");
var url = getCommentsRestBase() + "/comment/list?" + qs.toString();
return fetch(url, {
method: "GET",
credentials: "same-origin",
headers: {
"X-WP-Nonce": (window.aksrtData && aksrtData.restNonce) || ""
}
}).then(function (r) { return r.json(); });
}
/* ====== 评论列表动态刷新 ====== */
function showListLoading(commentsArea) {
var list = commentsArea.querySelector(".commentlist");
if (!list) return;
// 保留筛选栏,清空条目并显示 legacy 骨架
var filter = list.querySelector(".comment-filter");
var loader = list.querySelector(".post_ajax_loader");
var skeleton = loader ? loader.cloneNode(true) : null;
Array.prototype.slice.call(list.children).forEach(function (child) {
if (child !== filter && child !== loader) child.remove();
});
if (skeleton) {
skeleton.style.display = "block";
skeleton.removeAttribute("hidden");
list.appendChild(skeleton);
}
}
function reloadCommentList() {
loadCommentPage(1, { noScroll: true }).catch(function (error) {
console.error('[AKSRT Comment] 刷新评论列表失败:', error);
window.location.reload();
});
}
/* ====== 评论排序(最新 / 最早) ====== */
/**
* Locate #id within the given scope.
* Document has getElementById; Element roots (AJAX panels) only have querySelector.
*/
function findInScope(scope, id) {
scope = scope || document;
if (!scope) return null;
if (scope.nodeType === 9) {
return scope.getElementById(id);
}
if (scope.nodeType === 1) {
if (scope.id === id) return scope;
return typeof scope.querySelector === "function"
? scope.querySelector("#" + id)
: null;
}
return null;
}
function initCommentOrder(root) {
var scope = root || document;
var commentsArea = findInScope(scope, "comments");
if (!commentsArea || commentsArea.dataset.orderInit === "1") return;
// Event delegation survives filter HTML replacement after AJAX refresh.
commentsArea.dataset.orderInit = "1";
function renderLoadingState() {
showListLoading(commentsArea);
}
function applyCommentOrder(order) {
if (order !== "newest" && order !== "oldest" && order !== "hottest") {
order = "newest";
}
renderLoadingState();
var authorOnly = getCurrentAuthorOnly();
fetchCommentFragment({ order: order, authorOnly: authorOnly, page: 1 })
.then(function (json) {
if (json && json.success && json.data) {
applyFragmentPayload(commentsArea, json.data);
return;
}
throw new Error("order fragment failed");
})
.catch(function (error) {
console.error("[AKSRT Comment] 排序刷新失败:", error);
// 兜底整页刷新,地址栏保持无参。
window.location.reload();
});
}
function applyAuthorFilter(authorOnlyFlag) {
renderLoadingState();
var authorOnly = authorOnlyFlag === "1" || authorOnlyFlag === 1 || authorOnlyFlag === true;
var order = getCurrentCommentOrder();
fetchCommentFragment({ order: order, authorOnly: authorOnly, page: 1 })
.then(function (json) {
if (json && json.success && json.data) {
applyFragmentPayload(commentsArea, json.data);
return;
}
throw new Error("author fragment failed");
})
.catch(function (error) {
console.error("[AKSRT Comment] Author filter failed:", error);
// 兜底整页刷新,地址栏保持无参。
window.location.reload();
});
}
commentsArea.addEventListener("click", function (e) {
var target = e.target;
if (!target || typeof target.closest !== "function") return;
// 「只看作者」同时带 comment-orderby,需优先于排序按钮判断
var authorBtn = target.closest(".btn-only-author");
if (authorBtn && commentsArea.contains(authorBtn)) {
e.preventDefault();
applyAuthorFilter(authorBtn.getAttribute("data-author-only") || "0");
return;
}
var orderBtn = target.closest(".comment-orderby[data-order]");
if (orderBtn && commentsArea.contains(orderBtn)) {
e.preventDefault();
applyCommentOrder(orderBtn.getAttribute("data-order") || "newest");
return;
}
// 数字分页:本地 DOM 刷新,地址栏不携带参数(href 仅作无 JS 兜底)。
var pageLink = target.closest(".pagenav a.page-numbers");
if (pageLink && commentsArea.contains(pageLink) && !pageLink.classList.contains("pag-jump")) {
var page = parseCommentPageFromHref(pageLink.getAttribute("href"));
if (page > 0) {
e.preventDefault();
loadCommentPage(page).catch(function (error) {
console.error("[AKSRT Comment] 分页刷新失败:", error);
// AJAX 不可用时退回原始链接(pretty 链接本身无 ? 参数)。
window.location.href = pageLink.href;
});
}
}
});
}
/* ====== 数字分页跳页(legacy pag-jump) ====== */
var commentPageJumpBound = false;
function jumpToCommentPage(page) {
loadCommentPage(page).catch(function (error) {
console.error("[AKSRT Comment] 跳页失败:", error);
window.location.reload();
});
}
function initCommentPageJump() {
if (commentPageJumpBound) return;
commentPageJumpBound = true;
document.addEventListener("click", function (e) {
var jump = e.target.closest ? e.target.closest("#comments .pag-jump") : null;
if (!jump) return;
e.preventDefault();
var input = jump.querySelector(".jump-input");
if (input) jumpToCommentPage(input.value);
});
document.addEventListener("keydown", function (e) {
if (e.key !== "Enter") return;
var input = e.target;
if (!input || !input.classList || !input.classList.contains("jump-input")) return;
if (!input.closest("#comments .pagenav")) return;
e.preventDefault();
jumpToCommentPage(input.value);
});
}
function init() {
stripCommentUrlParams();
initCommentSystem();
initCommentPageJump();
initCommentOrder();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
// AJAX 注入新内容后由 auto_fun 重扫(form/commentsArea 均带 data 标记,重复调用幂等)。
if (window.jQuery) {
window.jQuery(document).on("auto_fun", init);
}
// 供 pagination.js 等模块复用:评论页码加载 / 列表刷新(局部 DOM,无 ? 参数)。
window.AksrtComments = {
loadPage: function (page, opts) { return loadCommentPage(page, opts); },
reload: function () { reloadCommentList(); }
};
})();