[js] 希望尽量折叠大纲

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

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

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

这是目前的效果

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(); }); } })();
  • 思源笔记

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

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

    25860 引用 • 107103 回帖 • 1 关注
  • 代码片段

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

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

    177 引用 • 1251 回帖
  • Q&A

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

    9927 引用 • 45082 回帖 • 79 关注
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 广州

推荐标签 标签

  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 636 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 48 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 1 关注
  • Visio
    1 引用 • 2 回帖
  • abitmean

    有点意思就行了

    33 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 674 关注
  • RemNote
    2 引用 • 16 回帖 • 19 关注
  • Excel
    31 引用 • 28 回帖
  • 导航

    各种网址链接、内容导航。

    45 引用 • 177 回帖 • 2 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 659 关注
  • PostgreSQL

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

    22 引用 • 22 回帖 • 1 关注
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    98 引用 • 903 回帖
  • Notion

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

    10 引用 • 77 回帖
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • WebSocket

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

    48 引用 • 206 回帖 • 284 关注
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 663 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    411 引用 • 3588 回帖
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    108 引用 • 153 回帖
  • jQuery

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

    63 引用 • 134 回帖 • 734 关注
  • 电影

    这是一个不能说的秘密。

    122 引用 • 608 回帖 • 2 关注
  • Gitea

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

    5 引用 • 16 回帖 • 3 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 33 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    80 引用 • 396 回帖
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 2 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 3 关注
  • gRpc
    11 引用 • 9 回帖 • 99 关注