[js] 批量折叠和展开标题,标题批量转换不再是梦

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

缘起:

看到有些小伙伴们希望有标题批量折叠或展开功能(比如 思源能否添加折叠或展开指定层级标题下内容的功能?怎样快速调整大纲级别? ),这个功能有时候确实挺有用的,比如批量转换等。

今天试着研究了下,于是整了一个 js 代码片段。

该代码主要有以下几个功能:

  1. alt + 点击标题前的箭头按钮,折叠/展开所有同级标题
  2. ctrl/meta + alt + 点击标题前的箭头按钮,折叠/展开所有标题
  3. 选择情况下,仅折叠/展开已选择的部分的标题

效果如下:

r98.gif

代码

https://gitee.com/wish163/mysoft/blob/main/%E6%80%9D%E6%BA%90/%E5%BF%AB%E9%80%9F%E6%8A%98%E5%8F%A0%E5%92%8C%E5%B1%95%E5%BC%80%E6%A0%87%E9%A2%98.js

思源的坑:

这里顺便吐槽下思源获取当前文档的坑,,看到很多小伙伴们使用下面的方法获取的

document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')

这样获取乍一看没问题,也能满足绝大多数场景,包括分屏。

但这种方法不适合思源刚刚启动或刚刚刷新后的情况,因为刚刚重启或刷新后的页面中并不存在 layout__wnd--active 这个类,导致这种方法失效。

那如果换成这样呢?

document.querySelector('[data-type="wnd"].layout__wnd--active .protyle:not(.fn__none)')||document.querySelector('[data-type="wnd"] .protyle:not(.fn__none)');

这种方式,当刚刚刷新或重启情况下,默认取第一个分屏的文档。

但,这在分屏情况下,不一定准确,用户正在操作的可能不是第一个分屏。

实时上,在分屏情况下是无解的,因为用户尚未操作,无法知道哪个文档是当前文档,换句话说不存在当前文档。这在逻辑上是没错的,从这个角度看也不算思源的坑。

所以,分屏情况下有没有准确获取用户操作的当前文档的办法呢?

我觉得这要具体问题具体分析了。

  1. 如果你确定你的操作被执行时,文档一定是被激活了的,可以用上面的方法实现。
  2. 如果有鼠标事件的操作,可以用 document.elementFromPoint(mouseX, mouseY) 方法实现,具体可以参考本代码中的获取方法。
  3. 如果 1 和 2 都无法确保,可以用 mouseover 或 mousemove 事件写入一个全局变量来实现。

当然,或许还有更好的方法吧,请各位大佬们不吝赐教!!!

  • 思源笔记

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

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

    28446 引用 • 119770 回帖
  • 代码片段

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

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

    285 引用 • 1985 回帖
1 操作
wilsons 在 2024-12-05 17:50:35 更新了该帖

相关帖子

欢迎来到这里!

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

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

    学习了,还没研究过插件开发,页面刚刷新完也有吗?如果分屏情况,且用户未在任何窗口操作时,它怎么知道哪个文档是当前文档的呢?

    1 回复
  • 其他回帖
  • 如果用户本身就没有点击/鼠标移入过文档,那么本身就不应该算作一次选择了文档。

    不过写代码本身就是根据场景不同选择适用的代码,想一个代码解决所有场景,这属于比较理想的情况了。

    我就举一个很简单的场景,假如我左右分屏两个文档,然后刷新了思源,这个时候应该算左边的是当前文档,还是算右边的呢?

    而针对这类场景,queryAll(':not(.fn__none)'),找到所有的文档,如果有多个,则提示用户选择。

    1 回复
  • 上面的是针对思源渲染的文档,如果是自定义渲染的 block,sql 版本:

    const sqlStmt = `sql root_id from blocks where id = '${clickedDomNodeId}'`
    const res = await reqeust(`http://localhost:6806/api/query/sql`, {
      stmt: sqlStmt,
    })
    const docId = res[0]?.root_id
    
    没测试,自己拿去改吧。
    Wetoria
  • wilsons 1

    关于获取当前文档,补充一点:

    1. 如果能拿到任何块 ID 或任何 dom 元素的情况,可以尝试用 document.querySelector('[data-node-id="your block id"]').closest('.protyle')或 element.closest('.protyle')获取。

    感谢 @Achuan-2 的指导和提醒!

    1 回复
  • 查看全部回帖
wilsons
正式入驻知乎了,以后新贴主要在这里。 欢迎大家订阅关注! 你的关注对我是莫大鼓励,也能让我持续产出优质内容,我们一起成长 🙏 点这里立即关注:https://www.zhihu.com/people/wilsonses