/*! * Argon 主题核心 JavaScript */ // ========== 兼容性修复 ========== // 确保 Prism 和 autoloader 存在 if (typeof window.Prism === 'undefined') { window.Prism = { highlightAll: function() {}, highlightElement: function() {}, plugins: {} }; } if (typeof window.Prism.plugins === 'undefined') { window.Prism.plugins = {}; } if (typeof window.Prism.plugins.autoloader === 'undefined') { window.Prism.plugins.autoloader = { languages_path: '', use_minified: true }; } // 确保 Zoomify 存在 if (typeof window.Zoomify === 'undefined') { window.Zoomify = function() {}; window.Zoomify.DEFAULTS = {}; } // 确保 jQuery 插件存在 if (typeof jQuery !== 'undefined') { (function($) { // 确保 easing 函数存在(防止其他插件覆盖 jQuery 后丢失) if (typeof $.easing === 'undefined') { $.easing = {}; } if (typeof $.easing.easeOutCirc === 'undefined') { $.easing.easeOutCirc = function(x) { return Math.sqrt(1 - Math.pow(x - 1, 2)); }; } if (typeof $.easing.easeOutExpo === 'undefined') { $.easing.easeOutExpo = function(x) { return x === 1 ? 1 : 1 - Math.pow(2, -10 * x); }; } if (!$.fn._argonInit) { $.fn._argonInit = $.fn.init; $.fn.init = function(selector, context, root) { // 修复空选择器、特殊字符和中文标点导致的语法错误 if (typeof selector === 'string') { let trimmed = selector.trim(); // 检查是否为空或只有 # 符号 if (trimmed === '' || trimmed === '#') { return new $.fn._argonInit(); } // 检查是否包含中文标点(可能导致语法错误) if (/[;,。:!?]/.test(trimmed)) { console.warn('[Argon] Invalid selector with Chinese punctuation:', selector); return new $.fn._argonInit(); } // 检查 ID 选择器是否有效(#后面必须有内容) if (/^#\s*$/.test(trimmed)) { return new $.fn._argonInit(); } } return $.fn._argonInit.call(this, selector, context, root); }; $.fn.init.prototype = $.fn; } // 确保 zoomify 插件存在 if (typeof $.fn.zoomify === 'undefined') { $.fn.zoomify = function() { return this; }; } // 确保 fancybox 存在 if (typeof $.fancybox === 'undefined') { $.fancybox = { defaults: { transitionEffect: 'slide', buttons: [], lang: 'zh_CN', i18n: {} }, open: function() {}, close: function() {} }; } if (typeof $.fancybox.defaults === 'undefined') { $.fancybox.defaults = { transitionEffect: 'slide', buttons: [], lang: 'zh_CN', i18n: {} }; } // 确保 pjax 存在 if (typeof $.pjax === 'undefined') { $.pjax = function() {}; $.pjax.defaults = { timeout: 10000, container: [], fragment: [] }; } if (typeof $.pjax.defaults === 'undefined') { $.pjax.defaults = { timeout: 10000, container: [], fragment: [] }; } })(jQuery); } // ========================================================================== // 性能优化模块引入 // ========================================================================== // 注意:argon-performance.js 需要在此文件之前加载 // 在 functions.php 中通过 wp_enqueue_script 确保加载顺序 // // 提供的优化功能: // - ArgonDOMCache: DOM 元素缓存系统 // - ArgonEventManager: 事件节流和防抖 // - ArgonResourceLoader: 资源按需加载 // - ArgonRenderOptimizer: 渲染优化和 GPU 加速 // - ArgonMemoryManager: 内存管理和清理 // - ArgonPerformanceMonitor: 性能监控和分析 // ========================================================================== // ========== 原有代码 ========== if (typeof(argonConfig) == "undefined"){ var argonConfig = {}; } if (typeof(argonConfig.wp_path) == "undefined"){ argonConfig.wp_path = "/"; } // ========================================================================== // 性能优化模块实例(全局变量) // ========================================================================== var argonDOMCache = null; // DOM 缓存实例 var argonEventManager = null; // 事件管理实例 var argonResourceLoader = null; // 资源加载实例 var argonRenderOptimizer = null; // 渲染优化实例 var argonMemoryManager = null; // 内存管理实例 var argonPerformanceMonitor = null; // 性能监控实例 // ========================================================================== // 调试控制台(由 argon-performance.js 引入) // ========================================================================== // 如果 ArgonDebug 未定义,创建一个简单的替代实现 if (typeof ArgonDebug === 'undefined') { window.ArgonDebug = { enabled: false, init() { if (typeof argonConfig !== 'undefined' && argonConfig.debug_mode) { this.enabled = true; } }, log(...args) { if (this.enabled) console.log('[Argon]', ...args); }, warn(...args) { if (this.enabled) console.warn('[Argon]', ...args); }, error(...args) { if (this.enabled) console.error('[Argon]', ...args); }, info(...args) { if (this.enabled) console.info('[Argon]', ...args); } }; ArgonDebug.init(); } /*Cookies 操作*/ function setCookie(cname, cvalue, exdays) { let d = new Date(); d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); let expires = "expires=" + d.toUTCString(); document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; } function getCookie(cname) { let name = cname + "="; let decodedCookie = decodeURIComponent(document.cookie); let ca = decodedCookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } /*多语言支持*/ var translation = {}; translation['en_US'] = { "确定": "OK", "清除": "Clear", "恢复博客默认": "Set To Default", "评论内容不能为空": "Comment content cannot be empty", "昵称不能为空": "Name cannot be empty", "邮箱或QQ号格式错误": "Incorrect email or QQ format", "邮箱格式错误": "Incorrect email format", "网站格式错误 (不是 http(s):// 开头)": "Website URL format error", "验证码未输入": "CAPTCHA cannot be empty", "验证码格式错误": "Incorrect CAPTCHA format", "请完成验证码验证": "Please complete CAPTCHA verification", "评论格式错误": "Comment format error", "发送中": "Sending", "正在发送": "Sending", "评论正在发送中...": "Comment is sending...", "发送": "Send", "评论发送失败": "Comment failed", "发送成功": "Success", "您的评论已发送": "Your comment has been sent", "评论": "Comments", "未知原因": "Unknown Error", "编辑中": "Editing", "正在编辑": "Editing", "评论正在编辑中...": "Comment is being edited...", "编辑": "Edit", "评论编辑失败": "Comment editing failed", "已编辑": "Edited", "编辑成功": "Success", "您的评论已编辑": "Your comment has been edited", "评论 #": "Comment #", "的编辑记录": "- Edit History", "加载失败": "Failed to load", "展开": "Show", "没有更多了": "No more comments", "找不到该 Repo": "Can't find the repository", "获取 Repo 信息失败": "Failed to get repository information", "点赞失败": "Vote failed", "Hitokoto 获取失败": "Failed to get Hitokoto", "复制成功": "Copied", "代码已复制到剪贴板": "Code has been copied to the clipboard", "复制失败": "Failed", "请手动复制代码": "Please copy the code manually", "刚刚": "Now", "分钟前": "minutes ago", "小时前": "hours ago", "昨天": "Yesterday", "前天": "The day before yesterday", "天前": "days ago", "隐藏行号": "Hide Line Numbers", "显示行号": "Show Line Numbers", "开启折行": "Enable Break Line", "关闭折行": "Disable Break Line", "复制": "Copy", "全屏": "Fullscreen", "退出全屏": "Exit Fullscreen", "置顶评论": "Pin Comment", "取消置顶评论": "Unpin Comment", "是否要取消置顶评论 #": "Do you want to unpin the comment #", "是否要置顶评论 #": "Do you want to pin the comment #", "确认": "Confirm", "取消": "Cancel", "置顶": "Pin", "取消置顶": "Unpin", "置顶成功": "Pinned", "取消置顶成功": "Unpinned", "该评论已置顶": "The comment has been pinned", "该评论已取消置顶": "The comment has been unpinned", "置顶失败": "Failed to pin", "取消置顶失败": "Failed to unpin", }; translation['ru_RU'] = { "确定": "ОК", "清除": "Очистить", "恢复博客默认": "Восстановить по умолчанию", "评论内容不能为空": "Содержимое комментария не может быть пустым", "昵称不能为空": "Имя не может быть пустым", "邮箱或QQ号格式错误": "Неверный формат электронной почты или QQ", "邮箱格式错误": "Неправильный формат электронной почты", "网站格式错误 (不是 http(s):// 开头)": "Сайт ошибка формата URL-адреса ", "验证码未输入": "Вы не решили капчу", "验证码格式错误": "Ошибка проверки капчи", "评论格式错误": "Неправильный формат комментария", "发送中": "Отправка", "正在发送": "Отправка", "评论正在发送中...": "Комментарий отправляется...", "发送": "Отправить", "评论发送失败": "Не удалось отправить комментарий", "发送成功": "Комментарий отправлен", "您的评论已发送": "Ваш комментарий был отправлен", "评论": "Комментарии", "未知原因": "Неизвестная ошибка", "编辑中": "Редактируется", "正在编辑": "Редактируется", "评论正在编辑中...": "Комментарий редактируется", "编辑": "Редактировать", "评论编辑失败": "Не удалось отредактировать комментарий", "已编辑": "Изменено", "编辑成功": "Успешно", "您的评论已编辑": "Ваш комментарий был изменен", "评论 #": "Комментарий #", "的编辑记录": "- История изменений", "加载失败": "Ошибка загрузки", "展开": "Показать", "没有更多了": "Комментариев больше нет", "找不到该 Repo": "Невозможно найти репозиторий", "获取 Repo 信息失败": "Неудалось получить информацию репозитория", "点赞失败": "Ошибка голосования", "Hitokoto 获取失败": "Проблемы с вызовом Hitokoto", "复制成功": "Скопировано", "代码已复制到剪贴板": "Код скопирован в буфер обмена", "复制失败": "Неудалось", "请手动复制代码": "Скопируйте код вручную", "刚刚": "Сейчас", "分钟前": "минут назад", "小时前": "часов назад", "昨天": "Вчера", "前天": "Позавчера", "天前": "дней назад", "隐藏行号": "Скрыть номера строк", "显示行号": "Показать номера строк", "开启折行": "Включить перенос строк", "关闭折行": "Выключить перенос строк", "复制": "Скопировать", "全屏": "Полноэкранный режим", "退出全屏": "Выход из полноэкранного режима", }; translation['zh_TW'] = { "确定": "確定", "清除": "清除", "恢复博客默认": "恢復博客默認", "评论内容不能为空": "評論內容不能為空", "昵称不能为空": "昵稱不能為空", "邮箱或QQ号格式错误": "郵箱或QQ號格式錯誤", "邮箱格式错误": "郵箱格式錯誤", "网站格式错误 (不是 http(s):// 开头)": "網站格式錯誤 (不是 http(s):// 開頭)", "验证码未输入": "驗證碼未輸入", "验证码格式错误": "驗證碼格式錯誤", "评论格式错误": "評論格式錯誤", "发送中": "發送中", "正在发送": "正在發送", "评论正在发送中...": "評論正在發送中...", "发送": "發送", "评论发送失败": "評論發送失敗", "发送成功": "發送成功", "您的评论已发送": "您的評論已發送", "评论": "評論", "未知原因": "未知原因", "编辑中": "編輯中", "正在编辑": "正在編輯", "评论正在编辑中...": "評論正在編輯中...", "编辑": "編輯", "评论编辑失败": "評論編輯失敗", "已编辑": "已編輯", "编辑成功": "編輯成功", "您的评论已编辑": "您的評論已編輯", "评论 #": "評論 #", "的编辑记录": "的編輯記錄", "加载失败": "加載失敗", "展开": "展開", "没有更多了": "沒有更多了", "找不到该 Repo": "找不到該 Repo", "获取 Repo 信息失败": "獲取 Repo 信息失敗", "点赞失败": "點贊失敗", "Hitokoto 获取失败": "Hitokoto 獲取失敗", "复制成功": "復制成功", "代码已复制到剪贴板": "代碼已復制到剪貼板", "复制失败": "復制失敗", "请手动复制代码": "請手動復制代碼", "刚刚": "剛剛", "分钟前": "分鐘前", "小时前": "小時前", "昨天": "昨天", "前天": "前天", "天前": "天前", "隐藏行号": "隱藏行號", "显示行号": "顯示行號", "开启折行": "開啟折行", "关闭折行": "關閉折行", "复制": "復制", "全屏": "全屏", "退出全屏": "退出全屏", }; function __(text){ let lang = argonConfig.language; if (typeof(translation[lang]) == "undefined"){ return text; } if (typeof(translation[lang][text]) == "undefined"){ return text; } return translation[lang][text]; } /*根据滚动高度改变顶栏透明度 */ !function(){ let toolbar = document.getElementById("navbar-main"); let $bannerContainer = $("#banner_container"); let $content = $("#content"); let startTransitionHeight; let endTransitionHeight; let maxOpacity = 0.85; startTransitionHeight = $bannerContainer.offset().top - 75; endTransitionHeight = $content.offset().top - 75; $(window).resize(function(){ startTransitionHeight = $bannerContainer.offset().top - 75; endTransitionHeight = $content.offset().top - 75; }); function changeToolbarTransparency(){ let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop < startTransitionHeight){ toolbar.style.setProperty('background-color', 'rgba(var(--toolbar-color), 0)', 'important'); toolbar.style.setProperty('box-shadow', 'none'); if (argonConfig.toolbar_blur){ toolbar.style.setProperty('backdrop-filter', 'blur(0px)'); } toolbar.classList.add("navbar-ontop"); return; } if (scrollTop > endTransitionHeight){ toolbar.style.setProperty('background-color', 'rgba(var(--toolbar-color), ' + maxOpacity + ')', 'important'); toolbar.style.setProperty('box-shadow', ''); if (argonConfig.toolbar_blur){ toolbar.style.setProperty('backdrop-filter', 'blur(16px)'); } toolbar.classList.remove("navbar-ontop"); return; } let transparency = (scrollTop - startTransitionHeight) / (endTransitionHeight - startTransitionHeight) * maxOpacity; toolbar.style.setProperty('background-color', 'rgba(var(--toolbar-color), ' + transparency, 'important'); toolbar.style.setProperty('box-shadow', ''); if (argonConfig.toolbar_blur){ if ((scrollTop - startTransitionHeight) / (endTransitionHeight - startTransitionHeight) > 0.3){ toolbar.style.setProperty('backdrop-filter', 'blur(16px)'); }else{ toolbar.style.setProperty('backdrop-filter', 'blur(0px)'); } } toolbar.classList.remove("navbar-ontop"); } function changeToolbarOnTopClass(){ let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop < 30){ toolbar.classList.add("navbar-no-blur"); }else{ toolbar.classList.remove("navbar-no-blur"); } } if ($("html").hasClass("no-banner")) { changeToolbarOnTopClass(); // 使用节流优化滚动事件性能 const throttledChangeToolbarOnTopClass = argonEventManager ? argonEventManager.throttle(changeToolbarOnTopClass, 16) : changeToolbarOnTopClass; document.addEventListener("scroll", throttledChangeToolbarOnTopClass, {passive: true}); return; } if (argonConfig.headroom == "absolute") { toolbar.classList.add("navbar-ontop"); return; } if ($("html").hasClass("toolbar-blur")) { argonConfig.toolbar_blur = true; maxOpacity = 0.65; }else{ argonConfig.toolbar_blur = false; } changeToolbarTransparency(); // 使用节流优化滚动事件性能 const throttledChangeToolbarTransparency = argonEventManager ? argonEventManager.throttle(changeToolbarTransparency, 16) : changeToolbarTransparency; document.addEventListener("scroll", throttledChangeToolbarTransparency, {passive: true}); }(); /*搜索*/ function searchPosts(word){ if ($(".search-result").length > 0){ let url = new URL(window.location.href); url.searchParams.set("s", word); $.pjax({ url: url.href }); }else{ $.pjax({ url: argonConfig.wp_path + "?s=" + encodeURI(word) }); } } /*顶栏搜索*/ $(document).on("click" , "#navbar_search_input_container" , function(){ $(this).addClass("open"); $("#navbar_search_input").focus(); }); $(document).on("blur" , "#navbar_search_input_container" , function(){ // 如果有文字则保持has-text类 if ($("#navbar_search_input").val().trim() !== "") { $(this).addClass("has-text"); } else { $(this).removeClass("has-text"); } $(this).removeClass("open"); }); // 监听输入变化来切换has-text类 $(document).on("input" , "#navbar_search_input" , function(){ var container = $("#navbar_search_input_container"); if ($(this).val().trim() !== "") { container.addClass("has-text"); } else { container.removeClass("has-text"); } }); $(document).on("keydown" , "#navbar_search_input_container #navbar_search_input" , function(e){ if (e.keyCode != 13){ return; } let word = $(this).val(); if (word == ""){ $("#navbar_search_input_container").blur(); return; } let scrolltop = $(document).scrollTop(); searchPosts(word); }); /*顶栏搜索 (Mobile)*/ $(document).on("keydown" , "#navbar_search_input_mobile" , function(e){ if (e.keyCode != 13){ return; } let word = $(this).val(); $("#navbar_global .collapse-close button").click(); if (word == ""){ return; } let scrolltop = $(document).scrollTop(); searchPosts(word); }); /*侧栏搜索*/ $(document).on("click" , "#leftbar_search_container" , function(){ $(".leftbar-search-button").addClass("open"); $("#leftbar_search_input").removeAttr("readonly").focus(); $("#leftbar_search_input").focus(); $("#leftbar_search_input").select(); return false; }); $(document).on("blur" , "#leftbar_search_container" , function(){ $(".leftbar-search-button").removeClass("open"); $("#leftbar_search_input").attr("readonly", "readonly"); }); $(document).on("keydown" , "#leftbar_search_input" , function(e){ if (e.keyCode != 13){ return; } let word = $(this).val(); if (word == ""){ $("#leftbar_search_container").blur(); return; } $("html").removeClass("leftbar-opened"); searchPosts(word); }); /*搜索过滤器*/ $(document).on("change" , ".search-filter" , function(e){ if (pjaxLoading){ $(this).prop("checked", !$(this).prop("checked")); e.preventDefault(); return; } pjaxLoading = true; let postTypes = []; $(".search-filter:checked").each(function(){ postTypes.push($(this).attr("name")); }); if (postTypes.length == 0){ postTypes = ["none"]; } let url = new URL(document.location.href); url.searchParams.set("post_type", postTypes.join(",")); url.pathname = url.pathname.replace(/\/page\/\d+$/, ''); $.pjax({ url: url.href }); }); /*左侧栏随页面滚动浮动*/ !function(){ if ($("#leftbar").length == 0){ let contentOffsetTop = $('#content').offset().top; function changeLeftbarStickyStatusWithoutSidebar(){ let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if( contentOffsetTop - 10 - scrollTop <= 20 ){ document.body.classList.add('leftbar-can-headroom'); }else{ document.body.classList.remove('leftbar-can-headroom'); } } changeLeftbarStickyStatusWithoutSidebar(); // 使用节流优化滚动事件性能 const throttledChangeLeftbarStickyStatusWithoutSidebar = argonEventManager ? argonEventManager.throttle(changeLeftbarStickyStatusWithoutSidebar, 16) : changeLeftbarStickyStatusWithoutSidebar; document.addEventListener("scroll", throttledChangeLeftbarStickyStatusWithoutSidebar, {passive: true}); $(window).resize(function(){ contentOffsetTop = $('#content').offset().top; changeLeftbarStickyStatusWithoutSidebar(); }); return; } let $leftbarPart1 = $('#leftbar_part1'); let $leftbarPart2 = $('#leftbar_part2'); let leftbarPart1 = document.getElementById('leftbar_part1'); let leftbarPart2 = document.getElementById('leftbar_part2'); let leftbarPart3 = document.getElementById('leftbar_part3'); let part1OffsetTop = $('#leftbar_part1').offset().top; let part1OuterHeight = $('#leftbar_part1').outerHeight(); function changeLeftbarStickyStatus(){ let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if( part1OffsetTop + part1OuterHeight + 10 - scrollTop <= (argonConfig.headroom != "absolute" ? 90 : 18) ){ //滚动条在页面中间浮动状态 leftbarPart2.classList.add('sticky'); if (leftbarPart3) { leftbarPart3.classList.add('sticky'); // 计算可用空间并分配给 part2 和 part3 let viewportHeight = window.innerHeight; let topOffset = argonConfig.headroom !== 'absolute' ? 90 : 20; let availableHeight = viewportHeight - topOffset - 20; // 20px 底部边距 // 获取 part3 的自然高度(不受限制时的高度) leftbarPart3.style.maxHeight = 'none'; let part3NaturalHeight = leftbarPart3.scrollHeight; leftbarPart3.style.maxHeight = ''; // 最小高度限制 let minPart2Height = 150; let minPart3Height = 100; // 计算分配 let part2Height, part3MaxHeight; if (part3NaturalHeight + minPart2Height <= availableHeight) { // part3 可以完全显示 part3MaxHeight = part3NaturalHeight; part2Height = availableHeight - part3NaturalHeight - 10; } else { // 需要按比例分配,part2 占 60%,part3 占 40% part2Height = Math.max(minPart2Height, availableHeight * 0.6); part3MaxHeight = Math.max(minPart3Height, availableHeight - part2Height - 10); } document.documentElement.style.setProperty('--leftbar-part2-height', leftbarPart2.offsetHeight + 10 + 'px'); document.documentElement.style.setProperty('--leftbar-part3-height', part3MaxHeight + 'px'); document.documentElement.style.setProperty('--leftbar-part3-max-height', part3MaxHeight + 'px'); } }else{ //滚动条在顶部 不浮动状态 leftbarPart2.classList.remove('sticky'); if (leftbarPart3) leftbarPart3.classList.remove('sticky'); } if( part1OffsetTop + part1OuterHeight + 10 - scrollTop <= 20 ){//侧栏下部分是否可以随 Headroom 一起向上移动 document.body.classList.add('leftbar-can-headroom'); }else{ document.body.classList.remove('leftbar-can-headroom'); } } changeLeftbarStickyStatus(); // 使用节流优化滚动事件性能 const throttledChangeLeftbarStickyStatus = argonEventManager ? argonEventManager.throttle(changeLeftbarStickyStatus, 16) : changeLeftbarStickyStatus; document.addEventListener("scroll", throttledChangeLeftbarStickyStatus, {passive: true}); $(window).resize(function(){ part1OffsetTop = $leftbarPart1.offset().top; part1OuterHeight = $leftbarPart1.outerHeight(); changeLeftbarStickyStatus(); }); new MutationObserver(function(){ part1OffsetTop = $leftbarPart1.offset().top; part1OuterHeight = $leftbarPart1.outerHeight(); changeLeftbarStickyStatus(); }).observe(leftbarPart1, {attributes: true, childList: true, subtree: true}); }(); /*Headroom*/ if (argonConfig.headroom == "true"){ var headroom = new Headroom(document.querySelector("body"),{ "tolerance" : { up : 0, down : 0 }, "offset": 0, "classes": { "initial": "with-headroom", "pinned": "headroom---pinned", "unpinned": "headroom---unpinned", "top": "headroom---top", "notTop": "headroom---not-top", "bottom": "headroom---bottom", "notBottom": "headroom---not-bottom", "frozen": "headroom---frozen" } }).init(); } /*瀑布流布局*/ function waterflowInit() { if (argonConfig.waterflow_columns == "1") { return; } $("#main.article-list img").each(function(index, ele){ ele.onload = function(){ waterflowInit(); } }); let columns; if (argonConfig.waterflow_columns == "2and3") { if ($("#main").outerWidth() > 1000) { columns = 3; } else { columns = 2; } }else{ columns = parseInt(argonConfig.waterflow_columns); } if ($("#main").outerWidth() < 650 && columns == 2) { columns = 1; }else if ($("#main").outerWidth() < 800 && columns == 3) { columns = 1; } let heights = [0, 0, 0]; function getMinHeightPosition(){ let res = 0, minn = 2147483647; for (var i = 0; i < columns; i++) { if (heights[i] < minn) { minn = heights[i]; res = i; } } return res; } function getMaxHeight(){ let res = 0; for (let i in heights) { res = Math.max(res, heights[i]); } return res; } $("#primary").css("transition", "none") .addClass("waterflow"); let $container = $("#main.article-list"); if (!$container.length){ return; } let $items = $container.find("article.post:not(.no-results), .shuoshuo-preview-container"); columns = Math.max(Math.min(columns, $items.length), 1); if (columns == 1) { $container.removeClass("waterflow"); $items.css("transition", "").css("position", "").css("width", "").css("top", "").css("left", "").css("margin", ""); $(".waterflow-placeholder").remove(); }else{ $container.addClass("waterflow"); $items.each(function(index, item) { let $item = $(item); $item.css("transition", "none") .css("position", "absolute") .css("width", "calc(" + (100 / columns) + "% - " + (10 * (columns - 1) / columns) + "px)").css("margin", 0); let itemHeight = $item.outerHeight() + 10; let pos = getMinHeightPosition(); $item.css("top", heights[getMinHeightPosition()] + "px") .css("left", (pos * $item.outerWidth() + 10 * pos) + "px"); heights[pos] += itemHeight; }); } if ($(".waterflow-placeholder").length) { $(".waterflow-placeholder").css("height", getMaxHeight() + "px"); }else{ $container.prepend("
"); } } waterflowInit(); if (argonConfig.waterflow_columns != "1") { $(window).resize(function(){ waterflowInit(); }); new MutationObserver(function(mutations, observer){ waterflowInit(); }).observe(document.querySelector("#primary"), { 'childList': true }); } /*移动端文章列表布局切换*/ !function(){ var mobileLayout = argonConfig.article_list_layout_mobile || "1"; var isMobile = window.innerWidth <= 900; function applyMobileLayout() { var nowMobile = window.innerWidth <= 900; if (nowMobile) { $("html").addClass("mobile-layout-" + mobileLayout); } else { $("html").removeClass("mobile-layout-1 mobile-layout-2 mobile-layout-3"); } } applyMobileLayout(); $(window).resize(function(){ applyMobileLayout(); }); }(); /*浮动按钮栏相关(回顶部)*/ !function(){ // 确保 DOM 和 jQuery 已加载 if (typeof jQuery === 'undefined') { setTimeout(arguments.callee, 50); return; } let $fabtns = $('#float_action_buttons'); if ($fabtns.length === 0) { setTimeout(arguments.callee, 50); return; } let $backToTopBtn = $('#fabtn_back_to_top'); let $toggleSidesBtn = $('#fabtn_toggle_sides'); let $toggleDarkmode = $('#fabtn_toggle_darkmode'); let $toggleAmoledMode = $('#blog_setting_toggle_darkmode_and_amoledarkmode'); let $toggleBlogSettings = $('#fabtn_toggle_blog_settings_popup'); let $goToComment = $('#fabtn_go_to_comment'); let $readingProgressBtn = $('#fabtn_reading_progress'); let $readingProgressBar = $('#fabtn_reading_progress_bar'); let $readingProgressDetails = $('#fabtn_reading_progress_details'); $backToTopBtn.on("click" , function(){ $("body,html").stop().animate({ scrollTop: 0 }, 600); }); $toggleDarkmode.on("click" , function(){ toggleDarkmode(); }); $toggleAmoledMode.on("click" , function(){ toggleAmoledDarkMode(); }) if ($("#post_comment").length > 0){ $("#fabtn_go_to_comment").removeClass("fabtn-hidden"); }else{ $("#fabtn_go_to_comment").addClass("fabtn-hidden"); } $goToComment.on("click" , function(){ var commentsArea = $("#comments"); var postCommentArea = $("#post_comment"); var wasCollapsed = commentsArea.hasClass("comments-collapsed"); var toggleBtn = $("#comments_toggle"); if (wasCollapsed && toggleBtn.length > 0) { // 折叠状态:先滚动到评论切换按钮位置,再展开 $("body,html").stop().animate({ scrollTop: toggleBtn.offset().top - 80 }, 600); toggleBtn.find("i").removeClass("fa-comments").addClass("fa-comment-o"); toggleBtn.find(".btn-inner--text").text("折叠评论"); toggleBtn.addClass("expanded"); commentsArea.removeClass("comments-collapsed"); setTimeout(function() { postCommentArea.removeClass("comments-collapsed"); $("#post_comment_content").focus(); }, 150); } else { // 已展开或无切换按钮:直接滚动到评论区 $("body,html").stop().animate({ scrollTop: postCommentArea.offset().top - 80 }, 600); $("#post_comment_content").focus(); } }); if (localStorage['Argon_fabs_Floating_Status'] == "left"){ $fabtns.addClass("fabtns-float-left"); } $toggleSidesBtn.on("click" , function(){ $fabtns.addClass("fabtns-unloaded"); setTimeout(function(){ $fabtns.toggleClass("fabtns-float-left"); if ($fabtns.hasClass("fabtns-float-left")){ localStorage['Argon_fabs_Floating_Status'] = "left"; }else{ localStorage['Argon_fabs_Floating_Status'] = "right"; } $fabtns.removeClass("fabtns-unloaded"); } , 300); }); //博客设置 $toggleBlogSettings.on("click" , function(){ $("#float_action_buttons").toggleClass("blog_settings_opened"); }); $("#close_blog_settings").on("click" , function(){ $("#float_action_buttons").removeClass("blog_settings_opened"); }); $("#blog_setting_darkmode_switch .custom-toggle-slider").on("click" , function(){ toggleDarkmode(); }); //字体 $("#blog_setting_font_sans_serif").on("click" , function(){ $("html").removeClass("use-serif"); localStorage['Argon_Use_Serif'] = "false"; }); $("#blog_setting_font_serif").on("click" , function(){ $("html").addClass("use-serif"); localStorage['Argon_Use_Serif'] = "true"; }); // 字体设置已在 header.php 中预加载,此处无需重复应用 //阴影 $("#blog_setting_shadow_small").on("click" , function(){ $("html").removeClass("use-big-shadow"); localStorage['Argon_Use_Big_Shadow'] = "false"; }); $("#blog_setting_shadow_big").on("click" , function(){ $("html").addClass("use-big-shadow"); localStorage['Argon_Use_Big_Shadow'] = "true"; }); // 阴影设置已在 header.php 中预加载,此处无需重复应用 //滤镜 function setBlogFilter(name){ if (name == undefined || name == ""){ name = "off"; } if (!$("html").hasClass("filter-" + name)){ $("html").removeClass("filter-sunset filter-darkness filter-grayscale"); if (name != "off"){ $("html").addClass("filter-" + name); } } $("#blog_setting_filters .blog-setting-filter-btn").removeClass("active"); $("#blog_setting_filters .blog-setting-filter-btn[filter-name='" + name + "']").addClass("active"); localStorage['Argon_Filter'] = name; } // 滤镜设置已在 header.php 中预加载,此处只需设置按钮状态 let currentFilter = localStorage['Argon_Filter'] || 'off'; $("#blog_setting_filters .blog-setting-filter-btn[filter-name='" + currentFilter + "']").addClass("active"); $(".blog-setting-filter-btn").on("click" , function(){ setBlogFilter(this.getAttribute("filter-name")); }); //UI 样式切换 (玻璃拟态/新拟态) function setUIStyle(style){ if (style == undefined || style == ""){ style = "default"; } $("html").removeClass("style-glass style-neumorphism"); if (style != "default"){ $("html").addClass("style-" + style); } $(".blog-setting-style-btn").removeClass("active"); $(".blog-setting-style-btn[style-name='" + style + "']").addClass("active"); localStorage['Argon_UI_Style'] = style; } // UI 样式设置已在 header.php 中预加载,此处只需设置按钮状态 let currentUIStyle = localStorage['Argon_UI_Style'] || 'default'; $(".blog-setting-style-btn[style-name='" + currentUIStyle + "']").addClass("active"); $(".blog-setting-style-btn").on("click" , function(){ setUIStyle(this.getAttribute("style-name")); }); let $window = $(window); function changefabtnDisplayStatus(){ //阅读进度 function hideReadingProgress(){ $readingProgressBtn.addClass("fabtn-hidden"); } function setReadingProgress(percent){ $readingProgressBtn.removeClass("fabtn-hidden"); $readingProgressDetails.html((percent * 100).toFixed(0) + "%"); $readingProgressBar.css("width" , (percent * 100).toFixed(0) + "%"); } if ($("article.post.post-full").length == 0){ hideReadingProgress(); }else{ let a = $window.scrollTop() - ($("article.post.post-full").offset().top - 80); let b = $("article.post.post-full").outerHeight() + 50 - $window.height(); if (b <= 0){ hideReadingProgress(); }else{ readingProgress = a / b; if (isNaN(readingProgress) || readingProgress < 0 || readingProgress > 1){ hideReadingProgress(); }else{ setReadingProgress(readingProgress); } } } //是否显示回顶 if ($(window).scrollTop() >= 400){ $backToTopBtn.removeClass("fabtn-hidden"); }else{ $backToTopBtn.addClass("fabtn-hidden"); } } changefabtnDisplayStatus(); $(window).scroll(function(){ changefabtnDisplayStatus(); }); $(window).resize(function(){ changefabtnDisplayStatus(); }); $fabtns.removeClass("fabtns-unloaded"); }(); /*卡片圆角大小调整*/ !function(){ function setCardRadius(radius, setcookie){ document.documentElement.style.setProperty('--card-radius', radius + "px"); if (setcookie){ setCookie("argon_card_radius", radius, 365); } } let slider = document.getElementById('blog_setting_card_radius'); noUiSlider.create(slider, { start: [$("meta[name='theme-card-radius']").attr("content")], step: 0.5, connect: [true, false], range: { 'min': [0], 'max': [30] } }); slider.noUiSlider.on('update', function (values){ let value = values[0]; setCardRadius(value, false); }); slider.noUiSlider.on('set', function (values){ let value = values[0]; setCardRadius(value, true); }); $(document).on("click" , "#blog_setting_card_radius_to_default" , function(){ slider.noUiSlider.set($("meta[name='theme-card-radius-origin']").attr("content")); setCardRadius($("meta[name='theme-card-radius-origin']").attr("content"), false); setCookie("argon_card_radius", $("meta[name='theme-card-radius-origin']").attr("content"), 0); }); }(); /*评论区 & 发送评论*/ !function(){ //回复评论 let replying = false , replyID = 0; /** * 显示回复框 * @param {number} commentID - 评论ID */ function reply(commentID){ cancelEdit(false); replying = true; replyID = commentID; let nameEl = $("#comment-" + commentID + " .comment-item-title > .comment-name")[0]; let textEl = $("#comment-" + commentID + " .comment-item-text")[0]; let sourceEl = $("#comment-" + commentID + " .comment-item-source")[0]; if (nameEl) { $("#post_comment_reply_name").text(nameEl.textContent); } let preview = textEl ? textEl.textContent : ''; if (sourceEl && sourceEl.innerHTML !== '') { preview = sourceEl.textContent; } $("#post_comment_reply_preview").text(preview); if ($("#comment-" + commentID + " .comment-item-title .badge-private-comment").length > 0){ $("#post_comment").addClass("post-comment-force-privatemode-on"); }else{ $("#post_comment").addClass("post-comment-force-privatemode-off"); } // 滚动到评论框(使用原生 scrollTo 避免 jQuery easing 依赖问题) let postComment = $('#post_comment'); if (postComment.length > 0 && postComment.offset()) { let targetTop = postComment.offset().top - 100; window.scrollTo({ top: targetTop, behavior: 'smooth' }); } // 使用 CSS 动画显示回复框 let replyInfo = $('#post_comment_reply_info'); if (replyInfo.length > 0) { replyInfo.removeClass('reply-leaving').css('display', 'block'); // 触发重排以确保动画生效 replyInfo[0].offsetHeight; replyInfo.addClass('reply-entering'); } setTimeout(function(){ $("#post_comment_content").focus(); }, 300); } /** * 取消回复 */ function cancelReply(){ replying = false; replyID = 0; let replyInfo = $('#post_comment_reply_info'); replyInfo.removeClass('reply-entering').addClass('reply-leaving'); setTimeout(function(){ replyInfo.css('display', 'none').removeClass('reply-leaving'); }, 200); $("#post_comment").removeClass("post-comment-force-privatemode-on post-comment-force-privatemode-off"); } $(document).on("click" , ".comment-reply" , function(){ reply(this.getAttribute("data-id")); }); $(document).on("click pjax:click" , "#post_comment_reply_cancel" , function(){ cancelReply(); }); $(document).on("pjax:click" , function(){ replying = false; replyID = 0; $('#post_comment_reply_info').css("display", "none").removeClass('reply-entering reply-leaving'); $("#post_comment").removeClass("post-comment-force-privatemode-on post-comment-force-privatemode-off"); }); //编辑评论 let editing = false , editID = 0; function edit(commentID){ cancelReply(); editing = true; editID = commentID; $('#post_comment').addClass("editing"); $("#post_comment_content").val($("#comment-" + editID + " .comment-item-source").text()); $("#post_comment_content").trigger("change"); if ($("#comment-" + editID).data("use-markdown") == true && document.getElementById("comment_post_use_markdown") != null){ document.getElementById("comment_post_use_markdown").checked = true; }else{ document.getElementById("comment_post_use_markdown").checked = false; } if ($("#comment-" + commentID + " .comment-item-title .badge-private-comment").length > 0){ $("#post_comment").addClass("post-comment-force-privatemode-on"); }else{ $("#post_comment").addClass("post-comment-force-privatemode-off"); } // 使用原生 scrollTo 避免 jQuery easing 依赖问题 let postCommentEl = document.getElementById('post_comment'); if (postCommentEl) { window.scrollTo({ top: postCommentEl.getBoundingClientRect().top + window.pageYOffset - 100, behavior: 'smooth' }); } $("#post_comment_content").focus(); } function cancelEdit(clear){ editing = false; editID = 0; $("#post_comment").removeClass("post-comment-force-privatemode-on post-comment-force-privatemode-off"); if (clear == true) $("#post_comment_content").val(""); $("#post_comment_content").trigger("change"); $('#post_comment').removeClass("editing"); } $(document).on("click", ".comment-edit", function(){ edit(this.getAttribute("data-id")); }); $(document).on("click", "#post_comment_edit_cancel", function(){ // 使用原生 scrollTo 避免 jQuery easing 依赖问题 let commentEl = document.getElementById("comment-" + editID); if (commentEl) { window.scrollTo({ top: commentEl.getBoundingClientRect().top + window.pageYOffset - 100, behavior: 'smooth' }); } cancelEdit(true); }); $(document).on("pjax:click", function(){ cancelEdit(true); }); $(document).on("click", ".comment-pin, .comment-unpin", function(){ toogleCommentPin(this.getAttribute("data-id"), !this.classList.contains("comment-pin")); }); $(document).on("click", ".comment-delete", function(){ deleteComment(this.getAttribute("data-id")); }); $(document).on("mouseenter", ".comment-parent-info", function(){ $("#comment-" + this.getAttribute("data-parent-id")).addClass("highlight"); }); $(document).on("mouseleave", ".comment-parent-info", function(){ $("#comment-" + this.getAttribute("data-parent-id")).removeClass("highlight"); }); //切换评论置顶状态 function toogleCommentPin(commentID, pinned){ $("#comment_pin_comfirm_dialog .modal-title").html(pinned ? __("取消置顶评论") : __("置顶评论")); $("#comment_pin_comfirm_dialog .modal-body").html(pinned ? __("是否要取消置顶评论 #") + commentID + "?" : __("是否要置顶评论 #") + commentID + "?"); $("#comment_pin_comfirm_dialog .btn-comfirm").html(__("确认")).attr("disabled", false); $("#comment_pin_comfirm_dialog .btn-dismiss").html(__("取消")).attr("disabled", false); $("#comment_pin_comfirm_dialog .btn-comfirm").off("click").on("click", function(){ $("#comment_pin_comfirm_dialog .btn-dismiss").attr("disabled", true) $("#comment_pin_comfirm_dialog .btn-comfirm").attr("disabled", true).prepend(__(``)); $.ajax({ type: 'POST', url: argonConfig.wp_path + "wp-admin/admin-ajax.php", dataType : "json", data: { action: "pin_comment", id: commentID, pinned: pinned ? "false" : "true" }, success: function(result){ $("#comment_pin_comfirm_dialog").modal('hide'); if (result.status == "success"){ if (pinned){ $("#comment-" + commentID + " .comment-name .badge-pinned").remove(); $("#comment-" + commentID + " .comment-unpin").removeClass("comment-unpin").addClass("comment-pin").html(__("置顶")); }else{ $("#comment-" + commentID + " .comment-name").append(`${__("置顶")}`); $("#comment-" + commentID + " .comment-pin").removeClass("comment-pin").addClass("comment-unpin").html(__("取消置顶")); } iziToast.show({ title: pinned ? __("取消置顶成功") : __("置顶成功"), message: pinned ? __("该评论已取消置顶") : __("该评论已置顶"), class: 'shadow-sm', position: 'topRight', backgroundColor: '#2dce89', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-check', timeout: 5000 }); } else { iziToast.show({ title: pinned ? __("取消置顶失败") : __("置顶失败"), message: result.msg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } }, error: function(result){ $("#comment_pin_comfirm_dialog").modal('hide'); iziToast.show({ title: pinned ? __("取消置顶失败") : __("置顶失败"), message: __("未知错误"), class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } }); }); $("#comment_pin_comfirm_dialog").modal(null); } //删除评论 function deleteComment(commentID) { if (!confirm(__('确定要删除评论 #') + commentID + '?')) { return; } $.ajax({ type: 'POST', url: argonConfig.wp_path + 'wp-admin/admin-ajax.php', dataType: 'json', data: { action: 'frontend_delete_comment', id: commentID }, success: function(result) { if (result.status === 'success') { // 移除评论元素 $('#comment-' + commentID).fadeOut(300, function() { $(this).next('.comment-divider').remove(); $(this).remove(); }); iziToast.show({ title: __('删除成功'), message: result.msg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#2dce89', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-check', timeout: 5000 }); } else { iziToast.show({ title: __('删除失败'), message: result.msg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } }, error: function() { iziToast.show({ title: __('删除失败'), message: __('未知错误'), class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } }); } //显示/隐藏额外输入框(评论者网址) $(document).on("click" , "#post_comment_toggle_extra_input" , function(){ $("#post_comment").toggleClass("show-extra-input"); if ($("#post_comment").hasClass("show-extra-input")){ $("#post_comment_extra_input").slideDown(250, 'easeOutCirc'); }else{ $("#post_comment_extra_input").slideUp(200, 'easeOutCirc'); } }); //输入框细节 $(document).on("change input keydown keyup propertychange" , "#post_comment_content" , function(){ $("#post_comment_content_hidden")[0].innerText = $("#post_comment_content").val() + "\n"; $("#post_comment_content").css("height" , $("#post_comment_content_hidden").outerHeight()); }); $(document).on("focus" , "#post_comment_link" , function(){ $(".post-comment-link-container").addClass("active"); }); $(document).on("blur" , "#post_comment_link" , function(){ $(".post-comment-link-container").removeClass("active"); }); $(document).on("focus" , "#post_comment_captcha" , function(){ $(".post-comment-captcha-container").addClass("active"); }); $(document).on("blur" , "#post_comment_captcha" , function(){ $(".post-comment-captcha-container").removeClass("active"); }); //发送评论 window.postComment = function postComment(){ let commentContent = $("#post_comment_content").val(); let commentName = $("#post_comment_name").val(); let commentEmail = $("#post_comment_email").val(); let commentLink = $("#post_comment_link").val(); let commentCaptcha = $("#post_comment_captcha").val(); let useMarkdown = false; let privateMode = false; let mailNotice = false; if ($("#comment_post_use_markdown").length > 0){ useMarkdown = $("#comment_post_use_markdown")[0].checked; } if ($("#comment_post_privatemode").length > 0){ privateMode = $("#comment_post_privatemode")[0].checked; } if ($("#comment_post_mailnotice").length > 0){ mailNotice = $("#comment_post_mailnotice")[0].checked; } let postID = $("#post_comment_post_id").val(); let commentCaptchaSeed = $("#post_comment_captcha_seed").val(); let isError = false; let errorMsg = ""; //检查表单合法性 if (commentContent.match(/^\s*$/)){ isError = true; errorMsg += __("评论内容不能为空") + "
"; } if (!$("#post_comment").hasClass("no-need-name-email")){ if (commentName.match(/^\s*$/)){ isError = true; errorMsg += __("昵称不能为空") + "
"; } if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱或QQ 号格式错误") + "
"; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱格式错误") + "
"; } } }else{ if (commentEmail.length || (document.getElementById("comment_post_mailnotice") != null && document.getElementById("comment_post_mailnotice").checked == true)){ if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱或QQ 号格式错误") + "
"; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱格式错误") + "
"; } } } } if (commentLink != "" && !(/https?:\/\//).test(commentLink)){ isError = true; errorMsg += __("网站格式错误 (不是 http(s):// 开头)") + "
"; } if (!$("#post_comment").hasClass("no-need-captcha")){ // 检查是否使用Geetest验证码 if ($("#geetest-captcha").length > 0) { // 检查Geetest库是否加载成功 if (typeof window.geetestLoadFailed !== 'undefined' && window.geetestLoadFailed) { isError = true; errorMsg += __("验证码服务不可用,请刷新页面重试"); } else if (typeof window.geetestCaptcha === 'undefined' || !window.geetestCaptcha) { isError = true; errorMsg += __("验证码未初始化,请稍后重试");; } else { // Geetest验证码检查 let lotNumber = $("#geetest_lot_number").val(); let captchaOutput = $("#geetest_captcha_output").val(); let passToken = $("#geetest_pass_token").val(); let genTime = $("#geetest_gen_time").val(); if (!lotNumber || !captchaOutput || !passToken || !genTime) { isError = true; errorMsg += __("请完成验证码验证"); } } } else { // 原有的数学验证码验证 if (commentCaptcha == ""){ isError = true; errorMsg += __("验证码未输入"); } if (commentCaptcha != "" && !(/^[0-9]+$/).test(commentCaptcha)){ isError = true; errorMsg += __("验证码格式错误"); } } } if (isError){ // 确保按钮和表单元素处于可用状态 $("#post_comment_send").removeAttr("disabled"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); $("#post_comment_email").removeAttr("disabled"); $("#post_comment_link").removeAttr("disabled"); $("#post_comment_captcha").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment").removeClass("sending"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); iziToast.show({ title: __("评论格式错误"), message: errorMsg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); return; } //增加 disabled 属性和其他的表单提示 $("#post_comment").addClass("sending"); $("#post_comment_content").attr("disabled","disabled"); $("#post_comment_name").attr("disabled","disabled"); $("#post_comment_email").attr("disabled","disabled"); $("#post_comment_captcha").attr("disabled","disabled"); $("#post_comment_link").attr("disabled","disabled"); $("#post_comment_send").attr("disabled","disabled"); $("#post_comment_reply_cancel").attr("disabled","disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送中")); iziToast.show({ title: __("正在发送"), message: __("评论正在发送中..."), class: 'shadow-sm iziToast-noprogressbar', position: 'topRight', backgroundColor: 'var(--themecolor)', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-spinner fa-spin', close: false, timeout: 999999999 }); // 准备数据 var ajaxData = { action: "ajax_post_comment", comment: commentContent, author: commentName, email: commentEmail, url: commentLink, comment_post_ID: postID, comment_parent: replyID, "wp-comment-cookies-consent": "yes", use_markdown: useMarkdown, private_mode: privateMode, enable_mailnotice: mailNotice, argon_nonce: $("#argon_comment_nonce").val() }; // 根据验证码类型添加相应参数 if ($("#geetest-captcha").length > 0) { // 检查Geetest库加载状态 if (typeof window.geetestLoadFailed !== 'undefined' && window.geetestLoadFailed) { // 重新启用按钮和表单元素 $("#post_comment").removeClass("sending"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); $("#post_comment_email").removeAttr("disabled"); $("#post_comment_captcha").removeAttr("disabled"); $("#post_comment_link").removeAttr("disabled"); $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); setTimeout(function() { try { iziToast.destroy(); iziToast.error({ title: __('评论发送失败'), message: __('验证码服务不可用,请刷新页面重试'), position: 'topRight' }); } catch (e) { ArgonDebug.warn('iziToast error:', e); } }, 0); return false; } // Geetest验证码参数 - 使用后端期望的参数名 ajaxData.lot_number = $("#geetest_lot_number").val(); ajaxData.captcha_output = $("#geetest_captcha_output").val(); ajaxData.pass_token = $("#geetest_pass_token").val(); ajaxData.gen_time = $("#geetest_gen_time").val(); // 验证Geetest参数是否完整 if (!ajaxData.lot_number || !ajaxData.captcha_output || !ajaxData.pass_token || !ajaxData.gen_time) { // 重新启用按钮和表单元素 $("#post_comment").removeClass("sending"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); $("#post_comment_email").removeAttr("disabled"); $("#post_comment_captcha").removeAttr("disabled"); $("#post_comment_link").removeAttr("disabled"); $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); // 使用 setTimeout 确保 iziToast 操作在下一个事件循环中执行 setTimeout(function() { try { iziToast.destroy(); iziToast.error({ title: __('评论发送失败'), message: __('请完成验证码验证'), position: 'topRight' }); } catch (e) { ArgonDebug.warn('iziToast error:', e); } }, 0); return false; } } else { // 原有数学验证码参数 ajaxData.comment_captcha_seed = commentCaptchaSeed; ajaxData.comment_captcha = commentCaptcha; } $.ajax({ type: 'POST', url: argonConfig.wp_path + "wp-admin/admin-ajax.php", dataType : "json", data: ajaxData, success: function(result){ $("#post_comment").removeClass("sending"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); $("#post_comment_email").removeAttr("disabled"); $("#post_comment_link").removeAttr("disabled"); $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); $("#post_comment").removeClass("show-extra-input post-comment-force-privatemode-on post-comment-force-privatemode-off"); if (!result.isAdmin){ $("#post_comment_captcha").removeAttr("disabled"); } //判断是否有错误 if (result.status == "failed"){ // 使用 setTimeout 确保 iziToast 操作在下一个事件循环中执行 setTimeout(function() { try { iziToast.destroy(); iziToast.show({ title: __("评论发送失败"), message: result.msg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } catch (e) { ArgonDebug.warn('iziToast error:', e); } }, 0); return; } //发送成功 // 先复位评论表单(确保无论后续操作是否成功都能重置表单) cancelReply(); $("#post_comment_content").val(""); // 重置数学验证码 $("#post_comment_captcha_seed").val(result.newCaptchaSeed); $("#post_comment_captcha + style").html(".post-comment-captcha-container:before{content: '" + result.newCaptcha + "';}"); $("#post_comment_captcha").val(""); // 清空Geetest验证码隐藏字段并重置验证码实例 if ($("#geetest-captcha").length > 0) { $("#geetest_lot_number").val(""); $("#geetest_captcha_output").val(""); $("#geetest_pass_token").val(""); $("#geetest_gen_time").val(""); // 重置验证状态标志位 window.geetestVerified = false; // 重置自动提交标记 window.geetestAutoSubmitting = false; // 重置 Geetest 实例,确保下一次可以重新验证 if (window.geetestCaptcha) { try { window.geetestCaptcha.reset(); } catch (e) { ArgonDebug.warn('Geetest reset error:', e); } } } // 显示成功提示 setTimeout(function() { try { iziToast.destroy(); iziToast.show({ title: __("发送成功"), message: __("您的评论已发送"), class: 'shadow-sm', position: 'topRight', backgroundColor: '#2dce89', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-check', timeout: 5000 }); } catch (e) { ArgonDebug.warn('iziToast error:', e); } }, 0); // 插入新评论 try { result.html = result.html.replace(/<(\/).noscript>/g, ""); let parentID = result.parentID; if (parentID == "" || parentID == null){ parentID = 0; } parentID = parseInt(parentID); if (parentID == 0){ if ($("#comments > .card-body > ol.comment-list").length == 0){ $("#comments > .card-body").html("

" + __("评论") + "

    "); } if (result.commentOrder == "asc"){ $("#comments > .card-body > ol.comment-list").append(result.html); }else{ $("#comments > .card-body > ol.comment-list").prepend(result.html); } }else{ if ($("#comment-" + parentID + " + .comment-divider + li > ul.children").length > 0){ $("#comment-" + parentID + " + .comment-divider + li > ul.children").append(result.html); }else{ $("#comment-" + parentID + " + .comment-divider").after("
  1. "); } } calcHumanTimesOnPage(); // 滚动到新评论 $("body,html").animate({ scrollTop: $("#comment-" + result.id).offset().top - 100 }, 500, 'easeOutExpo'); } catch (e) { ArgonDebug.warn('Comment insertion error:', e); } }, error: function(result){ $("#post_comment").removeClass("sending"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); $("#post_comment_email").removeAttr("disabled"); $("#post_comment_link").removeAttr("disabled"); $("#post_comment_send").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); $("#post_comment").removeClass("show-extra-input post-comment-force-privatemode-on post-comment-force-privatemode-off"); if (!result.isAdmin){ $("#post_comment_captcha").removeAttr("disabled"); } // 重置Geetest验证状态 window.geetestVerified = false; // 重置自动提交标记 window.geetestAutoSubmitting = false; $("#geetest_lot_number").val(""); $("#geetest_captcha_output").val(""); $("#geetest_pass_token").val(""); $("#geetest_gen_time").val(""); // 重置 Geetest 实例,确保下一次生成新的pass_token if (window.geetestCaptcha) { try { window.geetestCaptcha.reset(); } catch (e) {} } // 安全地处理iziToast 操作,防止time 属性错误 setTimeout(function() { try { iziToast.destroy(); iziToast.show({ title: __("评论发送失败"), message: __("未知原因"), class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } catch (e) { ArgonDebug.warn('iziToast operation error:', e); } }, 10); return; } }); } //编辑评论 function editComment(){ let commentContent = $("#post_comment_content").val(); let isError = false; let errorMsg = ""; if (commentContent.match(/^\s*$/)){ isError = true; errorMsg += __("评论内容不能为空") + "
    "; } if (isError){ iziToast.show({ title: __("评论格式错误"), message: errorMsg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); return; } //增加 disabled 属性和其他的表单提交 $("#post_comment_content").attr("disabled","disabled"); $("#post_comment_send").attr("disabled","disabled"); $("#post_comment_edit_cancel").attr("disabled","disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-not-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-not-editing").html(__("编辑中")); iziToast.show({ title: __("正在编辑"), message: __("评论正在编辑中.."), class: 'shadow-sm iziToast-noprogressbar', position: 'topRight', backgroundColor: 'var(--themecolor)', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-spinner fa-spin', close: false, timeout: 999999999 }); $.ajax({ type: 'POST', url: argonConfig.wp_path + "wp-admin/admin-ajax.php", dataType : "json", data: { action: "user_edit_comment", comment: commentContent, id: editID }, success: function(result){ $("#post_comment_content").removeAttr("disabled"); $("#post_comment_send").removeAttr("disabled"); $("#post_comment_edit_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-not-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-not-editing").html(__("编辑")); //判断是否有错误 if (result.status == "failed"){ iziToast.destroy(); iziToast.show({ title: __("评论编辑失败"), message: result.msg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); return; } //发送成功,替换原评论 result.new_comment = result.new_comment.replace(/<(\/).noscript>/g, ""); $("#comment-" + editID + " .comment-item-text").html(result.new_comment); $("#comment-" + editID + " .comment-item-source").html(result.new_comment_source); if ($("#comment-" + editID + " .comment-info .comment-edited").length == 0){ $("#comment-" + editID + " .comment-info").prepend("
    " + __("已编辑") + "
    ") } if (result.can_visit_edit_history){ $("#comment-" + editID + " .comment-info .comment-edited").addClass("comment-edithistory-accessible"); } iziToast.destroy(); iziToast.show({ title: __("编辑成功"), message: __("您的评论已编辑"), class: 'shadow-sm', position: 'topRight', backgroundColor: '#2dce89', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-check', timeout: 5000 }); $("body,html").animate({ scrollTop: $("#comment-" + editID).offset().top - 100 }, 500, 'easeOutExpo'); editing = false; editID = 0; $("#post_comment_content").val(""); $('#post_comment').removeClass("editing post-comment-force-privatemode-on post-comment-force-privatemode-off"); $("#post_comment_content").trigger("change"); }, error: function(result){ $("#post_comment_content").removeAttr("disabled"); $("#post_comment_send").removeAttr("disabled"); $("#post_comment_edit_cancel").removeAttr("disabled"); $("#post_comment_send .btn-inner--icon.hide-on-comment-not-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-not-editing").html(__("编辑")); if (result.readyState != 4 || result.status == 0){ iziToast.destroy(); iziToast.show({ title: __("评论编辑失败"), message: __("未知原因"), class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); return; } } }); } $(document).on("click" , "#post_comment_send" , function(){ if ($("#post_comment").hasClass("editing")){ editComment(); }else{ // 首先进行基本的表单验证 let commentContent = $("#post_comment_content").val(); let commentName = $("#post_comment_name").val(); let commentEmail = $("#post_comment_email").val(); let commentLink = $("#post_comment_link").val(); let isError = false; let errorMsg = ""; // 检查表单合法性 if (commentContent.match(/^\s*$/)){ isError = true; errorMsg += __("评论内容不能为空") + "
    "; } if (!$("#post_comment").hasClass("no-need-name-email")){ if (commentName.match(/^\s*$/)){ isError = true; errorMsg += __("昵称不能为空") + "
    "; } if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱或QQ 号格式错误") + "
    "; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱格式错误") + "
    "; } } }else{ if (commentEmail.length || (document.getElementById("comment_post_mailnotice") != null && document.getElementById("comment_post_mailnotice").checked == true)){ if ($("#post_comment").hasClass("enable-qq-avatar")){ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail) && !(/^[1-9][0-9]{4,10}$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱或QQ 号格式错误") + "
    "; } }else{ if (!(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(commentEmail)){ isError = true; errorMsg += __("邮箱格式错误") + "
    "; } } } } if (commentLink != "" && !(/https?:\/\//).test(commentLink)){ isError = true; errorMsg += __("网站格式错误 (不是 http(s):// 开头") + "
    "; } // 如果基本表单验证失败,显示错误信息并返回 if (isError){ // 确保按钮和表单元素处于可用状态 $("#post_comment_send").removeAttr("disabled"); $("#post_comment_content").removeAttr("disabled"); $("#post_comment_name").removeAttr("disabled"); $("#post_comment_email").removeAttr("disabled"); $("#post_comment_link").removeAttr("disabled"); $("#post_comment_captcha").removeAttr("disabled"); $("#post_comment_reply_cancel").removeAttr("disabled"); $("#post_comment").removeClass("sending"); $("#post_comment_send .btn-inner--icon.hide-on-comment-editing").html(""); $("#post_comment_send .btn-inner--text.hide-on-comment-editing").html(__("发送")); iziToast.show({ title: __("评论格式错误"), message: errorMsg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); return; } // 基本验证通过后,检查验证码 if ($("#geetest-captcha").length > 0) { // 检查Geetest 库是否加载失败 if (window.geetestLoadFailed) { if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') { try { loadGeetestScript(function(){ initGeetestCaptchaCore(); setTimeout(function(){ if (window.geetestCaptcha) { try { window.geetestCaptcha.showBox(); } catch(e){} } }, 0); }); } catch(e) {} } return; } // 如果正在自动提交中,防止重复点击 if (window.geetestAutoSubmitting) { return; } // 如果使用Geetest,检查验证码是否已完成 if (!window.geetestVerified) { // 验证码未完成,触发验证码显示 if (window.geetestCaptcha) { // 重置验证码状态 window.geetestCaptcha.reset(); // 然后显示验证码 window.geetestCaptcha.showBox(); } else { if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') { try { loadGeetestScript(function(){ initGeetestCaptchaCore(); setTimeout(function(){ if (window.geetestCaptcha) { try { window.geetestCaptcha.showBox(); } catch(e){} } }, 0); }); } catch(e) {} } } return; } } // 验证码已完成或不需要验证码,直接提交评论 postComment(); } }); }(); /*评论点赞*/ $(document).on('click', '.comment-upvote', function(){ let $this = $(this); let ID = $this.attr('data-id'); // 防止重复点击 if ($this.hasClass('comment-upvoting')) { return; } $this.addClass('comment-upvoting'); $.ajax({ url: argonConfig.wp_path + 'wp-admin/admin-ajax.php', type: 'POST', dataType: 'json', data: { action: 'upvote_comment', comment_id: ID, }, success: function(result){ $this.removeClass('comment-upvoting'); if (result.status === 'success'){ $('.comment-upvote-num', $this).html(result.total_upvote); if (result.upvoted) { $this.addClass('upvoted'); } else { $this.removeClass('upvoted'); } } else { $('.comment-upvote-num', $this).html(result.total_upvote); iziToast.show({ title: result.msg, class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } }, error: function(xhr){ $this.removeClass('comment-upvoting'); iziToast.show({ title: __('点赞失败'), class: 'shadow-sm', position: 'topRight', backgroundColor: '#f5365c', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-close', timeout: 5000 }); } }); }); /*评论表情面板*/ function lazyloadStickers(){ // 原生懒加载无需额外处理 } $(document).on("click" , "#comment_emotion_btn" , function(){ $("#comment_emotion_btn").toggleClass("comment-emotion-keyboard-open"); }); $(document).on("click" , ".emotion-keyboard .emotion-group-name" , function(){ $(".emotion-keyboard .emotion-group-name.active").removeClass("active"); $(this).addClass("active"); $(".emotion-keyboard .emotion-group:not(d-none)").addClass("d-none"); $(".emotion-keyboard .emotion-group[index='" + $(this).attr("index") + "']").removeClass("d-none"); }); function inputInsertText(text, input){ $(input).focus(); let isSuccess = document.execCommand("insertText", false, text); if (!isSuccess) { //FF if (typeof input.setRangeText === "function"){ const start = input.selectionStart; input.setRangeText(text); input.selectionStart = input.selectionEnd = start + input.length; const e = document.createEvent("UIEvent"); e.initEvent("input", true, false); input.dispatchEvent(e); }else{ let value = $(input).val(); let startPos = input.selectionStart, endPos = input.selectionEnd; $(input).val(value.substring(0, startPos) + text + value.substring(endPos)); input.selectionStart = startPos + text.length; input.selectionEnd = startPos + text.length; } } $(input).focus(); } $(document).on("click" , ".emotion-keyboard .emotion-item" , function(){ $("#comment_emotion_btn").removeClass("comment-emotion-keyboard-open"); if ($(this).hasClass("emotion-item-sticker")){ inputInsertText(" :" + $(this).attr("code") + ": ", document.getElementById("post_comment_content")); }else{ inputInsertText($(this).attr("text"), document.getElementById("post_comment_content")); } }); $(document).on("dragstart" , ".emotion-keyboard .emotion-item > img, .comment-sticker" , function(e){ e.preventDefault(); }); document.addEventListener('click', (e) => { if (document.getElementById("comment_emotion_btn") == null){ return; }   if(e.target.id != "comment_emotion_btn" && e.target.id != "emotion_keyboard" && !document.getElementById("comment_emotion_btn").contains(e.target) && !document.getElementById("emotion_keyboard").contains(e.target)){ $("#comment_emotion_btn").removeClass("comment-emotion-keyboard-open");   } }) /*查看评论编辑记录*/ function showCommentEditHistory(id){ let requestID = parseInt(new Date().getTime()); $("#comment_edit_history").data("request-id", requestID); $("#comment_edit_history .modal-title").html(__("评论 #") + id + " " + __("的编辑记录")); $("#comment_edit_history .modal-body").html("
    加载中/span>
    "); $("#comment_edit_history").modal(null); $.ajax({ type: 'POST', url: argonConfig.wp_path + "wp-admin/admin-ajax.php", dataType : "json", data: { action: "get_comment_edit_history", id: id }, success: function(result){ if ($("#comment_edit_history").data("request-id") != requestID){ return; } $("#comment_edit_history .modal-body").hide(); $("#comment_edit_history .modal-body").html(result.history); $("#comment_edit_history .modal-body").fadeIn(300); }, error: function(result){ if ($("#comment_edit_history").data("request-id") != requestID){ return; } $("#comment_edit_history .modal-body").hide(); $("#comment_edit_history .modal-body").html(__("加载失败")); $("#comment_edit_history .modal-body").fadeIn(300); } }); } $(document).on("click" , ".comment-edited.comment-edithistory-accessible" , function(){ showCommentEditHistory($(this).parent().parent().parent().parent().data("id")); }); /*过长评论折叠*/ function foldLongComments(){ if (argonConfig.fold_long_comments == false){ return; } $(".comment-item-inner").each(function(){ if ($(this).hasClass("comment-unfolded")){ return; } if (this.clientHeight > 800){ $(this).addClass("comment-folded"); $(this).append("
    "); } }); } foldLongComments(); $(document).on("click" , ".show-full-comment" , function(){ $(this).parent().removeClass("comment-folded").addClass("comment-unfolded"); }); /*评论文字头像*/ function generateCommentTextAvatar(img){ let emailHash = ''; try{ emailHash = img.attr("src").match(/([a-f\d]{32}|[A-F\d]{32})/)[0]; }catch{ emailHash = img.parent().parent().parent().find(".comment-name").text().trim(); if (emailHash == '' || emailHash == undefined){ emailHash = img.parent().find("*[class*='comment-author']").text().trim(); } } let hash = 0; for (i in emailHash){ hash = (hash * 233 + emailHash.charCodeAt(i)) % 16; } let colors = ['#e25f50', '#f25e90', '#bc67cb', '#9672cf', '#7984ce', '#5c96fa', '#7bdeeb', '#45d0e2', '#48b7ad', '#52bc89', '#9ace5f', '#d4e34a', '#f9d715', '#fac400', '#ffaa00', '#ff8b61', '#c2c2c2', '#8ea3af', '#a1877d', '#a3a3a3', '#b0b6e3', '#b49cde', '#c2c2c2', '#7bdeeb', '#bcaaa4', '#aed77f']; let text = $(".comment-name", img.parent().parent().parent()).text().trim()[0]; if (text == '' || text == undefined){ text = img.parent().find("*[class*='comment-author']").text().trim()[0]; } let classList = img.attr('class') + " text-avatar"; img.prop('outerHTML', '
    ' + text + '
    '); } document.addEventListener("error", function(e){ let img = $(e.target); if (!img.hasClass("avatar")){ return; } generateCommentTextAvatar(img); }, true); function refreshCommentTextAvatar(){ $(".comment-item-avatar > img.avatar").each(function(index, img){ if (!img.complete){ return; } if (img.naturalWidth !== 0){ return false; } generateCommentTextAvatar($(img)); }); } refreshCommentTextAvatar(); $(window).on("load", function(){ refreshCommentTextAvatar(); }); /*需要密码的文章加载*/ $(document).on("submit" , ".post-password-form" , function(){ $("input[type='submit']", this).attr("disabled", "disabled"); let url = $(this).attr("action"); $.pjax.form(this, { push: false, replace: false }); return false; }); /*评论分页加载*/ !function(){ $(document).on("click" , "#comments_navigation .page-item > div" , function(){ $("#comments").addClass("comments-loading"); NProgress.set(0.618); url = $(this).attr("href"); $.ajax({ type: 'POST', url: url, dataType : "html", success : function(result){ NProgress.done(); $vdom = $(result); $("#comments").html($("#comments", $vdom).html()); $("#comments").removeClass("comments-loading"); $("body,html").animate({ scrollTop: $("#comments").offset().top - 100 }, 500, 'easeOutExpo'); foldLongComments(); calcHumanTimesOnPage(); panguInit(); }, error : function(){ window.location.href = url; } }); }); $(document).on("click" , "#comments_more" , function(){ $("#comments_more").attr("disabled", "disabled"); NProgress.set(0.618); url = $(this).attr("href"); $.ajax({ type: 'POST', url: url, data: { no_post_view: 'true' }, dataType : "html", success : function(result){ NProgress.done(); $vdom = $(result); $("#comments > .card-body > ol.comment-list").append($("#comments > .card-body > ol.comment-list", $vdom).html()); if ($("#comments_more", $vdom).length == 0){ $("#comments_more").remove(); $(".comments-navigation-more").html("
    " + __("没有更多了") + "
    "); }else{ $("#comments_more").attr("href", $("#comments_more", $vdom).attr("href")); $("#comments_more").removeAttr("disabled"); } foldLongComments(); calcHumanTimesOnPage(); panguInit(); }, error : function(){ window.location.href = url; } }); }); }(); /*URL 和# 根据 ID 定位*/ function gotoHash(hash, durtion, easing = 'easeOutExpo'){ if (!hash || hash === "#"){ return; } var target = null; var decodedId = ""; try { decodedId = decodeURIComponent(hash.slice(1)); } catch (err) { decodedId = hash.slice(1); } if (decodedId) { target = document.getElementById(decodedId); } if (!target) { try { target = document.querySelector(hash); } catch (err) { return; } } if (!target){ return; } if (durtion == null){ durtion = 200; } $("body,html").stop().animate({ scrollTop: $(target).offset().top - 80 }, durtion, easing); } function getHash(url){ return url.substring(url.indexOf('#')); } !function(){ $(window).on("hashchange" , function(){ gotoHash(window.location.hash); }); $(window).trigger("hashchange"); }(); /*显示文章过时信息 Toast*/ function showPostOutdateToast(){ if ($("#primary #post_outdate_toast").length > 0){ iziToast.show({ title: '', message: $("#primary #post_outdate_toast").data("text"), class: 'shadow-sm', position: 'topRight', backgroundColor: 'var(--themecolor)', titleColor: '#ffffff', messageColor: '#ffffff', iconColor: '#ffffff', progressBarColor: '#ffffff', icon: 'fa fa-info', close: false, timeout: 8000 }); $("#primary #post_outdate_toast").remove(); } } showPostOutdateToast(); /*Zoomify*/ // 全局 Zoomify 实例数组,用于清理 var zoomifyInstances = []; function zoomifyInit(){ // 清理旧的 Zoomify 实例 if (zoomifyInstances.length > 0) { zoomifyInstances.forEach(function(instance) { try { if (instance && typeof instance.destroy === 'function') { instance.destroy(); } } catch(e) {} }); zoomifyInstances = []; } if (argonConfig.zoomify == false){ return; } if (typeof $.fn.zoomify === 'function') { $("article img:not(.zoomify-initialized)").each(function() { let $img = $(this); $img.addClass('zoomify-initialized'); try { let instance = $img.zoomify(argonConfig.zoomify).data('zoomify'); if (instance) { zoomifyInstances.push(instance); } } catch(e) {} }); } } zoomifyInit(); /*Fancybox*/ $.fancybox.defaults.transitionEffect = "slide"; $.fancybox.defaults.buttons = ["zoom", "fullScreen", "thumbs", "close"]; $.fancybox.defaults.lang = argonConfig.language; $.fancybox.defaults.i18n = { en_US: { CLOSE: "Close", NEXT: "Next", PREV: "Previous", ERROR: "The requested content cannot be loaded.
    Please try again later.", PLAY_START: "Start slideshow", PLAY_STOP: "Pause slideshow", FULL_SCREEN: "Full screen", THUMBS: "Thumbnails", DOWNLOAD: "Download", SHARE: "Share", ZOOM: "Zoom" }, zh_CN: { CLOSE: "关闭", NEXT: "下一个", PREV: "上一个", ERROR: "图片加载失败", PLAY_START: "开始幻灯片展示", PLAY_STOP: "暂停幻灯片展示", FULL_SCREEN: "全屏", THUMBS: "缩略图", DOWNLOAD: "下载", SHARE: "分享", ZOOM: "缩放" } }; /*Lazyload - 使用 IntersectionObserver 实现懒加载 /* * 优化说明: * 1. 使用全局 lazyloadObserver 变量,便于在 PJAX 切换时清理 * 2. 添加 Observer 存在性检查,防止重复初始化 * 3. 使用 requestAnimationFrame 替代 setTimeout 实现加载效果 * 4. 实现滚动监听降级方案,支持不兼容 IntersectionObserver 的浏览器 * 5. 使用 transitionend 事件清理样式,避免固定延迟 */ // 全局 Observer 实例,用于清理 var lazyloadObserver = null; // 全局滚动监听 handler,用于降级方案清理 var lazyloadScrollHandler = null; function lazyloadInit() { // 清理旧的 Observer(防止重复初始化) if (lazyloadObserver) { try { lazyloadObserver.disconnect(); lazyloadObserver = null; ArgonDebug.log('清理旧的 Lazyload Observer'); } catch(e) { ArgonDebug.warn('清理 Lazyload Observer 失败:', e); lazyloadObserver = null; } } // 清理旧的滚动监听器(降级方案) if (lazyloadScrollHandler) { try { window.removeEventListener('scroll', lazyloadScrollHandler); window.removeEventListener('resize', lazyloadScrollHandler); lazyloadScrollHandler = null; ArgonDebug.log('清理旧的滚动监听器'); } catch(e) { ArgonDebug.warn('清理滚动监听器失败:', e); lazyloadScrollHandler = null; } } // 检查是否启用懒加载 if (argonConfig.lazyload === false || argonConfig.lazyload === 'false') { // 未启用懒加载时,直接加载所有图片 loadAllImagesImmediately(); return; } let images = document.querySelectorAll('img.lazyload[data-src]'); if (images.length === 0) { ArgonDebug.log('没有需要懒加载的图片'); return; } let effect = argonConfig.lazyload_effect || 'fadeIn'; let threshold = parseInt(argonConfig.lazyload_threshold) || 800; ArgonDebug.log(`初始化懒加载: ${images.length} 张图片, 效果: ${effect}, 阈值: ${threshold}px`); // 使用 IntersectionObserver 实现懒加载 if ('IntersectionObserver' in window) { try { lazyloadObserver = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (entry.isIntersecting) { let img = entry.target; loadImageOptimized(img, effect); lazyloadObserver.unobserve(img); } }); }, { rootMargin: threshold + 'px 0px' }); images.forEach(function(img) { // 重置图片状态 img.style.opacity = ''; img.style.transform = ''; img.style.transition = ''; lazyloadObserver.observe(img); }); ArgonDebug.log('使用 IntersectionObserver 实现懒加载'); } catch(e) { ArgonDebug.error('IntersectionObserver 初始化失败,使用降级方案:', e); lazyloadFallback(images, effect, threshold); } } else { // 降级方案:使用滚动监听 ArgonDebug.log('浏览器不支持 IntersectionObserver,使用滚动监听降级方案'); lazyloadFallback(images, effect, threshold); } } /** * 优化的图片加载函数 * 使用 requestAnimationFrame 替代 setTimeout * @param {HTMLImageElement} img - 图片元素 * @param {string} effect - 加载效果类型 ('fadeIn' 或'slideDown') */ function loadImageOptimized(img, effect) { let src = img.getAttribute('data-src'); if (!src) { // 如果没有 data-src,取消 Observer 监听 if (lazyloadObserver) { lazyloadObserver.unobserve(img); } return; } // 预加载图片 let tempImg = new Image(); tempImg.onload = function() { // 使用 requestAnimationFrame 优化 DOM 操作 requestAnimationFrame(function() { img.src = src; img.removeAttribute('data-src'); let srcset = img.getAttribute('data-srcset'); if (srcset) { img.setAttribute('srcset', srcset); img.removeAttribute('data-srcset'); } let sizes = img.getAttribute('data-sizes'); if (sizes) { img.setAttribute('sizes', sizes); img.removeAttribute('data-sizes'); } img.classList.remove('lazyload'); // 移除所有lazyload-style-* 类 img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim(); // 应用加载效果 applyLoadEffectOptimized(img, effect); }); }; tempImg.onerror = function() { // 加载失败时使用降级方案 requestAnimationFrame(function() { img.src = src; img.removeAttribute('data-src'); let srcset = img.getAttribute('data-srcset'); if (srcset) { img.setAttribute('srcset', srcset); img.removeAttribute('data-srcset'); } let sizes = img.getAttribute('data-sizes'); if (sizes) { img.setAttribute('sizes', sizes); img.removeAttribute('data-sizes'); } img.classList.remove('lazyload'); img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim(); // 取消 Observer 监听 if (lazyloadObserver) { lazyloadObserver.unobserve(img); } }); }; tempImg.src = src; } /** * 使用 requestAnimationFrame 应用加载效果 * @param {HTMLImageElement} img - 图片元素 * @param {string} effect - 加载效果类型 ('fadeIn' 或'slideDown') */ function applyLoadEffectOptimized(img, effect) { if (effect === 'fadeIn') { img.style.opacity = '0'; img.style.transition = 'opacity 0.3s ease'; requestAnimationFrame(function() { requestAnimationFrame(function() { img.style.opacity = '1'; }); }); // 使用 transitionend 事件清理样式,更可靠 img.addEventListener('transitionend', function cleanup() { img.style.transition = ''; img.removeEventListener('transitionend', cleanup); }, {once: true}); } else if (effect === 'slideDown') { img.style.opacity = '0'; img.style.transform = 'translateY(-20px)'; img.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; requestAnimationFrame(function() { requestAnimationFrame(function() { img.style.opacity = '1'; img.style.transform = 'translateY(0)'; }); }); // 使用 transitionend 事件清理样式 img.addEventListener('transitionend', function cleanup() { img.style.transition = ''; img.style.transform = ''; img.removeEventListener('transitionend', cleanup); }, {once: true}); } } /** * 降级方案:使用滚动监听实现懒加载 * 当浏览器不支持IntersectionObserver 时使用 * @param {NodeList|Array} images - 需要懒加载的图片元素列表 * @param {string} effect - 加载效果类型 * @param {number} threshold - 提前加载的阈值(像素) */ function lazyloadFallback(images, effect, threshold) { let loadedImages = new Set(); function checkImagesInView() { let viewportHeight = window.innerHeight; let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; images.forEach(function(img) { if (loadedImages.has(img)) return; let rect = img.getBoundingClientRect(); if (rect.top < viewportHeight + threshold && rect.bottom > -threshold) { loadImageOptimized(img, effect); loadedImages.add(img); } }); // 如果所有图片都已加载,清理监听器 if (loadedImages.size === images.length) { if (lazyloadScrollHandler) { window.removeEventListener('scroll', lazyloadScrollHandler); window.removeEventListener('resize', lazyloadScrollHandler); lazyloadScrollHandler = null; ArgonDebug.log('所有图片已加载,清理滚动监听器'); } } } // 使用 eventManager 的节流函数优化性能 lazyloadScrollHandler = argonEventManager ? argonEventManager.throttle(checkImagesInView, 100) : checkImagesInView; // 绑定事件监听器 window.addEventListener('scroll', lazyloadScrollHandler, {passive: true}); window.addEventListener('resize', lazyloadScrollHandler, {passive: true}); // 立即检查一次 checkImagesInView(); } /** * 立即加载所有图片(懒加载禁用时) * 不应用任何加载效果,直接替换 src */ function loadAllImagesImmediately() { let images = document.querySelectorAll('img.lazyload[data-src]'); images.forEach(function(img) { let src = img.getAttribute('data-src'); if (src) { img.src = src; img.removeAttribute('data-src'); let srcset = img.getAttribute('data-srcset'); if (srcset) { img.setAttribute('srcset', srcset); img.removeAttribute('data-srcset'); } let sizes = img.getAttribute('data-sizes'); if (sizes) { img.setAttribute('sizes', sizes); img.removeAttribute('data-sizes'); } img.classList.remove('lazyload'); img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim(); } }); } // 确保 DOM 加载完成后再初始化懒加载 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', lazyloadInit); } else { // DOM 已经加载完成,立即初始化 lazyloadInit(); } /*Pangu.js*/ function panguInit(){ if (argonConfig.pangu.indexOf("article") >= 0){ pangu.spacingElementByClassName('post-content'); } if (argonConfig.pangu.indexOf("comment") >= 0){ pangu.spacingElementById('comments'); } if (argonConfig.pangu.indexOf("shuoshuo") >= 0){ pangu.spacingElementByClassName('shuoshuo-content'); } } panguInit(); /*Clamp.js*/ function clampInit(){ $(".clamp").each(function(index, dom) { $clamp(dom, {clamp: dom.getAttribute("clamp-line")}); }); } clampInit(); /*Tippy.js*/ function tippyInit(){ //Reference Popover tippy('sup.reference[data-content]:not(.tippy-initialized)', { content: (reference) => reference.getAttribute('data-content'), allowHTML: true, interactive: true,theme: 'light scroll-y', delay: [100, 250], animation: 'fade' }); $("sup.reference[data-content]:not(.tippy-initialized)").addClass("tippy-initialized"); } tippyInit(); /*Banner 全屏封面相关*/ if ($("html").hasClass("banner-as-cover")){ function classInit(){ if ($("#main").hasClass("article-list-home")){ if (!$("html").hasClass("is-home")){ $("html").addClass("is-home"); $("html").trigger("resize"); } }else{ if ($("html").hasClass("is-home")){ $("html").removeClass("is-home"); $("html").trigger("resize"); } } } classInit(); new MutationObserver(function(mutations, observer){ classInit(); }).observe(document.querySelector("#primary"), { 'childList': true }); $(".cover-scroll-down").on("click" , function(){ gotoHash("#content", 600, 'easeOutCirc'); $("#content").focus(); }); $fabs = $("#float_action_buttons"); $coverScrollDownBtn = $(".cover-scroll-down"); function changeWidgetsDisplayStatus(){ let scrollTop = $(window).scrollTop(); if (scrollTop >= window.outerHeight * 0.2){ $fabs.removeClass("hidden"); }else{ $fabs.addClass("hidden"); } if (scrollTop >= window.outerHeight * 0.6){ $coverScrollDownBtn.addClass("hidden"); }else{ $coverScrollDownBtn.removeClass("hidden"); } } changeWidgetsDisplayStatus(); $(window).scroll(function(){ changeWidgetsDisplayStatus(); }); $(window).resize(function(){ changeWidgetsDisplayStatus(); }); } /*Pjax*/ var pjaxScrollTop = 0, pjaxLoading = false; // ========================================================================== // 统一的资源清理管理器 // ========================================================================== // 在 PJAX 页面切换时清理所有旧页面资源,避免内存泄漏和功能失效 // Validates: Requirements 1.1, 1.2, 1.3, 1.4, 2.3, 6.1 // ========================================================================== /** * 清理 Lazyload Observer 和滚动监听器 * @returns {void} */ function cleanupLazyloadObserver() { // 清理 IntersectionObserver if (lazyloadObserver) { try { lazyloadObserver.disconnect(); lazyloadObserver = null; ArgonDebug.log('Lazyload Observer 已清理'); } catch(e) { ArgonDebug.warn('清理 Lazyload Observer 失败:', e); lazyloadObserver = null; } } // 清理滚动监听器(降级方案) if (lazyloadScrollHandler) { try { window.removeEventListener('scroll', lazyloadScrollHandler); window.removeEventListener('resize', lazyloadScrollHandler); lazyloadScrollHandler = null; ArgonDebug.log('Lazyload 滚动监听器已清理'); } catch(e) { ArgonDebug.warn('清理 Lazyload 滚动监听器失败:', e); lazyloadScrollHandler = null; } } } /** * 清理 Zoomify 实例 * @returns {void} */ function cleanupZoomifyInstances() { if (zoomifyInstances && zoomifyInstances.length > 0) { let cleanedCount = 0; zoomifyInstances.forEach(function(instance) { try { if (instance && typeof instance.destroy === 'function') { instance.destroy(); cleanedCount++; } } catch(e) { ArgonDebug.warn('销毁 Zoomify 实例失败:', e); } }); zoomifyInstances = []; ArgonDebug.log(`已清理 ${cleanedCount} 个 Zoomify 实例`); } // 移除初始化标记 $('img.zoomify-initialized').removeClass('zoomify-initialized'); } /** * 清理 Tippy 实例 * @returns {void} */ function cleanupTippyInstances() { if (typeof tippy !== 'undefined') { let cleanedCount = 0; document.querySelectorAll('[data-tippy-root]').forEach(function(el) { try { if (el._tippy && typeof el._tippy.destroy === 'function') { el._tippy.destroy(); cleanedCount++; } } catch(e) { ArgonDebug.warn('销毁 Tippy 实例失败:', e); } }); $('.tippy-initialized').removeClass('tippy-initialized'); if (cleanedCount > 0) { ArgonDebug.log(`已清理 ${cleanedCount} 个 Tippy 实例`); } } } /** * 清理动态添加的 style 标签 * @returns {void} */ function cleanupDynamicStyles() { try { // 只清理标记为动态的样式 const dynamicStyles = document.querySelectorAll('style[data-dynamic="true"]'); if (dynamicStyles.length > 0) { dynamicStyles.forEach(function(style) { style.remove(); }); ArgonDebug.log(`已清理 ${dynamicStyles.length} 个动态样式`); } } catch(e) { ArgonDebug.warn('清理动态样式失败:', e); } } /** * 清理动态添加的 script 标签 * @returns {void} */ function cleanupDynamicScripts() { try { // 只清理标记为动态的脚本 const dynamicScripts = document.querySelectorAll('script[data-dynamic="true"]'); if (dynamicScripts.length > 0) { dynamicScripts.forEach(function(script) { script.remove(); }); ArgonDebug.log(`已清理 ${dynamicScripts.length} 个动态脚本`); } } catch(e) { ArgonDebug.warn('清理动态脚本失败:', e); } } /** * 清理事件监听器 * @returns {void} */ function cleanupEventListeners() { try { // 注意:大部分事件使用事件委托,不需要手动清理 // 这里只清理特定的非委托事件 // Lazyload 滚动监听器已在 cleanupLazyloadObserver() 中清理 ArgonDebug.log('事件监听器已清理'); } catch(e) { ArgonDebug.warn('清理事件监听器失败:', e); } } /** * 清理 PJAX 页面切换前的所有资源 * 统一的资源清理管理器,在 pjax:beforeReplace 事件中调用 * * 清理内容包括: * - Lazyload Observer * - Zoomify 实例 * - Tippy 实例 * - 动态 style 标签 * - 动态 script 标签 * - 事件监听器 * * @returns {void} */ function cleanupPjaxResources() { ArgonDebug.log('开始清理 PJAX 资源...'); // 按顺序清理各类资源 cleanupLazyloadObserver(); cleanupZoomifyInstances(); cleanupTippyInstances(); cleanupDynamicStyles(); cleanupDynamicScripts(); cleanupEventListeners(); ArgonDebug.log('PJAX 资源清理完成'); } /** * 重置 GT4 验证码 * 清理状态变量、隐藏字段和容器,然后重新初始化 * 在 pjax:end 事件中调用 */ function resetGT4Captcha() { try { if ($('#geetest-captcha').length > 0) { // 重置前端状态,避免重复提交阻塞 window.geetestVerified = false; window.geetestAutoSubmitting = false; // 清空隐藏字段,防止残留导致pass_token 复用 $('#geetest_lot_number').val(''); $('#geetest_captcha_output').val(''); $('#geetest_pass_token').val(''); $('#geetest_gen_time').val(''); // 清空容器,防止重复appendTo 导致多个实例 $('#geetest-captcha').empty(); // 若页面脚本已提供初始化方法,则调用以加载验证码 if (typeof initGeetestCaptcha === 'function') { initGeetestCaptcha(); } else if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') { loadGeetestScript(function() { initGeetestCaptchaCore(); }); } } } catch (e) { ArgonDebug.warn('Geetest init on PJAX failed:', e); } } function handleHashNavigation() { if (!location.hash) { return; } let target = null; try { target = document.getElementById(decodeURIComponent(location.hash.slice(1))); } catch (e) { target = document.querySelector(location.hash); } if (!target) { return; } try { highlightJsRender(); } catch (err) { ArgonDebug.error('highlightJsRender failed:', err); } try { lazyloadInit(); } catch (err) { ArgonDebug.error('lazyloadInit failed:', err); } } // ========================================================================== // 内联脚本执行器 (Inline Script Executor) // ========================================================================== /** * 执行单个脚本元素 * 需求 4.4: 脚本执行失败时捕获错误并记录日志,不中断其他脚本执行 * * @param {HTMLScriptElement} oldScript - 原始脚本元素 * @returns {boolean} 是否执行成功 */ function executeScript(oldScript) { try { // 创建新的 script 元素 const newScript = document.createElement('script'); // 复制脚本内容 if (oldScript.textContent) { newScript.textContent = oldScript.textContent; } // 复制所有属性(包括 type, async, defer 等) // 需求 4.5: 尊重 async 和 defer 属性的执行时机 Array.from(oldScript.attributes).forEach(attr => { newScript.setAttribute(attr.name, attr.value); }); // 将脚本添加到 head 并立即执行 document.head.appendChild(newScript); // 执行后立即移除,避免污染 DOM document.head.removeChild(newScript); ArgonDebug.log('Script executed successfully:', oldScript.textContent.substring(0, 50) + '...'); return true; } catch (error) { // 需求 4.4: 捕获错误并记录日志 ArgonDebug.error('Script execution failed:', error); ArgonDebug.error('Failed script content:', oldScript.textContent); return false; } } /** * 执行新页面中的所有内联脚本 * 需求 4.1: 提取新页面中的所有 script 标签 * 需求 4.2: 区分内联脚本和外部脚本 * 需求 4.3: 按照脚本在 DOM 中的顺序执行 * 需求 4.4: 脚本执行失败不中断其他脚本执行 * * @param {HTMLElement|Document} container - 新页面的容器元素或文档对象 * @returns {Object} 执行结果统计 {total, success, failed} */ function executeInlineScripts(container) { // 如果没有传入容器,使用整个文档 if (!container) { container = document; } // 需求 4.1: 提取所有 script 标签 const scripts = container.querySelectorAll('script'); if (scripts.length === 0) { ArgonDebug.log('No scripts found in new page'); return {total: 0, success: 0, failed: 0}; } let successCount = 0; let failedCount = 0; ArgonDebug.log(`Found ${scripts.length} script tags in new page`); // 需求 4.3: 按照脚本在 DOM 中的顺序执行 scripts.forEach((script, index) => { if (script.getAttribute('data-pjax-executed') === 'true') { return; } // 需求 4.2: 只执行内联脚本(没有 src 属性的脚本) if (!script.src) { // 跳过空脚本 if (!script.textContent || script.textContent.trim() === '') { ArgonDebug.log(`Script ${index + 1}: Empty, skipped`); return; } ArgonDebug.log(`Executing inline script ${index + 1}/${scripts.length}`); // 需求 4.4: 错误隔离 - 单个脚本失败不影响其他脚本 const success = executeScript(script); if (success) { script.setAttribute('data-pjax-executed', 'true'); successCount++; } else { failedCount++; } } else { // 外部脚本由浏览器自动加载,不需要手动执行 ArgonDebug.log(`Script ${index + 1}: External (${script.src}), skipped`); } }); const result = { total: scripts.length, success: successCount, failed: failedCount }; ArgonDebug.log('Script execution completed:', result); return result; } var pjaxContainerSelectors = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar']; var pjaxContainers = pjaxContainerSelectors.filter(function(selector) { return document.querySelector(selector); }); // ========================================================================== // 现代化页面加载系统 // ========================================================================== /** * 页面加载管理器 - 提供智能加载动画和进度追踪 */ const PageLoader = (function() { // 配置常量 const CONFIG = { OVERLAY_ID: 'page-loader', MIN_DISPLAY_TIME: 400, // 最小显示时间(避免闪烁) FADE_DURATION: 350, // 淡出动画时长 PROGRESS_STEP: 0.1, // 进度条步进 PROGRESS_INTERVAL: 200, // 进度更新间隔 SKELETON_DELAY: 150 // 骨架屏延迟显示 }; // 状态管理 let state = { element: null, isVisible: false, startTime: 0, progress: 0, progressTimer: null, hideTimer: null, skeletonTimer: null }; /** * 创建加载动画 HTML */ function createHTML() { return `
    加载中
    正在为您准备内容
    `; } /** * 创建加载器元素 */ function createElement() { const el = document.createElement('div'); el.id = CONFIG.OVERLAY_ID; el.className = 'page-loader'; el.innerHTML = createHTML(); return el; } /** * 获取或创建元素 */ function getElement() { if (!state.element) { state.element = document.getElementById(CONFIG.OVERLAY_ID); if (!state.element) { state.element = createElement(); document.body.appendChild(state.element); } } return state.element; } /** * 更新进度环 */ function updateProgress(progress) { const el = state.element; if (!el) return; const circle = el.querySelector('.loader-ring-progress'); if (circle) { const circumference = 2 * Math.PI * 45; const offset = circumference - (progress / 100) * circumference; circle.style.strokeDashoffset = offset; } state.progress = progress; } /** * 自动递增进度 */ function startProgressAnimation() { stopProgressAnimation(); state.progress = 0; updateProgress(0); state.progressTimer = setInterval(function() { if (state.progress < 90) { // 使用缓动函数,越接近 90% 越慢 const increment = CONFIG.PROGRESS_STEP * (1 - state.progress / 100); state.progress = Math.min(90, state.progress + increment * 10); updateProgress(state.progress); } }, CONFIG.PROGRESS_INTERVAL); } /** * 停止进度动画 */ function stopProgressAnimation() { if (state.progressTimer) { clearInterval(state.progressTimer); state.progressTimer = null; } } /** * 完成进度到 100% */ function completeProgress() { stopProgressAnimation(); updateProgress(100); } /** * 显示加载器 */ function show() { // 清理之前的定时器 if (state.hideTimer) { clearTimeout(state.hideTimer); state.hideTimer = null; } if (state.skeletonTimer) { clearTimeout(state.skeletonTimer); state.skeletonTimer = null; } const el = getElement(); state.startTime = Date.now(); state.isVisible = true; // 移除隐藏类,添加显示类 el.classList.remove('is-hiding'); void el.offsetWidth; // 强制重排 el.classList.add('is-visible'); // 启动进度动画 startProgressAnimation(); // 延迟显示骨架屏(避免快速加载时闪烁) state.skeletonTimer = setTimeout(function() { if (state.isVisible && el) { el.classList.add('show-skeleton'); } }, CONFIG.SKELETON_DELAY); } /** * 隐藏加载器 */ function hide() { if (!state.isVisible) return; const el = state.element; if (!el) return; // 完成进度 completeProgress(); // 计算已显示时间 const elapsedTime = Date.now() - state.startTime; const remainingTime = Math.max(0, CONFIG.MIN_DISPLAY_TIME - elapsedTime); // 确保最小显示时间后再隐藏 state.hideTimer = setTimeout(function() { el.classList.add('is-hiding'); el.classList.remove('show-skeleton'); // 动画结束后清理 setTimeout(function() { el.classList.remove('is-visible', 'is-hiding'); state.isVisible = false; stopProgressAnimation(); }, CONFIG.FADE_DURATION); }, remainingTime); } /** * 设置进度(手动控制) */ function setProgress(progress) { progress = Math.max(0, Math.min(100, progress)); stopProgressAnimation(); updateProgress(progress); } /** * 销毁加载器 */ function destroy() { stopProgressAnimation(); if (state.hideTimer) { clearTimeout(state.hideTimer); state.hideTimer = null; } if (state.skeletonTimer) { clearTimeout(state.skeletonTimer); state.skeletonTimer = null; } if (state.element && state.element.parentNode) { state.element.parentNode.removeChild(state.element); } state.element = null; state.isVisible = false; } // 公开 API return { show: show, hide: hide, setProgress: setProgress, destroy: destroy }; })(); /** * 向后兼容的函数 */ function showLoadingOverlay() { PageLoader.show(); } function hideLoadingOverlay() { PageLoader.hide(); } function startPageTransition() { document.documentElement.classList.add('page-transition-enter'); pjaxContainers.forEach(function(selector) { var c = document.querySelector(selector); if (c) c.classList.add('page-transition-content'); }); } function activatePageTransition() { requestAnimationFrame(function() { document.documentElement.classList.add('page-transition-active'); }); } function endPageTransition() { document.documentElement.classList.remove('page-transition-active'); document.documentElement.classList.remove('page-transition-enter'); pjaxContainers.forEach(function(selector) { var c = document.querySelector(selector); if (c) c.classList.remove('page-transition-content'); }); } $.pjax.defaults.timeout = 10000; $.pjax.defaults.container = pjaxContainers; $.pjax.defaults.fragment = pjaxContainers; /* * PJAX 事件处理优化说明: * 1. pjax:beforeReplace - 统一清理资源(LazyLoad Observer、Zoomify、Tippy) * 2. pjax:complete - 单次初始化所有功能模块,添加错误处理,初始化所有功能模块 * 3. pjax:end - 只处理特定任务(移动端目录重置、GT4 验证码重置) * 4. 移除了重复的初始化调用,避免资源泄漏和性能问题 * * 需求映射: * - pjax:beforeReplace: 需求 1.1-1.4 (资源清理) * - pjax:complete: 需求 1.5, 1.6 (模块初始化和错误隔离) * - pjax:end: 需求 1.7 (特定任务处理) */ if (argonConfig.disable_pjax != true && argonConfig.disable_pjax != 'true') { $(document).pjax( "a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):not([download]):not(.reference-link):not(.reference-list-backlink):not([href^='#'])", pjaxContainers.length ? pjaxContainers[0] : '#primary', { fragment: (pjaxContainers.length ? pjaxContainers : ['#primary']), timeout: $.pjax.defaults.timeout } ) .on('pjax:click', function(e, f, g){ NProgress.remove(); NProgress.start(); pjaxLoading = true; showLoadingOverlay(); }).on('pjax:afterGetContainers', function(e, f, g) { pjaxScrollTop = 0; if ($("html").hasClass("banner-as-cover")){ if (g.is(".page-link")){ pjaxScrollTop = $("#content").offset().top - 80; } } }).on('pjax:send', function() { NProgress.set(0.618); startPageTransition(); }).on('pjax:beforeReplace', function(e, dom) { // ========== 需求 1.1-1.4: 清理旧页面的所有资源 ========== // 调用统一的资源清理管理器 // 清理内容:Lazyload Observer、Zoomify、Tippy 实例、动态标签 cleanupPjaxResources(); // 更新 UI 状态 if ($("#post_comment", dom[0]).length > 0){ $("#fabtn_go_to_comment").removeClass("d-none"); }else{ $("#fabtn_go_to_comment").addClass("d-none"); } // 处理滚动位置 if ($("html").hasClass("banner-as-cover")){ if (!$("#main").hasClass("article-list-home")){ pjaxScrollTop = 0; } } }).on('pjax:complete', function() { // ========== 需求 1.5, 1.6: 重新初始化所有功能模块 ========== pjaxLoading = false; NProgress.inc(); startPageTransition(); activatePageTransition(); setTimeout(function() { hideLoadingOverlay(); endPageTransition(); }, 320); // ========== 需求 4.1-4.5: 执行新页面中的内联脚本 ========== try { pjaxContainers.forEach(function(selector) { var container = document.querySelector(selector); if (container) { executeInlineScripts(container); } }); } catch (err) { ArgonDebug.error('executeInlineScripts failed:', err); } // MathJax 数学公式渲染 try{ if (MathJax != undefined){ if (MathJax.Hub != undefined){ MathJax.Hub.Typeset(); }else{ MathJax.typeset(); } } }catch (err){} // KaTeX 数学公式渲染 try{ if (renderMathInElement != undefined){ renderMathInElement(document.body,{ delimiters: [ {left: "$$", right: "$$", display: true}, {left: "$", right: "$", display: false}, {left: "\\(", right: "\\)", display: false} ] }); } }catch (err){} // 初始化各个功能模块(添加错误处理确保单个模块失败不影响其他模块) try { waterflowInit(); } catch (err) { ArgonDebug.error('waterflowInit failed:', err); } try { lazyloadInit(); } catch (err) { ArgonDebug.error('lazyloadInit failed:', err); } try { zoomifyInit(); } catch (err) { ArgonDebug.error('zoomifyInit failed:', err); } try { highlightJsRender(); } catch (err) { ArgonDebug.error('highlightJsRender failed:', err); } try { panguInit(); } catch (err) { ArgonDebug.error('panguInit failed:', err); } try { clampInit(); } catch (err) { ArgonDebug.error('clampInit failed:', err); } try { tippyInit(); } catch (err) { ArgonDebug.error('tippyInit failed:', err); } try { getGithubInfoCardContent(); } catch (err) { ArgonDebug.error('getGithubInfoCardContent failed:', err); } try { showPostOutdateToast(); } catch (err) { ArgonDebug.error('showPostOutdateToast failed:', err); } try { calcHumanTimesOnPage(); } catch (err) { ArgonDebug.error('calcHumanTimesOnPage failed:', err); } try { foldLongComments(); } catch (err) { ArgonDebug.error('foldLongComments failed:', err); } try { foldLongShuoshuo(); } catch (err) { ArgonDebug.error('foldLongShuoshuo failed:', err); } try { handleHashNavigation(); } catch (err) { ArgonDebug.error('handleHashNavigation failed:', err); } $("html").trigger("resize"); // 恢复滚动位置 if (pjaxScrollTop > 0) { $("body,html").scrollTop(pjaxScrollTop); pjaxScrollTop = 0; } // 调用用户自定义的 PJAX 加载完成回调 if (typeof(window.pjaxLoaded) == "function"){ try{ window.pjaxLoaded(); }catch (err){ ArgonDebug.error(err); } } NProgress.done(); }).on('pjax:error', function() { hideLoadingOverlay(); endPageTransition(); pjaxLoading = false; }).on('pjax:end', function() { // ========== 需求 1.7: 执行特定任务 ========== // 重置移动端目录状态 if (typeof window.resetMobileCatalog === 'function') { try { window.resetMobileCatalog(); } catch (err) { ArgonDebug.warn('resetMobileCatalog failed:', err); } } // GT4: PJAX 后确保评论页验证码已初始化 resetGT4Captcha(); }); } window.addEventListener('hashchange', function() { handleHashNavigation(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { handleHashNavigation(); }); } else { handleHashNavigation(); } /*Reference 跳转*/ $(document).on("click", ".reference-link , .reference-list-backlink" , function(e){ e.preventDefault(); var href = $(this).attr("href"); if (!href || href === "#" ) { return; } var $target; try { $target = $(href); } catch (err) { return; } $("body,html").animate({ scrollTop: $target.offset().top - document.body.clientHeight / 2 - 75 }, 500, 'easeOutExpo') setTimeout(function(){ if ($target.is("li")){ $(".space", $target).focus(); }else{ $target.focus(); } }, 1); }); /*Tags Dialog pjax 加载后自动关闭 */ $(document).on("click" , "#blog_tags .tag" , function(){ $("#blog_tags button.close").trigger("click"); }); $(document).on("click" , "#blog_categories .tag" , function(){ $("#blog_categories button.close").trigger("click"); }); /*侧栏 & 顶栏菜单手机适配*/ !function(){ $(document).on("click" , "#fabtn_open_sidebar, #open_sidebar" , function(){ $("html").addClass("leftbar-opened"); // 侧边栏打开时初始化移动端文章目录 initMobileCatalog(); // 如果有文章目录,默认展开 setTimeout(function() { var catalogSection = $("#mobile_catalog_toggle").closest(".leftbar-mobile-collapse-section"); if (catalogSection.length > 0 && !catalogSection.hasClass("expanded")) { catalogSection.addClass("expanded"); initMobileCatalog(); setTimeout(scrollMobileCatalogToActive, 200); } }, 100); }); $(document).on("click" , "#sidebar_mask, #leftbar_close_btn" , function(){ $("html").removeClass("leftbar-opened"); // 关闭侧边栏时折叠所有面板 $(".leftbar-mobile-collapse-section.expanded").removeClass("expanded"); }); $(document).on("click" , "#leftbar a[href]:not([no-pjax]):not([href^='#']):not(.has-submenu)" , function(){ $("html").removeClass("leftbar-opened"); // 关闭侧边栏时折叠所有面板 $(".leftbar-mobile-collapse-section.expanded").removeClass("expanded"); }); // 移动端子菜单展开/收起 $(document).on("click" , ".leftbar-mobile-menu-item.has-children > a.has-submenu" , function(e){ e.preventDefault(); $(this).parent().toggleClass("expanded"); }); // 移动端侧边栏搜索 $(document).on("keydown" , "#leftbar_mobile_search_input" , function(e){ if (e.keyCode != 13){ return; } let word = $(this).val(); if (word == ""){ return; } $("html").removeClass("leftbar-opened"); // 关闭侧边栏时折叠所有面板 $(".leftbar-mobile-collapse-section.expanded").removeClass("expanded"); searchPosts(word); }); $(document).on("click" , "#navbar_global.show .navbar-nav a[href]:not([no-pjax]):not([href^='#'])" , function(){ $("#navbar_global .navbar-toggler").click(); }); $(document).on("click" , "#navbar_global.show #navbar_search_btn_mobile" , function(){ $("#navbar_global .navbar-toggler").click(); }); // ========== 移动端折叠面板交互========== $(document).on("click", ".leftbar-mobile-collapse-header", function(e) { var section = $(this).closest(".leftbar-mobile-collapse-section"); var header = $(this); var isExpanded = section.hasClass("expanded"); // 切换展开状态 section.toggleClass("expanded"); // 如果是文章目录面板展开,初始化目录并滚动到当前位置 if (!isExpanded && header.attr("id") === "mobile_catalog_toggle") { initMobileCatalog(); setTimeout(scrollMobileCatalogToActive, 100); } }); // ========== 移动端文章目录初始化 ========== window.mobileCatalogInitialized = false; function initMobileCatalog() { if (window.mobileCatalogInitialized) return; var $mobileContainer = $("#leftbar_mobile_catalog"); var $postContent = $("#post_content"); if ($mobileContainer.length === 0) return; if ($postContent.length === 0) return; // 直接生成目录,不依赖 headIndex 插件 var $headers = $postContent.find('h1, h2, h3, h4, h5, h6'); if ($headers.length === 0) { $mobileContainer.html('
    暂无目录
    '); return; } // 构建目录树 var toc = []; var stack = [{ level: 0, children: toc }]; $headers.each(function(index) { var $h = $(this); var level = parseInt(this.tagName.charAt(1)); var text = $h.text().trim(); var id = $h.attr('id'); // 确保标题有ID if (!id) { id = 'mobile-heading-' + index; $h.attr('id', id); } var item = { id: id, text: text, level: level, children: [] }; // 找到合适的父级 while (stack.length > 1 && stack[stack.length - 1].level >= level) { stack.pop(); } stack[stack.length - 1].children.push(item); stack.push({ level: level, children: item.children }); }); // 递归生成 HTML function buildHtml(items, isRoot) { if (!items || items.length === 0) return ''; var html = isRoot ? '