|
|
|
@ -14,100 +14,6 @@ |
|
|
|
scrollTo: false |
|
|
|
}; |
|
|
|
|
|
|
|
// ========== 工具函数 ==========
|
|
|
|
|
|
|
|
var _loadedScripts = {}; |
|
|
|
var _pendingScripts = []; |
|
|
|
|
|
|
|
/** 动态加载外部 CSS(避免重复加载) */ |
|
|
|
function loadCSS(href) { |
|
|
|
if ($('link[href="' + href + '"]').length) return; |
|
|
|
$('<link rel="stylesheet" href="' + href + '" />').appendTo('head'); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 动态加载外部 JS(避免重复) |
|
|
|
* 用对象跟踪已加载的 URL,而不是检查 DOM 中的 <script> 标签 |
|
|
|
* (pjax 替换容器内容后,惰性 <script> 标签存在但不代表已执行) |
|
|
|
*/ |
|
|
|
function loadScript(src, callback) { |
|
|
|
if (_loadedScripts[src]) { |
|
|
|
if (typeof callback === 'function') callback(); |
|
|
|
return; |
|
|
|
} |
|
|
|
_loadedScripts[src] = true; |
|
|
|
var s = document.createElement('script'); |
|
|
|
s.src = src; |
|
|
|
s.onload = callback || null; |
|
|
|
document.body.appendChild(s); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按顺序执行脚本数组(内联和外部混合) |
|
|
|
* 外部脚本加载完成后再执行后续内联脚本,保持依赖顺序 |
|
|
|
*/ |
|
|
|
function executeScripts(scripts) { |
|
|
|
var idx = 0; |
|
|
|
function runNext() { |
|
|
|
while (idx < scripts.length) { |
|
|
|
var s = scripts[idx]; |
|
|
|
idx++; |
|
|
|
if (s.src) { |
|
|
|
loadScript(s.src, runNext); |
|
|
|
return; // 等待 onload 回调
|
|
|
|
} |
|
|
|
try { |
|
|
|
(window.execScript || function (code) { |
|
|
|
window['eval'].call(window, code); |
|
|
|
})(s.text); |
|
|
|
} catch (e) { |
|
|
|
console.warn('[pjax] inline script exec error:', e); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
runNext(); |
|
|
|
} |
|
|
|
|
|
|
|
// ========== 页面类型判断 ==========
|
|
|
|
|
|
|
|
/** 是否为文章页(非首页/分页) */ |
|
|
|
function isPostPage(pathname) { |
|
|
|
return !/^(\/(index\.html)?|\/page\d+(\/index\.html)?)$/.test(pathname || window.location.pathname); |
|
|
|
} |
|
|
|
|
|
|
|
/** 是否为真正的文章页(用 DOM 特征判断,仅 post 布局才有这些元素) */ |
|
|
|
function isRealPostPage() { |
|
|
|
return $(CONTAINER + ' #gitalk-container').length > 0; |
|
|
|
} |
|
|
|
|
|
|
|
// ========== 欢迎语生成 ==========
|
|
|
|
|
|
|
|
/** |
|
|
|
* 根据当前时间和页面生成 Live2D 欢迎语 |
|
|
|
* 此函数暴露到 window._live2d.getWelcomeText,供 message.js 首次加载时复用 |
|
|
|
* @param {string} [pathname] - 页面路径,默认当前路径 |
|
|
|
* @param {string} [title] - 页面标题,默认从 document.title 提取 |
|
|
|
* @returns {string} 欢迎语 HTML |
|
|
|
*/ |
|
|
|
function getWelcomeText(pathname, title) { |
|
|
|
pathname = pathname || window.location.pathname; |
|
|
|
title = title || document.title.split(' | ')[0]; |
|
|
|
|
|
|
|
if (pathname === '/' || pathname === '/index.html') { |
|
|
|
var now = (new Date()).getHours(); |
|
|
|
if (now > 23 || now <= 5) return '你是夜猫子呀?这么晚还不睡觉,明天起的来嘛?'; |
|
|
|
if (now > 5 && now <= 7) return '早上好!一日之计在于晨,美好的一天就要开始了!'; |
|
|
|
if (now > 7 && now <= 11) return '上午好!工作顺利嘛,不要久坐,多起来走动走动哦!'; |
|
|
|
if (now > 11 && now <= 14) return '中午了,工作了一个上午,现在是午餐时间!'; |
|
|
|
if (now > 14 && now <= 17) return '午后很容易犯困呢,今天的运动目标完成了吗?'; |
|
|
|
if (now > 17 && now <= 19) return '傍晚了!窗外夕阳的景色很美丽呢,最美不过夕阳红~~'; |
|
|
|
if (now > 19 && now <= 21) return '晚上好,今天过得怎么样?'; |
|
|
|
if (now > 21 && now <= 23) return '已经这么晚了呀,早点休息吧,晚安~~'; |
|
|
|
return '嗨~ 快来逗我玩吧!'; |
|
|
|
} |
|
|
|
return '欢迎阅读<span style="color:#0099cc;">「 ' + title + ' 」</span>'; |
|
|
|
} |
|
|
|
|
|
|
|
// ========== 各组件重初始化 ==========
|
|
|
|
|
|
|
|
/** 访问量统计 */ |
|
|
|
@ -153,28 +59,6 @@ |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** Gitalk 评论(post 页面专属) */ |
|
|
|
function reinitGitalk() { |
|
|
|
if ($(CONTAINER + ' #gitalk-container').length === 0) return; |
|
|
|
loadCSS('/assets/css/gitalk.css'); |
|
|
|
|
|
|
|
function doInitGitalk() { |
|
|
|
if (typeof Gitalk === 'undefined') { |
|
|
|
loadScript('/assets/js/gitalk.min.js', doInitGitalk); |
|
|
|
return; |
|
|
|
} |
|
|
|
var pageId = $(CONTAINER + ' #gitalk-container').data('page-id') || window.location.pathname; |
|
|
|
try { |
|
|
|
new Gitalk(Object.assign({ id: pageId }, window.GitalkConfig)) |
|
|
|
.render('gitalk-container'); |
|
|
|
} catch (e) { |
|
|
|
console.warn('[pjax] Gitalk init error:', e); |
|
|
|
} |
|
|
|
} |
|
|
|
$('#gitalk-container').empty(); |
|
|
|
doInitGitalk(); |
|
|
|
} |
|
|
|
|
|
|
|
/** 关键词高亮 */ |
|
|
|
function reinitHighlight() { |
|
|
|
var keyword = new URLSearchParams(window.location.search).get('kw'); |
|
|
|
@ -220,7 +104,7 @@ |
|
|
|
|
|
|
|
// 更新"想问这篇文章"相关状态(仅真正的文章页显示)
|
|
|
|
$('#post_id').val(pathname); |
|
|
|
if (isRealPostPage()) { |
|
|
|
if ($(CONTAINER + ' #gitalk-container').length > 0) { |
|
|
|
$('.live_talk_input_name_body').show(); |
|
|
|
} else { |
|
|
|
$('.live_talk_input_name_body').hide(); |
|
|
|
@ -261,59 +145,15 @@ |
|
|
|
function doPjaxComplete() { |
|
|
|
$('body').removeClass('pjax-loading'); |
|
|
|
// 清理可能残留的浮层(如推荐文章 tooltip,hover 后点击跳转时 mouseleave 来不及触发)
|
|
|
|
$('.content-tooltip').hide(); |
|
|
|
// go() 路径:脚本在 DOM 替换前提取到了 _pendingScripts,需在此执行
|
|
|
|
// pjax 库路径:_pendingScripts 为空,pjax 库自行处理了脚本执行
|
|
|
|
if (_pendingScripts.length > 0) { |
|
|
|
executeScripts(_pendingScripts); |
|
|
|
_pendingScripts = []; |
|
|
|
} |
|
|
|
$('.content-tooltip').remove(); |
|
|
|
onPjaxComplete(); |
|
|
|
} |
|
|
|
|
|
|
|
/** 暴露给模板内 onclick/onchange 调用的导航函数 */ |
|
|
|
window.go = function (url) { |
|
|
|
$('body').addClass('pjax-loading'); |
|
|
|
$.ajax({ |
|
|
|
url: url, |
|
|
|
beforeSend: function (xhr) { |
|
|
|
xhr.setRequestHeader('X-PJAX', 'true'); |
|
|
|
xhr.setRequestHeader('X-PJAX-Container', CONTAINER); |
|
|
|
}, |
|
|
|
success: function (html) { |
|
|
|
try { |
|
|
|
var doc = (new DOMParser()).parseFromString(html, 'text/html'); |
|
|
|
var fragment = doc.querySelector(CONTAINER); |
|
|
|
if (fragment) { |
|
|
|
// 先提取脚本(jQuery html() 会移除并可能异步处理脚本)
|
|
|
|
_pendingScripts = []; |
|
|
|
fragment.querySelectorAll('script').forEach(function (s) { |
|
|
|
_pendingScripts.push({ |
|
|
|
src: s.src || null, |
|
|
|
text: s.textContent |
|
|
|
}); |
|
|
|
s.remove(); |
|
|
|
}); |
|
|
|
$(CONTAINER).html(fragment.innerHTML); |
|
|
|
document.title = doc.title; |
|
|
|
history.pushState({ url: url }, document.title, url); |
|
|
|
doPjaxComplete(); |
|
|
|
} else { |
|
|
|
window.location.href = url; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
console.warn('[go] parse error, fallback:', e); |
|
|
|
window.location.href = url; |
|
|
|
} |
|
|
|
}, |
|
|
|
error: function () { window.location.href = url; }, |
|
|
|
timeout: PJAX_OPTS.timeout |
|
|
|
}); |
|
|
|
$.pjax({ url: url, ...PJAX_OPTS }); |
|
|
|
}; |
|
|
|
|
|
|
|
/** 暴露 getWelcomeText 供 message.js 首次加载时复用,避免欢迎语逻辑重复 */ |
|
|
|
window._pjaxGetWelcomeText = getWelcomeText; |
|
|
|
|
|
|
|
// ========== 初始化 ==========
|
|
|
|
|
|
|
|
/** 每次 pjax 完成后执行所有重初始化 */ |
|
|
|
@ -321,7 +161,6 @@ |
|
|
|
reinitVisitors(); |
|
|
|
reinitCopyButtons(); |
|
|
|
reinitHighlight(); |
|
|
|
reinitGitalk(); |
|
|
|
reinitAISummary(); |
|
|
|
reinitLive2d(); |
|
|
|
trackPageView(); |
|
|
|
@ -335,7 +174,9 @@ |
|
|
|
':not([href$=".xml"]):not([href$=".json"]):not([href$=".tgz"]):not([href$=".zip"])' + |
|
|
|
':not([href^="/Live2dHistoire"])'; |
|
|
|
$(document).pjax('a' + exclude, PJAX_OPTS.container, PJAX_OPTS); |
|
|
|
|
|
|
|
$(document).on('submit', 'form', function (e) { |
|
|
|
$.pjax.submit(e, PJAX_OPTS.container, PJAX_OPTS); |
|
|
|
}); |
|
|
|
$(document).on('pjax:send', function () { |
|
|
|
$('body').addClass('pjax-loading'); |
|
|
|
}); |
|
|
|
|