diff --git a/argontheme.js b/argontheme.js
index d9cc864..c85c2e4 100644
--- a/argontheme.js
+++ b/argontheme.js
@@ -2516,15 +2516,53 @@ $(document).on("click" , "#blog_categories .tag" , function(){
function initMobileCatalog() {
if (window.mobileCatalogInitialized) return;
- if ($("#leftbar_mobile_catalog").length === 0) return;
- if ($("#post_content").length === 0) return;
+ var $mobileContainer = $("#leftbar_mobile_catalog");
+ var $postContent = $("#post_content");
+ if ($mobileContainer.length === 0) return;
+ if ($postContent.length === 0) return;
+ // 直接从桌面端目录复制内容,避免重复初始化 headIndex 导致的冲突
+ var $desktopCatalog = $("#leftbar_catalog");
+ if ($desktopCatalog.length > 0 && $desktopCatalog.children().length > 0) {
+ // 复制桌面端目录内容到移动端
+ $mobileContainer.html($desktopCatalog.html());
+ window.mobileCatalogInitialized = true;
+
+ // 绑定移动端目录的点击事件
+ $mobileContainer.off('click.mobileCatalog').on('click.mobileCatalog', '.index-link', function(e) {
+ e.preventDefault();
+ var targetId = $(this).attr('href');
+ if (targetId && targetId.startsWith('#')) {
+ var $target = $(targetId);
+ if ($target.length) {
+ // 更新高亮状态
+ $mobileContainer.find('.index-item').removeClass('current');
+ $(this).closest('.index-item').addClass('current');
+
+ // 滚动到目标位置
+ $('html, body').animate({
+ scrollTop: $target.offset().top - 80
+ }, 500, 'easeOutExpo');
+ }
+ }
+ });
+
+ // 同步桌面端目录的高亮状态到移动端
+ syncMobileCatalogHighlight();
+
+ setTimeout(scrollMobileCatalogToActive, 150);
+ return;
+ }
+
+ // 如果桌面端目录不存在,则独立初始化移动端目录
var retryCount = 0;
var maxRetries = 30;
function tryInit() {
if (typeof jQuery !== 'undefined' && typeof jQuery.fn.headIndex === 'function') {
- jQuery(document).headIndex({
+ // 使用一个临时的包装元素来初始化,避免与桌面端冲突
+ var $wrapper = $('
');
+ $wrapper.headIndex({
articleWrapSelector: '#post_content',
indexBoxSelector: '#leftbar_mobile_catalog',
subItemBoxClass: "index-subItem-box",
@@ -2533,7 +2571,6 @@ $(document).on("click" , "#blog_categories .tag" , function(){
offset: 80,
});
window.mobileCatalogInitialized = true;
- // 初始化后滚动到当前位置
setTimeout(scrollMobileCatalogToActive, 150);
} else {
retryCount++;
@@ -2546,6 +2583,46 @@ $(document).on("click" , "#blog_categories .tag" , function(){
setTimeout(tryInit, 50);
}
+ // 同步桌面端目录高亮状态到移动端
+ function syncMobileCatalogHighlight() {
+ var $desktopCatalog = $("#leftbar_catalog");
+ var $mobileContainer = $("#leftbar_mobile_catalog");
+
+ if ($desktopCatalog.length === 0 || $mobileContainer.length === 0) return;
+
+ // 监听桌面端目录的高亮变化
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
+ var $target = $(mutation.target);
+ if ($target.hasClass('index-item')) {
+ var href = $target.find('> .index-link').attr('href');
+ if (href) {
+ // 同步高亮状态到移动端
+ $mobileContainer.find('.index-item').removeClass('current');
+ $mobileContainer.find('.index-link[href="' + href + '"]').closest('.index-item').addClass('current');
+ }
+ }
+ }
+ });
+ });
+
+ observer.observe($desktopCatalog[0], {
+ attributes: true,
+ subtree: true,
+ attributeFilter: ['class']
+ });
+
+ // 初始同步当前高亮状态
+ var $currentItem = $desktopCatalog.find('.index-item.current');
+ if ($currentItem.length > 0) {
+ var href = $currentItem.find('> .index-link').attr('href');
+ if (href) {
+ $mobileContainer.find('.index-link[href="' + href + '"]').closest('.index-item').addClass('current');
+ }
+ }
+ }
+
// 重置移动端目录状态(供 PJAX 调用)
window.resetMobileCatalog = function() {
window.mobileCatalogInitialized = false;
diff --git a/assets/vendor/headindex/headindex.js b/assets/vendor/headindex/headindex.js
index 5c3e5da..1490722 100644
--- a/assets/vendor/headindex/headindex.js
+++ b/assets/vendor/headindex/headindex.js
@@ -1,126 +1,320 @@
/*!
* headIndex.js - 文章目录生成插件
* 为 Argon 主题提供文章目录功能
+ *
+ * 注意:此文件仅用于后台设置页面预览
+ * 前端页面使用的是 argon_js_merged.js 中的压缩版本
*/
-(function($) {
- 'use strict';
-
- $.fn.headIndex = function(options) {
- var defaults = {
- articleWrapSelector: '#post_content',
- indexBoxSelector: '#leftbar_catalog',
- subItemBoxClass: 'index-subItem-box',
- scrollOffset: 80,
- activeClass: 'active'
- };
-
- var settings = $.extend({}, defaults, options);
- var $articleWrap = $(settings.articleWrapSelector);
- var $indexBox = $(settings.indexBoxSelector);
-
- if (!$articleWrap.length || !$indexBox.length) {
- return this;
+;(function($, window) {
+ var headIndex = (function() {
+ function headIndex(element, options) {
+ this.settings = $.extend(true, $.fn.headIndex.default, options || {});
+ this.element = element;
+ this.init();
}
-
- // 查找所有标题元素
- var $headings = $articleWrap.find('h1, h2, h3, h4, h5, h6');
- if ($headings.length === 0) {
- $indexBox.html('暂无目录
');
- return this;
- }
-
- // 生成目录HTML
- var indexHtml = '';
- var currentLevel = 0;
- var indexCounter = 0;
-
- $headings.each(function(index) {
- var $heading = $(this);
- var level = parseInt(this.tagName.substring(1));
- var text = $heading.text().trim();
- var id = 'heading-' + index;
-
- // 为标题添加ID
- if (!$heading.attr('id')) {
- $heading.attr('id', id);
- } else {
- id = $heading.attr('id');
- }
-
- // 处理层级
- if (level > currentLevel) {
- for (var i = currentLevel; i < level; i++) {
- if (i === currentLevel) {
- indexHtml += '';
- } else {
- indexHtml += '';
- }
- }
- } else if (level < currentLevel) {
- for (var j = currentLevel; j > level; j--) {
- indexHtml += '
';
- }
- }
-
- indexHtml += '- ' + text + '
';
- currentLevel = level;
- indexCounter++;
- });
-
- // 关闭所有未关闭的标签
- for (var k = 0; k < currentLevel; k++) {
- indexHtml += '
';
- }
- indexHtml += '
';
-
- $indexBox.html(indexHtml);
-
- // 绑定点击事件
- $indexBox.on('click', '.catalog-link', function(e) {
- e.preventDefault();
- var targetId = $(this).data('target');
- var $target = $('#' + targetId);
-
- if ($target.length) {
- $('html, body').animate({
- scrollTop: $target.offset().top - settings.scrollOffset
- }, 500, 'easeOutExpo');
+ headIndex.prototype = {
+ init: function() {
+ this.articleWrap = $(this.settings.articleWrapSelector);
+ this.headerList = this.articleWrap.find(':header');
+ this.indexBox = $(this.settings.indexBoxSelector);
+ this.indexScrollBox = $(this.settings.indexScrollBoxSelector);
+ this.scrollBody = $(this.settings.scrollSelector);
+ this.scrollWrap = $(this.settings.scrollWrap);
+ this.manual = false;
+ this.mouseHovered = false;
- // 更新活动状态
- $indexBox.find('.catalog-link').removeClass(settings.activeClass);
- $(this).addClass(settings.activeClass);
- }
- });
-
- // 滚动时高亮当前章节
- var throttleTimer = null;
- $(window).on('scroll', function() {
- if (throttleTimer) {
- clearTimeout(throttleTimer);
- }
-
- throttleTimer = setTimeout(function() {
- var scrollTop = $(window).scrollTop();
- var currentHeading = null;
+ if (this.indexBox.length === 0 || this.headerList.length === 0) {
+ return null;
+ }
- $headings.each(function() {
- var $heading = $(this);
- var headingTop = $heading.offset().top - settings.scrollOffset - 50;
-
- if (scrollTop >= headingTop) {
- currentHeading = $heading.attr('id');
+ this.initHeader();
+ this.event();
+ },
+
+ initHeader: function() {
+ for (var i = 0; i < this.headerList.length; i++, this.autoId++) {
+ this.headerList[i].id = this.headerList[i].id || "header-id-" + this.autoId;
+ this.headerList[i].topHeight = this.offsetTop(this.headerList[i]);
+ this.headerList[i].h = Number(this.headerList[i].tagName.charAt(1));
+ }
+
+ this.tempHtml = [];
+ this.buildHtml(this.buildTree());
+ var res = '' + this.tempHtml.join('') + '
';
+ this.indexBox.html(res);
+ },
+
+ event: function() {
+ var that = this;
+ var manualValTimer = null;
+
+ this.indexBox.on('click.headindex', function(event) {
+ var target = $(event.target);
+ if (target.hasClass(that.settings.linkClass)) {
+ event.preventDefault();
+ var indexItem = target.parent('.' + that.settings.itemClass);
+ that.manual = true;
+ if (manualValTimer) {
+ clearTimeout(manualValTimer);
+ manualValTimer = null;
+ }
+ manualValTimer = setTimeout(function() {
+ that.manual = false;
+ }, 400);
+ that.current(indexItem);
+ that.scrollTo(event.target.getAttribute('href'));
}
});
- if (currentHeading) {
- $indexBox.find('.catalog-link').removeClass(settings.activeClass);
- $indexBox.find('.catalog-link[data-target="' + currentHeading + '"]').addClass(settings.activeClass);
+ this.indexScrollBox.on('mouseover', function(event) {
+ that.mouseHovered = true;
+ });
+
+ this.indexScrollBox.on('mouseleave', function(event) {
+ that.mouseHovered = false;
+ });
+
+ $(this.scrollWrap).scroll(function() {
+ if (that.manual) return;
+ that.updateCurrent();
+ });
+
+ that.updateCurrent();
+ },
+
+ updateTopHeight: function() {
+ var length = this.headerList.length;
+ var i;
+ if (length === 0) return;
+
+ if (this.headerList[0].topHeight === this.offsetTop(this.headerList[0]) &&
+ this.headerList[length - 1].topHeight === this.offsetTop(this.headerList[length - 1])) {
+ return;
}
- }, 100);
+
+ if ((this.headerList[0].topHeight - this.offsetTop(this.headerList[0])) ===
+ (this.headerList[length - 1].topHeight - this.offsetTop(this.headerList[length - 1]))) {
+ var hx = this.offsetTop(this.headerList[0]) - this.headerList[0].topHeight;
+ for (i = 0; i < this.headerList.length; i++, this.autoId++) {
+ this.headerList[i].topHeight += hx;
+ }
+ return;
+ }
+
+ for (i = 0; i < this.headerList.length; i++, this.autoId++) {
+ this.headerList[i].topHeight = this.offsetTop(this.headerList[i]);
+ }
+ },
+
+ current: function(indexItem) {
+ var subBox, currentClass = 'current';
+ if (indexItem.length === 0 || indexItem.hasClass(currentClass)) {
+ return;
+ }
+
+ var otherCurrent = this.indexBox.find('li.' + currentClass);
+ if (otherCurrent.length > 0) {
+ otherCurrent.removeClass(currentClass);
+ }
+
+ this.indexBox.find('ul.open').removeClass('open');
+ subBox = indexItem.children('.' + this.settings.subItemBoxClass);
+ if (subBox.length > 0) {
+ subBox.addClass('open').slideDown();
+ }
+
+ var parentsBox = indexItem.parents('ul.' + this.settings.subItemBoxClass);
+ if (parentsBox.length > 0) {
+ parentsBox.addClass('open').slideDown();
+ }
+
+ subBox = this.indexBox.find('ul.' + this.settings.subItemBoxClass).not('.open');
+ if (subBox.length > 0) {
+ subBox.slideUp();
+ }
+
+ indexItem.addClass(currentClass);
+
+ if (this.mouseHovered) {
+ return;
+ }
+
+ var relativeOffsetTopToWrapper = indexItem.position().top;
+ var indexScrollBoxScrollTop = this.indexScrollBox.scrollTop();
+ var indexScrollBoxHeight = this.indexScrollBox.height();
+
+ if (relativeOffsetTopToWrapper < 20 + indexItem.height()) {
+ var target = indexScrollBoxScrollTop + relativeOffsetTopToWrapper - 20 - indexItem.height();
+ if (target < 30) {
+ target = 0;
+ }
+ this.indexScrollBox.stop().animate({scrollTop: target}, 'normal', 'easeOutExpo');
+ }
+
+ if (relativeOffsetTopToWrapper > indexScrollBoxHeight - 10) {
+ this.indexScrollBox.stop().animate({
+ scrollTop: indexScrollBoxScrollTop + relativeOffsetTopToWrapper - indexScrollBoxHeight + 10 + indexItem.height()
+ }, 'normal', 'easeOutExpo');
+ }
+ },
+
+ buildHtml: function(tree) {
+ if (tree === undefined || tree.length === 0) return;
+
+ for (var i = 0; i < tree.length; i++) {
+ this.tempHtml.push("" + tree[i].item.innerText + "");
+ if (tree[i].children.length !== 0) {
+ this.tempHtml.push("");
+ this.buildHtml(tree[i].children);
+ this.tempHtml.push("
");
+ }
+ this.tempHtml.push("");
+ }
+ },
+
+ buildTree: function() {
+ var current = null, tempCur, indexTree = [];
+
+ for (var i = 0; i < this.headerList.length; i++) {
+ if (current == null) {
+ current = {
+ item: this.headerList[i],
+ parent: null,
+ children: []
+ };
+ indexTree.push(current);
+ continue;
+ }
+
+ if (current.item.h < this.headerList[i].h) {
+ tempCur = {
+ item: this.headerList[i],
+ parent: current,
+ children: []
+ };
+ current.children.push(tempCur);
+ current = tempCur;
+ continue;
+ }
+
+ if (current.item.h === this.headerList[i].h) {
+ tempCur = {
+ item: this.headerList[i],
+ parent: current.parent,
+ children: []
+ };
+ ((current.parent && current.parent.children) || indexTree).push(tempCur);
+ current = tempCur;
+ continue;
+ }
+
+ while (current != null && current.item.h > this.headerList[i].h) {
+ current = current.parent;
+ }
+
+ if (current == null) {
+ current = {
+ item: this.headerList[i],
+ parent: null,
+ children: []
+ };
+ indexTree.push(current);
+ continue;
+ }
+ i--;
+ }
+
+ return indexTree;
+ },
+
+ search: function(start, end, findValue) {
+ if (this.headerList.length === 0) return null;
+
+ if (end - start <= 1) {
+ if (this.headerList[end].topHeight < findValue) {
+ return this.headerList[end];
+ }
+ return this.headerList[start];
+ }
+
+ if (start < end) {
+ var middleIndex = parseInt((start + end) / 2);
+ var middleValue = this.headerList[middleIndex].topHeight;
+
+ if (findValue < middleValue) {
+ end = middleIndex;
+ } else if (findValue > middleValue) {
+ start = middleIndex;
+ } else {
+ return this.headerList[middleIndex];
+ }
+ return this.search(start, end, findValue);
+ }
+ },
+
+ offsetTop: function(elem) {
+ return $(elem).offset().top - this.settings.offset;
+ },
+
+ scrollTo: function(eid) {
+ this.scrollBody.stop().animate({
+ scrollTop: this.offsetTop(document.getElementById(eid.substr(1))) + 8
+ }, 'normal', 'easeOutExpo');
+ },
+
+ updateCurrent: function() {
+ var scrollTop = this.scrollBody.scrollTop();
+ this.updateTopHeight();
+ var find = this.search(0, this.headerList.length - 1, scrollTop);
+ if (!find) {
+ return;
+ }
+ var indexItem = this.indexBox.find('a[href="#' + find.id + '"]').parent('li.' + this.settings.itemClass);
+ this.current(indexItem);
+ },
+
+ clean: function() {
+ if (this.element) {
+ this.element.data("headIndex", null);
+ }
+ },
+
+ ignoreScrollEvent: function(ignore) {
+ if (ignore) {
+ this.manual = true;
+ } else {
+ this.manual = false;
+ this.updateCurrent();
+ }
+ }
+ };
+
+ headIndex.prototype.autoId = 1;
+
+ return headIndex;
+ })();
+
+ $.fn.headIndex = function(options) {
+ return this.each(function() {
+ var $this = $(this),
+ instance = $this.data("headIndex");
+ instance = new headIndex($this, options);
+ $this.data("headIndex", instance);
+ if ($.type(options) === "string") return instance[options]();
});
-
- return this;
};
-
-})(jQuery);
\ No newline at end of file
+
+ $.fn.headIndex.default = {
+ articleWrapSelector: ".article-wrap",
+ indexBoxSelector: ".index-box",
+ indexScrollBoxSelector: "#leftbar_part2_inner",
+ scrollSelector: 'body,html',
+ scrollWrap: window,
+ subItemBoxClass: "index-subItem-box",
+ itemClass: "index-item",
+ linkClass: "index-link",
+ offset: 0
+ };
+
+})(jQuery, window);