[js] 快捷键实现在文档树上遍历

本贴最后更新于 209 天前,其中的信息可能已经天翻地覆

操作&效果

  1. 使用 alt+shift+上/下键 遍历文档树
    上: 打开 当前文档的上一个文档(当前文档树的上一个)
    下: 打开 当前文档的下一个文档(当前文档树的下一个)
  2. 使用 alt+shift+左/右键 展开折叠文档树
    左: 如果当前文档展开, 就折叠; 如果是折叠, 就跳转到父文档
    右: 如果当前文档折叠, 就展开; 如果是展开, 就跳转到第一个子文档

备注

  1. 生效前提: 左侧文档有被选中, 像这样 image.png
  2. 需要将这项配置打开: 始终定位打开的文档
  3. 与插件 文档层级导航 自带的快捷键冲突, 请自行解决

js 代码

(() => {
function set_file_open(now_ele, next_ele) {
    if (!next_ele) return
    if (next_ele.getAttribute('data-type') == 'navigation-root') {
        // 笔记本
        now_ele.classList.remove("b3-list-item--focus");
        next_ele.classList.add("b3-list-item--focus");
    }
    else {
        // 普通文档
        next_ele.click()
    }
    // console.log(next_ele)
}
function handle_file_navigation(now_ele, type) {
    if (!now_ele) return
    if (type == 'ArrowUp' || type == 'ArrowDown') {  // 上
        let ele_list = Array.from(document.querySelectorAll('div.sy__file li'))
        let idx = ele_list.indexOf(now_ele)
        if (idx == -1) return
        if (type == 'ArrowUp' && idx != 0) idx--
        else if (type == 'ArrowDown' && idx != ele_list.length - 1) idx++
        else return
        let next_ele = ele_list[idx]
        set_file_open(now_ele, next_ele)
    }
    else if (type == 'ArrowLeft') {
        let next_ele = now_ele.querySelector('.b3-list-item__arrow--open')
        if (next_ele) {
            // 有下层展开按钮: 折叠
            next_ele.parentElement.click()
        }
        else {
            // 其他情况, 跳转到上层
            next_ele = now_ele.parentElement.previousElementSibling
            if (next_ele?.tagName.toLowerCase() == 'li') {
                set_file_open(now_ele, next_ele)
            }
        }
    }
    else if (type == 'ArrowRight') {
        let next_ele = now_ele.querySelector('span.b3-list-item__toggle:not(.fn__hidden)')
        if (next_ele) {
            // 有下层展开按钮: 展开
            if (next_ele.querySelector('.b3-list-item__arrow--open')) {
                now_ele.nextElementSibling.firstChild.click()
            }
            else {
                next_ele.click()
            }
        }
    }
}

setTimeout(() => document.querySelector('[data-type="focus"]')?.click(), 1000);
// 事件监听
document.addEventListener('keydown', async (event) => {
    // 上/下, 遍历列表
    // 左: 没有下层: 跳转到上层
    //     有下层&下层展开: 折叠
    //     有下层&下层折叠: 跳转到上层
    // 右: 没有下层: 不处理
    //     有下层&下层展开: 跳转到第一个子节点
    //     有下层&下层折叠: 展开

    if (event.altKey && event.shiftKey &&
        (event.key == 'ArrowUp' || event.key == 'ArrowDown' ||
            event.key == 'ArrowLeft' || event.key == 'ArrowRight')) {
        let now_ele = document.querySelector('div.sy__file li.b3-list-item--focus')
        // console.log(now_ele)
        // console.log(event.key)
        handle_file_navigation(now_ele, event.key);
    }
});

})()

  • 思源笔记

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

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

    26030 引用 • 108019 回帖 • 1 关注
  • 代码片段

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

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

    188 引用 • 1322 回帖

相关帖子

欢迎来到这里!

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

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

    由于 siyuan 屏蔽了 alt+shift+左右键 的快捷键, 现在改为 alt+ctrl+上下左右键

    (() => {
    function set_file_open(now_ele, next_ele) {
        if (!next_ele) return
        if (next_ele.getAttribute('data-type') == 'navigation-root') {
            // 笔记本
            now_ele.classList.remove("b3-list-item--focus");
            next_ele.classList.add("b3-list-item--focus");
        }
        else {
            // 普通文档
            next_ele.click()
        }
        // console.log(next_ele)
    }
    function handle_file_navigation(now_ele, type) {
        if (!now_ele) return
        if (type == 'ArrowUp' || type == 'ArrowDown') {  // 上
            let ele_list = Array.from(document.querySelectorAll('div.sy__file li'))
            let idx = ele_list.indexOf(now_ele)
            if (idx == -1) return
            if (type == 'ArrowUp' && idx != 0) idx--
            else if (type == 'ArrowDown' && idx != ele_list.length - 1) idx++
            else return
            let next_ele = ele_list[idx]
            set_file_open(now_ele, next_ele)
        }
        else if (type == 'ArrowLeft') {
            let next_ele = now_ele.querySelector('.b3-list-item__arrow--open')
            if (next_ele) {
                // 有下层展开按钮: 折叠
                next_ele.parentElement.click()
            }
            else {
                // 其他情况, 跳转到上层
                next_ele = now_ele.parentElement.previousElementSibling
                if (next_ele?.tagName.toLowerCase() == 'li') {
                    set_file_open(now_ele, next_ele)
                }
            }
        }
        else if (type == 'ArrowRight') {
            let next_ele = now_ele.querySelector('span.b3-list-item__toggle:not(.fn__hidden)')
            if (next_ele) {
                // 有下层展开按钮: 展开
                if (next_ele.querySelector('.b3-list-item__arrow--open')) {
                    now_ele.nextElementSibling.firstChild.click()
                }
                else {
                    next_ele.click()
                }
            }
        }
    }
    
    setTimeout(() => document.querySelector('[data-type="focus"]')?.click(), 1000);
    // 事件监听
    document.addEventListener('keydown', async (event) => {
        // 上/下, 遍历列表
        // 左: 没有下层: 跳转到上层
        //     有下层&下层展开: 折叠
        //     有下层&下层折叠: 跳转到上层
        // 右: 没有下层: 不处理
        //     有下层&下层展开: 跳转到第一个子节点
        //     有下层&下层折叠: 展开
    
    
        if (event.altKey && event.ctrlKey &&
            (event.key == 'ArrowUp' || event.key == 'ArrowDown' ||
                event.key == 'ArrowLeft' || event.key == 'ArrowRight')) {
            let now_ele = document.querySelector('div.sy__file li.b3-list-item--focus')
            // console.log(now_ele)
            // console.log(event.key)
            handle_file_navigation(now_ele, event.key);
        }
    });
    
    })()
    
    
    1 回复
  • 这个问题不是只会出现在编辑器里吗?会影响到文档树?

    他把快捷键屏蔽了呀, addEventListener 监听不到这个快捷键, 不会触发回调
    HugZephyr
    @EmberSky 我这里实测只有在段落开头才监听不到,其他地方都是可以的
    JeffreyChen 1