[js] 右键文档树定位按钮时先折叠再定位

效果是右键文档树上的定位按钮时,先折叠其他打开的笔记本,再定位到当前文档

image.png

JS 代码片段:

设置开头的变量为 true 时是“左键定位, 右键折叠定位”,为 false 时互换为“左键折叠定位, 右键定位”

// 右键文档树定位按钮时先折叠再定位 JS片段
// author by JeffreyChen https://ld246.com/article/1727980528164
(function() {
  // 设置为 true 时是“左键定位, 右键折叠定位”,为 false 时互换为“左键折叠定位, 右键定位”
  const originalBehavior = true;

  function addFocusHandler() {
    const MAX_RETRIES = 100; // 最大重试次数
    const RETRY_INTERVAL = 200; // 重试间隔(毫秒)
    let retryCount = 0;

    const FOCUS_BUTTON_SELECTOR = '.layout-tab-container > .file-tree .block__icon[data-type="focus"]';
    const FILE_TREE_SELECTOR = ".layout-tab-container > .file-tree > .fn__flex-1 > ul.b3-list[data-url]";

    function collapseLists() {
      const fileTreeLists = document.querySelectorAll(FILE_TREE_SELECTOR);

      fileTreeLists.forEach(list => {
        const fragment = new DocumentFragment();
        Array.from(list.children).forEach(item => {
          if (item.matches('li.b3-list-item')) {
            const toggleElement = item.querySelector('.b3-list-item__toggle');
            const arrowElement = item.querySelector('.b3-list-item__arrow');

            if (toggleElement && arrowElement.classList.contains('b3-list-item__arrow--open')) {
              arrowElement.classList.remove('b3-list-item__arrow--open');

              const nextSibling = item.nextElementSibling;
              if (nextSibling && nextSibling.matches('ul')) {
                fragment.appendChild(nextSibling);
              }
            }
          }
        });

        // 批量清空节点
        requestAnimationFrame(() => fragment.replaceChildren());
      });
    }

    function tryModifyAriaLabelAndAddHandler() {
      const focusButton = document.querySelector(FOCUS_BUTTON_SELECTOR);

      if (focusButton) {
        if (originalBehavior) {
          // 原始逻辑
          focusButton.setAttribute('aria-label', '左键定位, 右键折叠定位');
          focusButton.addEventListener('contextmenu', function(e) {
            e.preventDefault(); // 阻止默认右键行为
            collapseLists();
            focusButton.click(); // 模拟点击当前按钮
          });
        } else {
          // 左右互换逻辑
          focusButton.setAttribute('aria-label', '左键折叠定位, 右键定位');
          
          function leftClickHandler(e) {
            e.preventDefault(); // 阻止左键点击的默认行为
            collapseLists();
            focusButton.click(); // 模拟点击当前按钮
          }

          function contextMenuHandler(e) {
            e.preventDefault(); // 阻止右键点击的默认行为
            focusButton.removeEventListener('click', leftClickHandler);
            focusButton.click(); // 模拟点击当前按钮
            setTimeout(() => {
              focusButton.addEventListener('click', leftClickHandler);
            }, 0);
          }

          // 为左键和右键添加相应的监听器
          focusButton.addEventListener('click', leftClickHandler);
          focusButton.addEventListener('contextmenu', contextMenuHandler);
        }
      } else {
        retryCount++;
        if (retryCount < MAX_RETRIES) {
          setTimeout(tryModifyAriaLabelAndAddHandler, RETRY_INTERVAL); // 继续重试
        } else {
          console.error('代码片段报错:无法找到文档树上的定位按钮');
        }
      }
    }

    // 初次调用
    tryModifyAriaLabelAndAddHandler();
  }

  // 添加处理程序
  addFocusHandler();
})();

目前已知的问题是:

  1. 如果当前文档所在的笔记本是展开的,使用时会有一点不必要的抖动。开发需求已经反馈到:Issue #12695 · siyuan-note/siyuan
  2. 有时候不能定位到预期中的文档,这个是思源的问题,已经反馈到:Issue #12694 · siyuan-note/siyuan
打赏 30 积分后可见
30 积分 • 7 打赏
  • 思源笔记

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

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

    22251 引用 • 88937 回帖
  • 代码片段

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

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

    63 引用 • 348 回帖 • 1 关注
2 操作
JeffreyChen 在 2024-10-06 14:33:50 更新了该帖
JeffreyChen 在 2024-10-04 02:38:04 更新了该帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 求助!

    大佬能否给一个定位文档后,点击展开该定位文档的功能。

    目的:

    使用了“二级文档树”插件,参考[css] 关于二级文档树的某些定制设计 - 链滴 (ld246.com),添加 css 自定义实现了左侧原文档树显示文件夹,右侧二级文档树显示文件的功能。使用原文档树的定位按钮时,只能在左侧原文档树定位,而不能使二级文档树定位。

    思路:使用原文档树的定位按钮时,在左侧原文档树定位到文档,然后点击将其展开,那么左侧(原文档树)显示该文档下的所有文件夹,同时右侧(二级文档树)显示该文档下的所有文件。

    1 回复
  • 其他回帖
  • JeffreyChen 1 1 赞同
    1. 帖子更新了代码片段,在代码开头增加了一个变量切换
    2. 始终显示文档树上的按钮可以用下面这个 CSS:
      #layouts .layout-tab-container > .file-tree .block__icon {
          opacity: 1;
      }
      
  • 改好了,不过左键点击的时候不行,我没研究出来为什么:

    // 右键文档树定位按钮时先折叠再定位 JS片段
    // author by JeffreyChen https://ld246.com/article/1727980528164
    (function() {
      // 设置为 true 时是“左键定位, 右键折叠定位”,为 false 时互换为“左键折叠定位, 右键定位”
      const originalBehavior = true;
    
      function addFocusHandler() {
        const MAX_RETRIES = 100; // 最大重试次数
        const RETRY_INTERVAL = 200; // 重试间隔(毫秒)
        let retryCount = 0;
    
        const FOCUS_BUTTON_SELECTOR = '.layout-tab-container > .file-tree .block__icon[data-type="focus"]';
        const FILE_TREE_SELECTOR = ".layout-tab-container > .file-tree > .fn__flex-1 > ul.b3-list[data-url]";
    
        function collapseLists() {
          const fileTreeLists = document.querySelectorAll(FILE_TREE_SELECTOR);
    
          fileTreeLists.forEach(list => {
            const fragment = new DocumentFragment();
            Array.from(list.children).forEach(item => {
              if (item.matches('li.b3-list-item')) {
                const toggleElement = item.querySelector('.b3-list-item__toggle');
                const arrowElement = item.querySelector('.b3-list-item__arrow');
    
                if (toggleElement && arrowElement.classList.contains('b3-list-item__arrow--open')) {
                  arrowElement.classList.remove('b3-list-item__arrow--open');
    
                  const nextSibling = item.nextElementSibling;
                  if (nextSibling && nextSibling.matches('ul')) {
                    fragment.appendChild(nextSibling);
                  }
                }
              }
            });
    
            // 批量清空节点
            requestAnimationFrame(() => fragment.replaceChildren());
          });
        }
    
        function simulateClickOnFocusedText() {
          const focusedTextElement = document.querySelector('.layout-tab-container > .file-tree > .fn__flex-1 .b3-list-item--focus > .b3-list-item__text');
          if (focusedTextElement) {
            focusedTextElement.click(); // 模拟点击找到的第一个元素
          } else {
            console.error('找不到聚焦文本元素');
          }
        }
    
        function tryModifyAriaLabelAndAddHandler() {
          const focusButton = document.querySelector(FOCUS_BUTTON_SELECTOR);
    
          if (focusButton) {
            // 在点击按钮后 500ms 模拟点击目标元素
            const handleButtonClick = () => {
              setTimeout(simulateClickOnFocusedText, 500); // 延时调用
            };
      
            if (originalBehavior) {
              // 原始逻辑
              focusButton.setAttribute('aria-label', '左键定位, 右键折叠定位');
              focusButton.addEventListener('contextmenu', function(e) {
                e.preventDefault(); // 阻止默认右键行为
                collapseLists();
                focusButton.click(); // 模拟点击当前按钮
                handleButtonClick(); // 添加延时点击操作
              });
            } else {
              // 左右互换逻辑
              focusButton.setAttribute('aria-label', '左键折叠定位, 右键定位');
        
              function leftClickHandler(e) {
                e.preventDefault(); // 阻止左键点击的默认行为
                collapseLists();
                focusButton.click(); // 模拟点击当前按钮
                handleButtonClick(); // 添加延时点击操作
              }
    
              function contextMenuHandler(e) {
                e.preventDefault(); // 阻止右键点击的默认行为
                focusButton.removeEventListener('click', leftClickHandler);
                focusButton.click(); // 模拟点击当前按钮
                setTimeout(() => {
                  focusButton.addEventListener('click', leftClickHandler);
                }, 0);
                handleButtonClick(); // 添加延时点击操作
              }
    
              // 为左键和右键添加相应的监听器
              focusButton.addEventListener('click', leftClickHandler);
              focusButton.addEventListener('contextmenu', contextMenuHandler);
            }
          } else {
            retryCount++;
            if (retryCount < MAX_RETRIES) {
              setTimeout(tryModifyAriaLabelAndAddHandler, RETRY_INTERVAL); // 继续重试
            } else {
              console.error('代码片段报错:无法找到文档树上的定位按钮');
            }
          }
        }
    
        // 初次调用
        tryModifyAriaLabelAndAddHandler();
      }
    
      // 添加处理程序
      addFocusHandler();
    })();
    
    1 回复
  • xnyshu 2 评论

    是的。

    @JeffreyChen 抱歉,这个真的不会写
    zxkmm
  • 查看全部回帖
JeffreyChen
思源是支持 Markdown 语法输入的块编辑器,而不是 Markdown 文件编辑器; 思源笔记同步教程:ld246.com/article/1692089679062

推荐标签 标签

  • VirtualBox

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

    10 引用 • 2 回帖 • 6 关注
  • Google

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

    49 引用 • 192 回帖 • 2 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 596 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 377 关注
  • 大疆创新

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

    2 引用 • 14 回帖 • 1 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    20 引用 • 7 回帖 • 2 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 71 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 707 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    28 引用 • 108 回帖
  • 代码片段

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

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

    63 引用 • 348 回帖 • 1 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 2 关注
  • 工具

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

    286 引用 • 729 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 430 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • TGIF

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

    287 引用 • 4484 回帖 • 667 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 780 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 1 关注
  • 强迫症

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

    15 引用 • 161 回帖
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    176 引用 • 815 回帖
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖
  • API

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

    77 引用 • 430 回帖 • 2 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 2 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 327 关注
  • CodeMirror
    1 引用 • 2 回帖 • 129 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖 • 1 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    110 引用 • 54 回帖 • 1 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 3 关注