[js] 快速改样式 ----// 利用 protyle.toolbar.setInlineMark 进行块更新后保存

//protyle.toolbar.setInlineMark
(() => {
    // 创建按钮组
    const buttonGroup = document.createElement('div');
    buttonGroup.style.position = 'fixed';
    buttonGroup.style.top = '600px';
    buttonGroup.style.left = '1200px';
    buttonGroup.style.display = 'flex';
    buttonGroup.style.flexDirection = 'column';
    buttonGroup.style.cursor = 'move';
    buttonGroup.style.userSelect = 'none';

    // 创建颜色按钮
    function createButton(color) {
        const button = document.createElement('button');
        button.textContent = color.name;
        button.style.backgroundColor = color.background;
        button.style.color = color.color;
        button.style.padding = '1px 2px';
        button.style.border = 'none';
        button.style.cursor = 'pointer';
        button.style.marginBottom = '5px';
        button.addEventListener('click', async () => {
            const protyle = getProtyle();
            if (!protyle) {
                console.error("未找到 Protyle 实例");
                return;
            }

            const selection = window.getSelection();
            if (selection.rangeCount > 0) {
                const range = selection.getRangeAt(0);
                if (range.startContainer.nodeType === Node.TEXT_NODE && range.startContainer.parentNode) {
                    protyle.toolbar.setInlineMark(protyle, "bold", range);
                    if (color.background) {
                        protyle.toolbar.setInlineMark(protyle, "backgroundColor", range, {
                            type: "backgroundColor",
                            color: color.background
                        });
                    }
                    if (color.color) {
                        protyle.toolbar.setInlineMark(protyle, "color", range, {
                            type: "color",
                            color: color.color
                        });
                    }
                } else {
                    console.error("选中的文本范围不包含有效的节点");
                }
            }
        });
        button.addEventListener('mouseover', () => {
            button.style.background = 'linear-gradient(to right, #ff7e5f, #feb47b)';
            button.style.color = 'white';
        });
        button.addEventListener('mouseout', () => {
            button.style.background = color.background;
            button.style.color = color.color;
        });
        return button;
    }

    // 创建清除样式按钮
    function createClearButton() {
        const button = document.createElement('button');
        button.textContent = '清除';
        button.style.backgroundColor = '#CCCCCC';
        button.style.color = '#000000';
        button.style.padding = '1px 2px';
        button.style.border = 'none';
        button.style.cursor = 'pointer';
        button.addEventListener('click', async () => {
            const protyle = getProtyle();
            if (!protyle) {
                console.error("未找到 Protyle 实例");
                return;
            }

            const selection = window.getSelection();
            if (selection.rangeCount > 0) {
                const range = selection.getRangeAt(0);
                if (range.startContainer.nodeType === Node.TEXT_NODE && range.startContainer.parentNode) {
                    protyle.toolbar.setInlineMark(protyle, "clear", range);
                } else {
                    console.error("选中的文本范围不包含有效的节点");
                }
            }
        });
        return button;
    }

    // 获取Protyle实例
    function getProtyle() {
        try {
            if (document.getElementById("sidebar")) return siyuan.mobile.editor.protyle;
            const currDoc = siyuan?.layout?.centerLayout?.children.map(item => item.children.find(item => item.headElement?.classList.contains('item--focus') && (item.panelElement.closest('.layout__wnd--active') || item.panelElement.closest('[data-type="wnd"]')))).find(item => item);
            return currDoc?.model.editor.protyle;
        } catch (e) {
            console.error(e);
            return null;
        }
    }

    const colors = [
        {
            name: '黄色',
            background: '#FFFF00',
            color: '#000000'
        },
        {
            name: '蓝色',
            background: '#0000FF',
            color: '#FFFFFF'
        },
        {
            name: '绿色',
            background: '#00FF00',
            color: '#000000'
        },
        {
            name: '红色',
            background: '#FF0000',
            color: '#FFFFFF'
        }
    ];

    const buttons = colors.map(createButton);
    const clearButton = createClearButton();

    document.addEventListener('keydown', function (e) {
        if (e.ctrlKey) {
            const key = e.key.toLowerCase();
            const index = ['e', 'r', 't', 'y'].indexOf(key);
            if (index !== -1) {
                buttons[index].click();
            }
            if (key === 'c') {
                clearButton.click();
            }
        }
    });

    buttons.forEach(button => buttonGroup.appendChild(button));
    buttonGroup.appendChild(clearButton);
    document.body.appendChild(buttonGroup);

    let startX;
    let startY;
    let isDragging = false;

    buttonGroup.addEventListener('mousedown', function (e) {
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
    });

    document.addEventListener('mousemove', function (e) {
        if (isDragging) {
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            const rect = buttonGroup.getBoundingClientRect();
            let newLeft = rect.left + dx;
            let newTop = rect.top + dy;

            const viewportWidth = window.innerWidth;
            const viewportHeight = window.innerHeight;

            const buttonGroupWidth = buttonGroup.offsetWidth;
            const buttonGroupHeight = buttonGroup.offsetHeight;

            newLeft = Math.max(0, Math.min(newLeft, viewportWidth - buttonGroupWidth));
            newTop = Math.max(0, Math.min(newTop, viewportHeight - buttonGroupHeight));

            buttonGroup.style.left = `${newLeft}px`;
            buttonGroup.style.top = `${newTop}px`;
            startX = e.clientX;
            startY = e.clientY;
        }
    });

    document.addEventListener('mouseup', function () {
        isDragging = false;
    });
})();

  • 思源笔记

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

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

    23830 引用 • 96870 回帖
  • 代码片段

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

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

    109 引用 • 762 回帖
1 操作
cxg318 在 2025-01-18 01:14:32 更新了该帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • cxg318
    作者

    PixPin20250118003959.gif

  • trollface 阁下可曾试过选中已经设置过样式的地方

    换个方式,不用 updateBlock ,样式设置过的地方没什么问题。就是浮窗中不起作用,不知道怎么弄。
    cxg318
    @cxg318 突然想到,要不要给叶归加上选择自定义颜色了
    Wetoria 1 赞同

推荐标签 标签

  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    55 引用 • 85 回帖 • 2 关注
  • Q&A

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

    8882 引用 • 40469 回帖 • 130 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 169 关注
  • Latke

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

    71 引用 • 535 回帖 • 796 关注
  • 小说

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

    30 引用 • 108 回帖
  • 导航

    各种网址链接、内容导航。

    43 引用 • 177 回帖 • 1 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 647 关注
  • SEO

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

    35 引用 • 200 回帖 • 25 关注
  • Google

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

    49 引用 • 192 回帖
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 3 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 1 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    409 引用 • 3578 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 537 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 486 关注
  • 设计模式

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

    200 引用 • 120 回帖 • 1 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3192 引用 • 8214 回帖 • 1 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    36 引用 • 155 回帖
  • 自由行
    1 关注
  • Word
    13 引用 • 40 回帖
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 70 关注
  • Thymeleaf

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

    11 引用 • 19 回帖 • 369 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    66 引用 • 114 回帖 • 211 关注
  • 生活

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

    230 引用 • 1454 回帖
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 257 关注
  • Access
    1 引用 • 3 回帖 • 1 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 3 关注