求 js 代码,只展开当前活动页签的文档树

本贴最后更新于 317 天前,其中的信息可能已经时移俗易

求 js 代码,在使用“始终定位打开的文档”功能时,只展开当前文档的文档树,自动关闭(不展开)其它无关的文档树。例如:

有笔记本 A,内有文档 A1,子文档 A2、子子文档 A3。

有笔记本 B,内有文档 B1,子文档 B2、子子文档 B3。

已将文档 A2、B2 打开,显示在上方页签栏中。

启用“始终定位打开的文档”功能。

点击 A2 页签,左侧文档树自动展开,并定位到 A-A1-A2;A3 列表不展开

点击 B2 页签,左侧文档树自动展开,定位到 B-B1-B2;同时关闭 A-A1-A2 文档树的展开状态,恢复到笔记本 A。也就是仅保留当前活动页签对应的文档树是展开状态,其它文档树分支全部关闭,包括当前活动文档的子文档树。

  • 思源笔记

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

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

    25092 引用 • 103450 回帖
  • Q&A

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

    9567 引用 • 43553 回帖 • 98 关注
1 操作
wenbocn 在 2024-06-02 13:54:35 更新了该帖

相关帖子

被采纳的回答
  • wilsons 1

    时隔 1 个多月,你解决了吗?相见即是有缘,看到此贴感觉有些思路,就尝试写了下,实现了这个功能。由于刚接触思源,对思源 api 还不是很了解,所以选择用 js 代码片段实现,纯原生 js 实现,方法比较笨,勉强能用。

    不足之处也请论坛里的大佬们多多批评指正!

    效果如下:

    t2.gif

    完整代码如下:

    // 等待标签页容器渲染完成后开始监听 whenElementExist('.layout__center').then(async element => { // 等待笔记列表加载完毕 await sleep(40); // 监听页签切换事件 observeTabChanged(element, (tab) => { // 折叠所有笔记,然后定位当前笔记 collapseAllBooksThenFocusCurrentBook(element, tab); }); }); // 折叠所有笔记,然后定位当前笔记 async function collapseAllBooksThenFocusCurrentBook(element, tab) { // 等待激活文档加载完毕 await whenElementExist(()=>{ const content = element.querySelector('.layout-tab-container [data-id="'+tab.getAttribute("data-id")+'"]'); return content && content.getAttribute("data-loading") === "finished"; }); // 折叠所有笔记 document.querySelectorAll("ul.b3-list[data-url]").forEach(async book => { const bookName = tab.getAttribute("aria-label")?.split('/')[0]; if(bookName) { // 如果在本笔记中则不再折叠 const bookText = book.querySelector('li[data-type="navigation-root"] span.b3-list-item__text')?.innerText; if(bookText === bookName) { return; } } // 折叠笔记 const bookArrowBtn = book.querySelector('li[data-type="navigation-root"] span.b3-list-item__toggle'); if (bookArrowBtn && bookArrowBtn.firstElementChild.classList.contains("b3-list-item__arrow--open")) { bookArrowBtn.click(); } }); // 定位当前笔记 document.querySelector(".layout-tab-container .block__icons span[data-type=focus]")?.click(); } // 监听页签切换事件 function observeTabChanged(parentNode, callback) { // 创建一个回调函数来处理观察到的变化 const observerCallback = function(mutationsList, observer) { // 用常规方式遍历 mutationsList 中的每一个 mutation for (let mutation of mutationsList) { // 属性被修改 if (mutation.type === 'attributes' && mutation.attributeName === 'class') { const element = mutation.target; if (element.tagName.toLowerCase() === 'li' && element.getAttribute('data-type') === 'tab-header' && element.classList.contains('item--focus')) { if(typeof callback === 'function') callback(element); } } // 如果有新的子节点被添加 if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === 'li') { if (node.getAttribute('data-type') === 'tab-header' && node.classList.contains('item--focus')) { if(typeof callback === 'function') callback(node); } } }); } } }; // 创建一个观察器实例并传入回调函数 const observer = new MutationObserver(observerCallback); // 配置观察器:传递一个对象来指定观察器的行为 const config = { attributes: true, attributeFilter: ['class'], childList: true, subtree: true }; // 开始观察目标节点 observer.observe(parentNode, config); // 返回一个函数,用于停止观察 return function stopObserving() { observer.disconnect(); }; } // 延迟执行 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 等待元素渲染完成后执行 function whenElementExist(selector) { 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 { requestAnimationFrame(checkForElement); } }; checkForElement(); }); }

    使用方法:

    设置 》外观 》代码片段 》js 中新增加代码片段,然后把上面的代码粘贴过去即可。

    image.png

优质回帖
  • wilsons 2

    @wenbocn 我已完美实现了不闪动的版本,并且改进了官方定位,在未打开目录树时,左侧 dock 区目录树显示隐藏按钮样式会获取焦点的 bug

    效果如下

    t6.gif

    完整代码如下

    由于链滴代码长度有限制,只能放到 jsrun 了。

  • wilsons 2

    确实是焦点问题,楼主主要想要的是定位文档树,且定位和展开关闭目录使用了模拟点击,这些操作都会使当前文档的焦点移动到目录树上,导致大纲还没来得及切换就失去焦点文档了。

    其实,定位文档树也是要获得焦点的,这和文档焦点矛盾,具体怎么做看自己需求,是希望最后焦点落在哪里?

    如果想最终焦点落在文档树上,可以在 focusCurrentDocInTrees 函数的开头加上 sleep(120),等待大纲切换完毕再定位

    image.png

    image.png

    如果想最终焦点落在文档上,则在 focusCurrentDocInTrees 函数的末尾加上以下代码,定位文档树后恢复文档焦点

    // 文档树模拟点击后恢复文档窗口(编辑器)的焦点(最终焦点在文档) whenElementExist('.layout__tab--active .b3-list--background .b3-list-item--focus').then(() => { const activepPotyle = document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)'); if(activepPotyle) activepPotyle.click(); });

    image.png

    image.png

    这是我修改后的代码,只需要配置这个参数即可

    // 最终焦点落在文档树还是文档上? tree 文档树,doc 文档
    const lastFoucsIn = 'doc';

    https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/%E5%8F%AA%E5%B1%95%E5%BC%80%E5%BD%93%E5%89%8D%E6%B4%BB%E5%8A%A8%E9%A1%B5%E7%AD%BE%E7%9A%84%E6%96%87%E6%A1%A3%E6%A0%91.js

  • player 1 赞同

    ToolbarBox

    这里有除了自动定位的其他代码。 自动定位就做个监听, 针对 class layout__wnd--active ,发现有 tab 的变化,就触发一次,locateDoc() 即可。

欢迎来到这里!

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

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

    @wenbocn 我已完美实现了不闪动的版本,并且改进了官方定位,在未打开目录树时,左侧 dock 区目录树显示隐藏按钮样式会获取焦点的 bug

    效果如下

    t6.gif

    完整代码如下

    由于链滴代码长度有限制,只能放到 jsrun 了。

    5 回复
  • 其他回帖
  • 发了 https://sypai.cc/archives/977/

    @wenbocn 从代码中提取的这段代码,本意是想通过标签的 aria-label 属性实现,如果展开的笔记是当前点击的文档所在笔记不再折叠再展开了,这样防止出现跳动。但现在想来如果同一个笔记下,展开多个目录可能会导致同个笔记下的文档切换时不再折叠,不知道是否符合你的需求,如果不符合,建议把这段代码删除。而且这段代码在打开文档时还会出现跳动,实现并不完美。

    const bookName = tab.getAttribute("aria-label")?.split('/')[0]; if(bookName) { // 如果在本笔记中则不再折叠 const bookText = book.querySelector('li[data-type="navigation-root"] span.b3-list-item__text')?.innerText; if(bookText === bookName) { return; } }

    比如,如下场景不会折叠同个笔记下的目录

    t4.gif

    2 回复
  • 把这个

    // 定位当前笔记 document.querySelector(".layout-tab-container .block__icons span[data-type=focus]")?.click();

    改为下面这个就好了

    // 定位当前笔记 if(document.querySelector('#dockLeft span[data-type="file"].dock__item--active')) { document.querySelector(".layout-tab-container .block__icons span[data-type=focus]")?.click(); }

    不过,我测试下来,还是会闪动的。

  • 现在就是点击文档页签,折叠所有文档树,然后定位打开的文档,使用设置的保持定位和 js 去定位效果是一样的。这里最多不折叠当前文档下的笔记目录,但仅仅这样仍然会跳动的,因为折叠过程必然会显得跳动。至于当前笔记下的其他目录是否折叠这看你需求。貌似你的需求只显示当前文档所在目录,其他统统折叠,无论是否相同笔记下。晚点我看看能否改进,但不一定能,别抱希望,免得到时候希望越大失望越大。

    论坛有大佬有好办法的也请多多指点!

    1 回复
  • 查看全部回帖

推荐标签 标签

  • 工具

    子曰:“工欲善其事,必先利其器。”

    298 引用 • 762 回帖 • 1 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 2 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 30 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 207 关注
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1708 回帖
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    245 引用 • 1338 回帖
  • 大疆创新

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

    2 引用 • 14 回帖
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 2 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    210 引用 • 2040 回帖
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖 • 1 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 344 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖
  • 招聘

    哪里都缺人,哪里都不缺人。

    189 引用 • 1057 回帖 • 2 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 666 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    289 引用 • 4492 回帖 • 653 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖 • 1 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    89 引用 • 122 回帖 • 619 关注
  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 384 回帖 • 10 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 19 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 457 关注
  • CodeMirror
    2 引用 • 17 回帖 • 158 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 54 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 27 关注