[js] 添加一个顶栏按钮,实现点击即打开代码片段界面

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

最终实现的 JS 代码片段:

/** * 在顶栏添加按钮,快捷打开代码片段界面 JS片段 * 参考 https://ld246.com/article/1674026309504 修改,同时感谢 [Undii](https://ld246.com/member/Undii) 提供 帮助 * 为顶栏增加代码片段按钮,点击后创建快捷键按下事件 * 挂件模式支持点击日记列出笔记本。 https://ld246.com/article/1674026309504 */ // 设置是否添加对应按钮 let g_addSnippets = true;// 设置 // 插入按钮 // 插入日历笔记本选择挂件 // 参考: https://ld246.com/article/1662969146166 原作者: BryceAndJuly // 参考: https://github.com/svchord/Rem-Craft 原作者: Seven Chor function addSnippets() { let barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "afterend", '<div id="barSnippets_simulate" class="toolbar__item ariaLabel" aria-label="代码片段/Snippets"></div>' ); let settingBtn = document.getElementById("barSnippets_simulate"); settingBtn.innerHTML = `<svg><use xlink:href="#iconCode"></use></svg>`; settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); setTimeout(function() { // 找到包含 data-name="appearance" 的 <li> 元素 var element = document.querySelector('li[data-name="appearance"]'); // 创建一个点击事件 var event = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); // 触发点击事件 element.dispatchEvent(event); }, 100); // 1000毫秒 = 1秒 setTimeout(function() { // 获取按钮元素 var button = document.getElementById('codeSnippet'); // 创建一个新的点击事件 var clickEvent = new MouseEvent('click', { view: window, bubbles: true, cancelable: true }); // 触发按钮的点击事件 button.dispatchEvent(clickEvent); }, 200); // 1000毫秒 = 1秒 } ); } /** * */ function dispatchKeyEvent(functionName) { let keyInit = parseHotKeyStr(window.top.siyuan.config.keymap.general[functionName].custom); keyInit["bubbles"] = true; let keydownEvent = new KeyboardEvent('keydown', keyInit); document.getElementsByTagName("body")[0].dispatchEvent(keydownEvent); let keyUpEvent = new KeyboardEvent('keyup', keyInit); document.getElementsByTagName("body")[0].dispatchEvent(keyUpEvent); } /** * * @param {*} hotkeyStr 思源hotkey格式 Refer: https://github.com/siyuan-note/siyuan/blob/d0f011b1a5b12e5546421f8bd442606bf0b5ad86/app/src/protyle/util/hotKey.ts#L4 * @returns KeyboardEventInit Refer: https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/KeyboardEvent */ function parseHotKeyStr(hotkeyStr) { let result = { ctrlKey: false, altKey: false, metaKey: false, shiftKey: false, key: 'A', keyCode: 0 } if (hotkeyStr == "" || hotkeyStr == undefined || hotkeyStr == null) { console.error("解析快捷键设置失败", hotkeyStr); throw new Error("解析快捷键设置失败"); } let onlyKey = hotkeyStr; if (hotkeyStr.indexOf("⌘") != -1) { result.ctrlKey = true; onlyKey = onlyKey.replace("⌘", ""); } if (hotkeyStr.indexOf("⌥") != -1) { result.altKey = true; onlyKey = onlyKey.replace("⌥", ""); } if (hotkeyStr.indexOf("⇧") != -1) { result.shiftKey = true; onlyKey = onlyKey.replace("⇧", ""); } // 未处理 windows btn (MetaKey) result.key = onlyKey; // 在https://github.com/siyuan-note/siyuan/commit/70acd57c4b4701b973a8ca93fadf6c003b24c789#diff-558f9f531a326d2fd53151e3fc250ac4bd545452ba782b0c7c18765a37a4e2cc // 更改中,思源改为使用keyCode判断快捷键按下事件,这里进行了对应的转换 // 另请参考该提交中涉及的文件 result.keyCode = keyCodeList[result.key]; console.assert(result.keyCode != undefined, `keyCode转换错误,key为${result.key}`); switch (result.key) { case "→": { result.key = "ArrowRight"; break; } case "←": { result.key = "ArrowLeft"; break; } case "↑": { result.key = "ArrowUp"; break; } case "↓": { result.key = "ArrowDown"; break; } case "⌦": { result.key = "Delete"; break; } case "⌫": { result.key = "Backspace"; break; } case "↩": { result.key = "Enter"; break; } } return result; } if (g_addSnippets) addSnippets(); const keyCodeList = { "⌫": 8, "⇥": 9, "↩": 13, "⇧": 16, "⌘": 91, "⌥": 18, "Pause": 19, "CapsLock": 20, "Escape": 27, " ": 32, "PageUp": 33, "PageDown": 34, "End": 35, "Home": 36, "←": 37, "↑": 38, "→": 39, "↓": 40, "PrintScreen": 44, "Insert": 45, "⌦": 46, "0": 48, "1": 49, "2": 50, "3": 51, "4": 52, "5": 53, "6": 54, "7": 55, "8": 56, "9": 57, "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74, "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84, "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90, "ContextMenu": 93, "MyComputer": 182, "MyCalculator": 183, ";": 186, "=": 187, ",": 188, "-": 189, ".": 190, "/": 191, "`": 192, "[": 219, "\\": 220, "]": 221, "'": 222, "*": 106, "+": 107, "-": 109, ".": 110, "/": 111, "F1": 112, "F2": 113, "F3": 114, "F4": 115, "F5": 116, "F6": 117, "F7": 118, "F8": 119, "F9": 120, "F10": 121, "F11": 122, "F12": 123, "NumLock": 144, "ScrollLock": 145 };

原贴:

看到个 帖子 ,添加按钮应该是这样:

function addSnippets() { let barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "afterend", '<div id="barSnippets_simulate" class="toolbar__item ariaLabel" aria-label="代码片段/Snippets" ></div>' ); let settingBtn = document.getElementById("barSnippets_simulate"); settingBtn.innerHTML = `<svg><use xlink:href="#iconCode"></use></svg>`; settingBtn.addEventListener("click", function() { openSnippets(); }, false); } function openSnippets() { } addSnippets();

但是我不知道怎么打开代码片段界面

  • 思源笔记

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

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

    26125 引用 • 108470 回帖
  • 代码片段

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

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

    192 引用 • 1363 回帖
  • Q&A

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

    10040 引用 • 45626 回帖 • 69 关注
1 操作
JeffreyChen 在 2024-10-04 17:26:37 更新了该帖

相关帖子

被采纳的回答
  • Undii 1 via Android

    主要是 模拟点击应该在 点击顶栏按钮、并且打开设置页之后进行
    你这里的 setTimeout 并没有和点击顶栏按钮关联起来,也就是,“延迟模拟点击打开代码片段”,这个事情之会在代码生效时执行一次。在 4 秒内打开了设置,这里代码就会正确执行一次。

    settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); // setTimeout写在这里 } );

    上面的代码,是将 click 点击顶栏按钮的事件和 function 关联了起来,具体的,这里执行了 dispatchKeyEvent 来模拟快捷键打开设置页面,

    所以 setTimeout 应该写在这里;

    我也在原帖中更新了相应的代码。

欢迎来到这里!

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

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

    假如你只想通过代码片段来实现,可以用代码模拟点击 siyuan-> 设置-> 外观-> 代码片段来实现.

    也可以用 openapi 实现. fetchPost /api/snippet/getSnippet", 具体代码可参考 siyuan\app\src\config\util\snippets.ts

    1 回复
  • 首先我没学过编程,只是看过一些代码。

    刚开始我是想通过点击这个顶栏按钮「创建快捷键按下事件」打开设置界面,然后模拟点击 外观 > 代码片段设置 ,但我不会编程,只能拿 GPT 改,能打开设置界面,但没法点击,我也不会修(跟模拟点击相关的代码附在后面)。

    然后就想到看看是不是通过什么请求打开的代码片段界面,看到了 api/snippet/getSnippet ,然后就去仓库搜,搜到了我感觉可能跟打开界面有关的 代码 ,但我看不懂,只能试试 把 ts 转为 js 之后粘贴到之前的代码里试试,果然没法直接运行。然而我也不知道怎么搞这个 POST 请求 ,请求了也不知道怎么用。

    最后我就无能为力了。

    image.png

    /** * 为顶栏增加代码片段按钮,点击后创建快捷键按下事件 * 挂件模式支持点击日记列出笔记本。 https://ld246.com/article/1674026309504 */ // 设置是否添加对应按钮 let g_addSnippets = true;// 设置 function addSnippets() { let barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "afterend", '<div id="barSnippets_simulate" class="toolbar__item ariaLabel" aria-label="代码片段/Snippets" ></div>' ); let settingBtn = document.getElementById("barSnippets_simulate"); settingBtn.innerHTML = `<svg><use xlink:href="#iconCode"></use></svg>`; settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); }, false ); setTimeout(function() { // 找到包含 data-name="appearance" 的 <li> 元素 var element = document.querySelector('li[data-name="appearance"]'); // 创建一个点击事件 var event = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); // 触发点击事件 element.dispatchEvent(event); }, 2000); // 1000毫秒 = 1秒 setTimeout(function() { // 模拟点击代码片段设置按钮 // var button = document.getElementById('codeSnippet'); // button.click(); // 获取按钮元素 var button = document.getElementById('codeSnippet'); // 创建一个新的点击事件 var clickEvent = new MouseEvent('click', { view: window, bubbles: true, cancelable: true }); // 触发按钮的点击事件 button.dispatchEvent(clickEvent); }, 2000); // 1000毫秒 = 1秒 }
    1 回复
  • 两个 setTimeout 的位置错了,应该放在 dispatchKeyEvent("config"); 之后;

    我没想过 GPT 还能做这个;这是怎么给 GPT 说的呢?

    setTimeout 延迟两秒似乎也不需要,能更快,设置几百应该就行;

    2 回复
  • 我首先理解了基础代码,然后再修改到可以正常打开设置界面,之后模拟点击我不会,就用开发者工具找到那个元素,然后:

    我:怎么用 JS 模拟点击按钮:<button class="b3-button b3-button--outline fn__flex-center fn__size200" id="codeSnippet"><svg><use xlink:href="#iconSettings"></use></svg>设置 </button>

    GPT:要使用 JavaScript 模拟点击按钮,可以通过以下步骤实现:

    1. 首先,获取对应的按钮元素。在这种情况下,您可以使用按钮的 id 属性来获取该元素。
    var button = document.getElementById('codeSnippet');
    1. 然后,您可以使用 click() 方法来模拟点击按钮。
    button.click();

    整体代码如下:

    var button = document.getElementById('codeSnippet'); button.click();

    这样,当您运行这段 JavaScript 代码时,它将模拟点击具有 id 为 codeSnippet 的按钮。

    我:让这个模拟点击在这段程序的最后阶段执行:

    function addSnippets() { let barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "afterend", '<div id="barSnippets_simulate" class="toolbar__item ariaLabel" aria-label="代码片段/Snippets" ></div>' ); let settingBtn = document.getElementById("barSnippets_simulate"); settingBtn.innerHTML = `<svg><use xlink:href="#iconCode"></use></svg>`; settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); }, false ); }

    GPT:要在这段程序的最后阶段执行模拟点击按钮的操作,您可以在 addSnippets() 函数的最后调用前面提到的模拟点击按钮的代码。这样可以确保在设置按钮被添加到页面并且事件监听器被设置后再触发点击事件。

    下面是修改后的代码:

    function addSnippets() { let barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "afterend", '<div id="barSnippets_simulate" class="toolbar__item ariaLabel" aria-label="代码片段/Snippets" ></div>' ); let settingBtn = document.getElementById("barSnippets_simulate"); settingBtn.innerHTML = `<svg><use xlink:href="#iconCode"></use></svg>`; settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); }, false ); // 模拟点击按钮 var button = document.getElementById('codeSnippet'); button.click(); }

    在这个修改后的代码中,addSnippets() 函数会先执行添加设置按钮的操作,然后再执行模拟点击按钮的操作。这样可以确保在设置按钮被添加到页面并且事件监听器被设置后再触发点击事件。

    然后发现界面加载要一点时间,于是就:

    我:我想在前面增加 1s 的延时

    GPT:要在调用按钮点击事件处理程序之前增加 1 秒的延时,您可以使用 setTimeout() 函数来实现。setTimeout() 函数可以在指定的时间间隔后执行指定的函数。

    下面是一个示例代码,演示如何在调用按钮点击事件处理程序之前增加 1 秒的延时:

    // 获取按钮元素 var button = document.getElementById('codeSnippet'); // 创建一个新的点击事件 var clickEvent = new MouseEvent('click', { view: window, bubbles: true, cancelable: true }); // 增加1秒延时后触发按钮的点击事件 setTimeout(function() { button.dispatchEvent(clickEvent); }, 1000); // 1000毫秒 = 1秒

    在这段代码中,setTimeout() 函数会在 1 秒后触发指定的函数,该函数会触发按钮的点击事件处理程序。这样就实现了在调用按钮点击事件处理程序之前增加 1 秒的延时。

    我就自己把代码加上去了。

  • 我让 GPT 改了一下,成功了一次,然后就一直都不行了。我不太理解:

    回帖不能超过 4000 字,完整代码:顶栏按钮.zip

    function addSnippets() { let barMode = document.getElementById("barMode"); barMode.insertAdjacentHTML( "afterend", '<div id="barSnippets_simulate" class="toolbar__item ariaLabel" aria-label="代码片段/Snippets"></div>' ); let settingBtn = document.getElementById("barSnippets_simulate"); settingBtn.innerHTML = `<svg><use xlink:href="#iconCode"></use></svg>`; settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); } ); setTimeout(function() { // 找到包含 data-name="appearance" 的 <li> 元素 var element = document.querySelector('li[data-name="appearance"]'); // 创建一个点击事件 var event = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); // 触发点击事件 element.dispatchEvent(event); }, 4000); // 4000毫秒 = 4秒 setTimeout(function() { // 获取按钮元素 var button = document.getElementById('codeSnippet'); // 创建一个新的点击事件 var clickEvent = new MouseEvent('click', { view: window, bubbles: true, cancelable: true }); // 触发按钮的点击事件 button.dispatchEvent(clickEvent); }, 4000); // 4000毫秒 = 4秒 }
    1 回复
  • Undii 1 1 评论 via Android

    主要是 模拟点击应该在 点击顶栏按钮、并且打开设置页之后进行
    你这里的 setTimeout 并没有和点击顶栏按钮关联起来,也就是,“延迟模拟点击打开代码片段”,这个事情之会在代码生效时执行一次。在 4 秒内打开了设置,这里代码就会正确执行一次。

    settingBtn.addEventListener( "click", function (e) { dispatchKeyEvent("config"); // setTimeout写在这里 } );

    上面的代码,是将 click 点击顶栏按钮的事件和 function 关联了起来,具体的,这里执行了 dispatchKeyEvent 来模拟快捷键打开设置页面,

    所以 setTimeout 应该写在这里;

    我也在原帖中更新了相应的代码。

    1 回复
    用 api 的话 返回的是代码片段的内容 需要自己写一个 dialog 显示 这个最好用插件做。
    Undii
  • 这回我搞懂了,能顺利运行了,谢谢你 😘

  • kikkawa via macOS

    很实用,谢谢

  • GloR

    感谢大佬!

    或许大佬愿意把这两个插件的功能整合一下么?

    点击 按钮 快速开关代码片段 + 点击“管理”快速打开代码片段窗口

    image.png

    image.png

请输入回帖内容 ...
JeffreyChen
思源笔记同步教程:https://ld246.com/article/1692089679062 爱发电:https://afdian.com/a/JeffreyChen

推荐标签 标签

  • jQuery

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

    63 引用 • 134 回帖 • 734 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 70 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 100 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 226 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 562 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 111 关注
  • danl
    176 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖 • 1 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    10 引用 • 54 回帖 • 181 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 3 关注
  • TGIF

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

    291 引用 • 4495 回帖 • 662 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 10 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 394 关注
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    211 引用 • 358 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • 前端

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

    246 引用 • 1338 回帖
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    44 引用 • 208 回帖
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖 • 1 关注
  • sts
    2 引用 • 2 回帖 • 241 关注
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 28 回帖 • 1 关注
  • 印象笔记
    3 引用 • 16 回帖
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    91 引用 • 384 回帖
  • 代码片段

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

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

    192 引用 • 1363 回帖 • 1 关注
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    589 引用 • 3528 回帖
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    59 引用 • 22 回帖 • 12 关注
  • Q&A

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

    10040 引用 • 45626 回帖 • 69 关注