diff options
Diffstat (limited to 'assets/js/pjax.js')
| -rw-r--r-- | assets/js/pjax.js | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/assets/js/pjax.js b/assets/js/pjax.js new file mode 100644 index 0000000..a9484e6 --- /dev/null +++ b/assets/js/pjax.js @@ -0,0 +1,153 @@ +/** + * PJAX 初始化与页面切换重绑定脚本 + * 依赖:jQuery, jquery.pjax.min.js + * 加载顺序:在 jquery.pjax.min.js 之后,body 末尾 + */ + +(function ($) { + // ========== 常量 ========== + var CONTAINER = '#pjax-container'; + var PJAX_OPTS = { + container: CONTAINER, + fragment: CONTAINER, + timeout: 5000, + scrollTo: false + }; + + // ========== 各组件重初始化 ========== + + /** Google Analytics 页面浏览事件 */ + function trackPageView() { + if (typeof gtag === 'function') { + gtag('config', window._gaId || '', { page_path: window.location.pathname }); + } + } + + /** Live2D 重初始化 */ + var _live2dSelectors = ['.post-link', '#search-input']; + var _live2dDelegateBound = false; + + function reinitLive2d() { + if (!window._live2d) return; + var pathname = window.location.pathname; + + // 更新"想问这篇文章"相关状态(仅真正的文章页显示) + $('#post_id').val(pathname); + if ($(CONTAINER + ' #gitalk-container').length > 0) { + $('.live_talk_input_name_body').show(); + } else { + $('.live_talk_input_name_body').hide(); + $('#load_this').prop('checked', false); + } + + // 音乐按钮:根据当前页面是否有 BGM 输入来显示/隐藏 + if (typeof window._live2d.initBGM === 'function') { + window._live2d.initBGM(); + } + + // 事件委托绑定(只执行一次) + if (!_live2dDelegateBound && typeof String.prototype.renderTip === 'function') { + var selector = CONTAINER + ' ' + _live2dSelectors.join(', ' + CONTAINER + ' '); + $(document).on('mouseover._live2d_pjax', selector, function (e) { + var $el = $(e.currentTarget || e.target); + if ($el.is('.post-link')) { + window._live2d.showMessage('要看看 ' + $el.text() + ' 么?', 3000); + } else if ($el.is('#search-input')) { + window._live2d.showMessage('在找什么东西呢,需要帮忙吗?', 3000); + } + }); + $(document).on('mouseout._live2d_pjax', selector, function () { + if (window._live2d.showHitokoto) window._live2d.showHitokoto(); + }); + _live2dDelegateBound = true; + } + + // 欢迎语 + if (typeof window._live2d.showMessage === 'function') { + window._live2d.showMessage(getWelcomeText(pathname), 6000); + } + } + + // ========== PJAX 导航 ========== + + /** PJAX 完成后的统一处理 */ + function doPjaxComplete() { + $('body').removeClass('pjax-loading'); + // 清理可能残留的浮层(如推荐文章 tooltip,hover 后点击跳转时 mouseleave 来不及触发) + $('.content-tooltip').remove(); + onPjaxComplete(); + } + + /** 暴露给模板内 onclick/onchange 调用的导航函数 */ + window.go = function (url) { + $.pjax($.extend({ url: url }, PJAX_OPTS)); + }; + + // ========== 初始化 ========== + + /** pjax 完成后滚动到目标位置:有锚点则定位锚点,否则回到顶部 */ + function scrollToAnchor() { + var hash = window.location.hash; + if (hash) { + // 中文等非 ASCII 字符在 URL 中会被编码,需先解码再匹配元素 id + var id = hash.slice(1); + try { id = decodeURIComponent(id); } catch (e) { /* 保持原值 */ } + var target = document.getElementById(id) || + document.querySelector('a[name="' + id + '"]'); + if (target) { + target.scrollIntoView({ behavior: 'smooth', block: 'start' }); + return; + } + } + window.scrollTo(0, 0); + } + + /** 每次 pjax 完成后执行所有重初始化 */ + function onPjaxComplete() { + initVisitors(); + initCopyButtons(); + highlightKeyword(); + reinitLive2d(); + trackPageView(); + scrollToAnchor(); + } + + $(document).ready(function () { + // 排除列表:外链、锚点、静态资源、Live2D 目录 + var exclude = ':not([target="_blank"]):not([href^="http"]):not([href^="//"])' + + ':not([href^="mailto"]):not([href^="#"])' + + ':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#search-input-all', function (e) { + $.pjax.submit(e, PJAX_OPTS.container, PJAX_OPTS); + }); + $(document).on('pjax:send', function () { + $('body').addClass('pjax-loading'); + }); + $(document).on('pjax:complete', doPjaxComplete); + $(document).on('pjax:end', function (event, xhr, options) { + var $container = $(options.container || PJAX_OPTS.container); + + $container.find('script[type="module"]').each(function () { + var oldScript = this; + var newScript = document.createElement('script'); + newScript.type = 'module'; + + // 如果是外链脚本 (<script src="..."></script>) + if (oldScript.src) { + newScript.src = oldScript.src; + } else { + // 如果是行内脚本 (<script>...code...</script>) + newScript.textContent = oldScript.textContent; + } + // 插入到 body 中触发浏览器执行 + document.body.appendChild(newScript); + + // 运行完后建议移除,防止 DOM 变得混乱(不影响模块执行) + newScript.remove(); + }); + }); + }); + +})(jQuery);
\ No newline at end of file |
