Files
blog/themes/Ying/assets/js/modules/mypjax.js
T
zqlit 654de1fdf0 feat(关于页): 重设计为「时间线 + 数据一览」版式,动效对齐全站 UIKit 范式
- 版式:01 关于我(属性四行 + 时间线四节点 + 三张数据卡 + 分类 Top5 条,
  全部构建期实时统计,新增 partial about-intro.html)+ 02 这个博客 + 03 走心
  评论 + 04 热力图,间距统一由 .about-sec 管,字号统一四档
- 动效:纯官方 UIKit scrollspy(与归档页同源)—— target 一律后代选择器、
  动画类用 uk-animation-slide-*-medium(50px 位移)+ repeat:true 滚回重播、
  分节标题 fade 不 repeat;删自研编排器,CSS 只留分类条宽度填充与
  prefers-reduced-motion 守卫
- 修复 PJAX 下 UIKit 不重绑的既有 bug:mypjax.js 换页后调 UIkit.update()
  (评论区/说说的 scrollspy 同样依赖此修复)
- 走心评论:骨架屏、8s 超时、sessionStorage 缓存(10 分钟)、重试按钮;
  异步渲染后手动 UIkit.update() 让卡片参与入场级联
2026-10-07 21:45:46 +08:00

204 lines
7.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 定义pjax 预设pjax
(function() {
if (typeof Pjax === 'undefined') {
console.error('Pjax library is not loaded.');
return;
}
var pjax = new Pjax({
// 这里填写页面中改变的部分(和 CSS 选择器用法一样)
selectors: ["title", "#pjax-container"],
cacheBust: false,
elements: "a", // 拦截所有链接
switches: {
"#pjax-container": Pjax.switches.default
}
});
// 将 pjax 实例挂载到 window 以便调试或外部访问
window.pjax = pjax;
console.log("Pjax initialized:", pjax);
})();
// UIKit 重新扫描(PJAX 必需)
// ─────────────────────────────────────────────────────────────
// UIKit 只在页面加载时做一次「全量 boot」:它遍历 document.body,把带
// uk-* 属性的元素逐个 connect 成组件。PJAX 换入的 DOM 是我们用
// innerHTML 塞进去的,UIKit 的 MutationObserver 虽然监听了 childList,
// 但因为「换入前属性就已存在」,observer 拿不到 attribute 的新增事件,
// 加上 PJAX 的替换发生在 UIKit 首次 boot 之后,组件就永远绑不上。
//
// 症状:uk-scrollspy 的元素停在 visibility:hidden(动画类的初始态),
// 下折叠的内容永久不可见,滚动也不会出现。
//
// 解法:换页后手动调一次 UIkit.update()。它会从传入节点向上走到
// document.body,再对整棵子树递归 connect —— 正好补上这次 boot。
function reinitUIKit(root) {
if (typeof window.UIkit === 'undefined' || typeof window.UIkit.update !== 'function') return;
var target = root || document.getElementById('pjax-container') || document.body;
try {
window.UIkit.update(target);
} catch (e) {
console.warn('UIkit.update failed:', e);
}
}
// 暴露给页面脚本:动态插入带 uk-* 属性的内容后,调一次即可让 UIKit 生效
window.reinitUIKit = reinitUIKit;
// pjax预先加载代码
function pjax_reload() {
console.log("Pjax reload triggered");
// 给pjax容器加入css过渡动画
// var pjaxContainer = document.getElementById("pjax-container");
// if (pjaxContainer) pjaxContainer.classList.add("uk-animation-slide-bottom-small");
// 评论区过渡动画
var selectors = [
".comment-meta",
".comment-author vcard",
".comment-metadata",
".comment-content",
".reply"
];
selectors.forEach(function(selector) {
document.querySelectorAll(selector).forEach(function(el) {
el.setAttribute("uk-scrollspy", "cls: uk-animation-fade; delay: 100");
});
});
// 说说页面过渡动画
var shuoshuoBody = document.getElementById("shuoshuo_body");
if (shuoshuoBody) {
shuoshuoBody.setAttribute("uk-scrollspy", "target: > .shuoshuo; cls: uk-animation-fade; delay: 250");
}
}
function refreshHeatmap() {
if (typeof renderHeatmap === 'function') {
try {
renderHeatmap();
} catch (e) {
console.error('renderHeatmap error:', e);
}
}
}
// pjax发送时期
document.addEventListener("pjax:send", function () {
// pjax动画减少圆圈动画
NProgress.configure({
showSpinner: false
});
// pjax执行动画开始
NProgress.start(); //加载动画效果开始
});
// Pjax 成功后,重新加载下面的函数
document.addEventListener("pjax:success", function () {
// 重载图片懒加载插件的js
if (typeof lazyLoadInit === 'function') {
lazyLoadInit({
// coverColor: "white",
// coverDiv: "<div style='display: flex; justify-content: center; align-items: center; height: 200px; color: #000000;'><span>优世界·一个记录生活点滴的小站</span></div>",
offsetBottom: 50,
offsetTopm: 50,
showTime: 1100,
queueInterval: 100
});
}
// 激活文章图片灯箱
if (window.ViewImage) {
ViewImage.init('.post-content img');
}
if (typeof window.refreshFloatingTools === 'function') {
window.refreshFloatingTools();
}
});
// pjax加载完成
document.addEventListener("pjax:complete", function () {
// 立即执行:进度条、基础 UI
if (typeof NProgress !== 'undefined') NProgress.done();
pjax_reload();
// ★ 关键:pjax_reload() 里刚给评论/说说等元素新加了 uk-scrollspy 属性,
// 此刻连同换入的整棵新 DOM 一起交给 UIKit 重新 boot一遍。
// 必须在 pjax_reload() 之后调用,否则新加的属性会被漏掉。
// (关于页的分节动画也走 UIKit scrollspy,所以同样靠这一步复活。)
reinitUIKit();
// 动态加载页面特定JS(PJAX适配)
// 检测当前页面是否为文章详情页,如果是则加载page-only.js
var currentPath = window.location.pathname;
var isArticlePage = document.querySelector('#Comments') !== null ||
document.querySelector('.post-content') !== null;
if (isArticlePage && !window._pageOnlyLoaded && window._pageOnlyScriptUrl) {
// 动态加载page-only.js(使用Hugo fingerprint后的正确URL)
var script = document.createElement('script');
script.src = window._pageOnlyScriptUrl;
script.onload = function() {
window._pageOnlyLoaded = true;
console.log('page-only.js loaded for PJAX navigation');
// 初始化Artalk等
if (typeof window.initArtalk === 'function') {
try { window.initArtalk(); } catch(e) { console.error('initArtalk error:', e); }
}
if (typeof window.initParagraphComments === 'function') {
try { window.initParagraphComments(); } catch(e) {}
}
};
document.body.appendChild(script);
}
// 下一帧执行:轻量初始化
requestAnimationFrame(function() {
if (typeof initCodeCopy === 'function') initCodeCopy();
if (typeof window.initSearch === 'function') {
try { window.initSearch(); } catch(e) {}
}
if (typeof window.refreshFloatingTools === 'function') {
window.refreshFloatingTools();
} else if (typeof window.initFloatingTools === 'function') {
try { window.initFloatingTools(); } catch(e) {}
}
// 文章动画
if (typeof window.initPostScrollspy === 'function') window.initPostScrollspy();
});
// 空闲时执行:非关键功能
var idle = window.requestIdleCallback || function(fn) { return setTimeout(fn, 200); };
idle(function() {
if (typeof window.initParagraphComments === 'function') {
try { window.initParagraphComments(); } catch(e) {}
}
if (typeof window.initInfiniteScroll === 'function' && window.enableInfiniteScroll) {
window.initInfiniteScroll();
}
if (typeof window.initLinkStatus === 'function') {
try { window.initLinkStatus(); } catch(e) {}
}
if (typeof window.initArtalk === 'function') {
try { window.initArtalk(); } catch(e) {}
}
if (typeof window.bsz_fetch === 'function') {
try { window.bsz_fetch(); } catch(e) {}
}
if (typeof window.initImageFrameReveal === 'function') {
try { window.initImageFrameReveal(); } catch(e) {}
}
// 链接卡片和中英文间距(DOM 扫描,非关键)
if (typeof window.initLinkify === 'function') window.initLinkify();
if (typeof window.initPangu === 'function') window.initPangu();
});
// 延迟:代码折叠
setTimeout(function() {
if (typeof window.initCodeFold === 'function') window.initCodeFold();
}, 300);
});