[js] 希望尽量折叠大纲

本贴最后更新于 206 天前,其中的信息可能已经时移世改

之前在社区发布一个关于折叠大纲的代码求助(希望鼠标悬浮自动展开大纲 - 链滴),很高兴看到有热心的人进行帮助,但是最近复习的时候,发现有一点需要优化一下

大纲折叠可以方便我们快速获取文章的大致结构,方便我们去进行定位,但是当我们复习的时候,也就是鼠标点击大纲跳到对应的标题时,如果想回去大纲再进行点击,就需要再次寻找标题对应的大纲,然而此时大纲的加深效果(光标对应标题的大纲定位效果)已经消失,寻找对应的标题就需要重新一个字一个字的核对,这对复习效果造成极大的不便,望请大佬们帮我修改下代码片段

这是目前的效果

image.png

这是我理想的效果

image.png

示例代码

// see https://ld246.com/article/1727096963532 (async ()=>{ whenElementExist('.sy__outline > .fn__flex-1').then(async el => { // 监听大纲标题被添加 observeChildAddition(el, node => { return node.tagName.toLowerCase() === 'ul' && node.classList.contains('b3-list') && node.querySelector('.b3-list-item') }, uls => { // 获取大纲列表 const ul = uls[0]; // 遍历大纲第一级子元素 Array.from(ul.children).forEach(item => { // 初始时,仅打开第一级 if(item.tagName === 'LI') { const toggleBtn = item.querySelector('.b3-list-item__toggle'); const svg = toggleBtn?.querySelector('svg.b3-list-item__arrow'); if(!svg.classList.contains('b3-list-item__arrow--open')) { svg.classList.add('b3-list-item__arrow--open'); } } if(item.tagName === 'UL') { if(item.classList.contains('fn__none')) { item.remove('fn__none'); } // 初始时,隐藏第一级下面的后代元素 itemsShow(item, false); } // 监听大纲鼠标移入事件 const ul = item.tagName === 'LI' ? item.nextElementSibling : item; item.addEventListener('mouseenter', (event) => { if(!ul || ul?.tagName !== 'UL') return; // 鼠标移入显示第一级后面的后代元素 itemsShow(ul, true); }) // 监听大纲鼠标移出事件 item.addEventListener('mouseleave', (event) => { if(!ul || ul?.tagName !== 'UL') return; // 鼠标移出隐藏第一级后面的后代元素 itemsShow(ul, false); }); }); }); }); // 动态显示隐藏子标题 function itemsShow(ul, isOpen) { if(isOpen){ const svgs = ul.querySelectorAll('span.b3-list-item__toggle svg:not(.b3-list-item__arrow--open)'); svgs.forEach(item => { item.classList.add('b3-list-item__arrow--open'); }); const uls = ul.querySelectorAll('ul.fn__none'); uls.forEach(item => { item.classList.remove('fn__none'); }); } else { const svgs = ul.querySelectorAll('span.b3-list-item__toggle svg.b3-list-item__arrow--open'); svgs.forEach(item => { item.classList.remove('b3-list-item__arrow--open'); }); const uls = ul.querySelectorAll('ul:not(.fn__none)'); uls.forEach(item => { item.classList.add('fn__none'); }); } } function observeChildAddition(el, filter, handler) { // 配置观察器选项 const config = { attributes: false, childList: true, subtree: false }; // 定义回调函数 const callback = function(mutationsList, observer) { // 遍历 mutation 列表 for (let mutation of mutationsList) { if (mutation.type === 'childList') { console.log(mutation, 111); // 查找新增加的具有类名 'b3-list' 的 ul 元素 const newULs = Array.from(mutation.addedNodes).filter(node => node.nodeType === Node.ELEMENT_NODE && filter(node)); // 如果有新的 ul 元素被添加,则调用处理函数 if(newULs.length > 0) { handler(newULs); } } } }; // 创建一个新的 MutationObserver 实例 const observer = new MutationObserver(callback); // 开始观察目标节点 observer.observe(el, config); // 返回一个函数来停止观察 return () => { observer.disconnect(); }; } // 等待元素渲染完成后执行 function whenElementExist(selector, bySetTimeout = false, delay = 40) { return new Promise(resolve => { const checkForElement = () => { let element = null; if (typeof selector === 'function') { element = selector(); } else { element = document.querySelector(selector); } if (element) { resolve(element); } else { if (bySetTimeout) { setTimeout(checkForElement, delay); } else { requestAnimationFrame(checkForElement); } } }; checkForElement(); }); } })();
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25540 引用 • 105644 回帖 • 2 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    172 引用 • 1165 回帖
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9772 引用 • 44459 回帖 • 89 关注
1 操作
CongSec 在 2024-10-23 20:16:25 置顶了该帖

相关帖子

被采纳的回答

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • shiyuankill

    你好,大纲层级背景颜色是怎么搞出来的

    1 回复
  • CongSec

    没有人做这个吗?这个对喜欢用大纲的人来说很友善

  • wilsons 3 2 评论

    不知是否你想要的效果

    如图

    r81.gif

    代码

    代码备份地址:https://gitee.com/wish163/mysoft/blob/master/%E6%80%9D%E6%BA%90%E6%8A%98%E5%8F%A0%E5%A4%A7%E7%BA%B2%E6%94%B9%E8%BF%9B%E7%89%88.js

    1 回复
    这几天一直在关注这个话题,这个效果好,感谢大佬。 (与此同时,默默地擦了下没有技术的眼泪)
    ZiYunMaster
    @ZiYunMaster 更新了点击大纲项后,当鼠标移开大纲后,大纲被点击的项不消失
    wilsons 1
  • CongSec

    感谢大佬的代码片段,非常好用 ❤️ ❤️ ❤️

  • wilsons 1

    更新到 version 0.0.3

    0.0.3 改进文档打开时,自动根据上次光标的位置定位光标所在的标题

    1 回复
  • CongSec

    感谢你的更新,能否做出最后的优化?能否保留原版本(标题处)在大纲处快速跳转的功能

    因为如果我们想在大纲处进行多处的快速跳转时,这个突然折叠打乱原来的大纲状态,需要重新查找并展开

    理想的效果:

    实际的效果:

    ❤️ ❤️ ❤️

    1 回复
  • 没太懂,

    1. 鼠标移上去不是会全部展开某一级下的所有标题吗?为什么你这边需要鼠标点击展开?
    2. 你想要的效果是鼠标移上去需要自动定位到文档中的标题?还是鼠标移上去仅展开该某一级下的所有标题?
    1 回复
  • CongSec

    比如说有时候我们鼠标悬浮在大纲里来回切换两个标题查看两段文字,原来的版本可以通过来回点击 1 和 2 即可,现在的版本需要重新寻找进行定位然后展开,感觉这个功能比较细腻,光靠 js 难易实现,可能是我还没适应这个代码,不过还是非常感谢您能耐心看完我的建议 ❤️

    image.png

    1 回复
  • wilsons 1

    抱歉,还是没理解你的问题。之所以没理解,是因为我这边没有你说的这些问题。

    所以,我怀疑你的代码可能有冲突或受其他代码影响了,建议你在完全新空间测试试试,以排除干扰项。

    这个代码就是在原来的基础上修改的,仅仅增加了光标处的标题会在大纲处定位而已,对原有逻辑没有影响。

    如果确定新空间仍有问题,可以尝试注释 openCursorHeading() 函数调用试试。

    光标处的标题在大纲处定位的函数就是 openCursorHeading(),一共有 3 处调用,你可以分别尝试注释这些调用试试,看看哪种是你想要的效果,3 处都注释就是原来的代码。

    这三处调用的作用分别是:

    第一处,在文档被打开时,默认使用上次的光标定位,注释掉则打开时不会定位光标位置。

    第二处,在鼠标离开大纲时,使用当前文档的光标定位,注释掉则鼠标离开大纲后定位消失。

    第三处,当光标移动时,使用当前光标定位,注释掉则光标移动不会定位标题在大纲中的位置(如果注释掉这个的话,就失去本改进版的意义了)。

    总之,你觉得效果不满意可以尝试注释这些调用看看是否你想要的效果,前提是确保代码没受到其他因素的影响。再次强调,本次修改仅仅增加了光标处的标题在大纲处定位而已,原有逻辑和功能并未有改变。

    1 回复
  • ZiYunMaster 1 评论
    抱歉,水平有限,这个太复杂了,建议在 github 搜索下有没有类似插件
    wilsons
请输入回帖内容 ...
CongSec
新手可以看我发的求助帖以及汇总帖子,很有帮助的!_! 网安笔记分享:http://congsec.xyz 广州

推荐标签 标签

  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 2 关注
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 28 回帖 • 2 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 733 关注
  • CodeMirror
    2 引用 • 17 回帖 • 163 关注
  • 博客

    记录并分享人生的经历。

    273 引用 • 2388 回帖
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖 • 2 关注
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 397 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 501 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 789 关注
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 77 回帖
  • 印象笔记
    3 引用 • 16 回帖 • 1 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 649 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • Gzip

    gzip (GNU zip)是 GNU 自由软件的文件压缩程序。我们在 Linux 中经常会用到后缀为 .gz 的文件,它们就是 Gzip 格式的。现今已经成为互联网上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

    9 引用 • 12 回帖 • 167 关注
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    79 引用 • 431 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 432 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 364 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 290 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖 • 1 关注
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    5 引用 • 16 回帖 • 2 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 6 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    196 引用 • 291 回帖 • 373 关注
  • Anytype
    3 引用 • 31 回帖 • 16 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖 • 2 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 3 关注