首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >操纵innerText of a CKEditor ViewElement

操纵innerText of a CKEditor ViewElement
EN

Stack Overflow用户
提问于 2022-06-13 10:39:22
回答 1查看 97关注 0票数 0

我正在为#neoscms的CKEditor5创建一个自定义插件。近地天体正在使用#ckeditor5 5,但使用的是自定义视图。

插件或多或少是占位符插件。用户可以使用键值存储项(标识符和标签)配置数据源。CKEditor中的下拉列表中填充了项,当用户从下拉列表中选择一个项时,它会创建一个占位符元素,该元素应该以带某些数据属性的span元素结尾。

其主要思想是拥有一个空元素和数据属性,以标识元素并能够分配活动数据。但事实证明,实时数据是一件棘手的事情。当我在网站上使用额外的JS片段操作span时,CKEditor无法处理这个问题。

是否有可能操作DOM中的视图元素,并且仍然有一个工作的编辑器?如果我只是在downCasting中添加内部文本,而不替换某些内容,插件就可以正常工作。但现场数据会很好。

带有元素的近地天体后端

也许这段代码给出了一个包的概念。它还没有准备好,因为这或多或少是主要特性;)

代码语言:javascript
复制
import {Plugin, toWidget, viewToModelPositionOutsideModelElement, Widget,} from "ckeditor5-exports";

import PlaceholderCommand from "./placeHolderCommand";

export default class PlaceholderEditing extends Plugin {
    static get requires() {
        return [Widget];
    }

    init() {
        this._defineSchema();
        this._defineConverters();

        this.editor.commands.add(
            "placeholder",
            new PlaceholderCommand(this.editor)
        );

        this.editor.editing.mapper.on(
            "viewToModelPosition",
            viewToModelPositionOutsideModelElement(this.editor.model, (viewElement) =>
                viewElement.hasClass("internezzo-placeholder")
            )
        );

        this.editor.config.define("placeholderProps", {
            types: ["name", "node", "nodePath"],
        });

        this.editor.config.define("placeholderBrackets", {
            open: "[",
            close: "]",
        });
    }

    _defineSchema() {
        const schema = this.editor.model.schema;

        schema.register("placeholder", {
            allowWhere: "$text",
            isInline: true,
            isObject: true,
            allowAttributes: [
                "name",
                "node",
                "nodePath",
                "data-placeholder-identifier",
                "data-node-identifier",
                "data-node-path",
            ],
        });
    }

    _defineConverters() {
        const conversion = this.editor.conversion;
        const config = this.editor.config;

        conversion.for("upcast").elementToElement({
            view: {
                name: "span",
                classes: ["foobar-placeholder"],
            },
            model: (viewElement, writer) => {
                const name = viewElement.getAttribute('data-placeholder-identifier');
                const node = viewElement.getAttribute('data-node-identifier');
                const nodePath = viewElement.getAttribute('data-node-path');
                const modelWriter = writer.writer || writer;
                return modelWriter.createElement("placeholder", {name, node, nodePath, editable: false});
            },
        });

        conversion.for("editingDowncast").elementToElement({
            model: "placeholder",
            view: (modelItem, writer) => {
                const viewWriter = writer.writer || writer;
                const widgetElement = createPlaceholderView(modelItem, viewWriter);
                return toWidget(widgetElement, viewWriter);
            },
        });

        conversion.for("dataDowncast").elementToElement({
            model: "placeholder",
            view: (modelItem, writer) => {
                const viewWriter = writer.writer || writer;

                return createPlaceholderView(modelItem, viewWriter);
            },
        });

        // Helper method for downcast converters.
        function createPlaceholderView(modelItem, viewWriter) {
            const name = modelItem.getAttribute("name");
            const node = modelItem.getAttribute("node");
            const nodePath = modelItem.getAttribute("nodePath");

            const placeholderView = viewWriter.createContainerElement("span", {
                class: "foobar-placeholder",
                "data-placeholder-identifier": name,
                "data-node-identifier": node,
                "data-node-path": nodePath,
            });

            // Would be nice to remove that and have just empty spans that get dynamic data
            let innerText = config.get("placeholderBrackets.open") + name;
            innerText += config.get("placeholderBrackets.close");
            viewWriter.insert(
                viewWriter.createPositionAt(placeholderView, 0),
                viewWriter.createText(innerText)
            );

            return placeholderView;
        }
    }
}

因此,网站使用的额外JS片段是使用类foobar-placeholder搜索跨范围,并将一个包含实时数据的值写入span中。当然,这是在前端工作的,但是使用CKEditor的CMS的后端对于不断变化的数据有问题。

EN

回答 1

Stack Overflow用户

发布于 2022-06-13 19:09:40

我找不到CKEditor文档的解决方案,也许我以某种方式滥用了API,但我现在找到了一个可行的解决方案。

我的网站片段现在正在通过广播消息与插件进行通信。然后搜索占位符元素并检查是否需要更改属性。

代码语言:javascript
复制
const broadcastChannel = new BroadcastChannel('placeholder:changeData');
broadcastChannel.postMessage({identifier: name, value});

在插件中

代码语言:javascript
复制
// Receive new values for placeholder via broadcast
        const broadcastChannel = new BroadcastChannel('placeholder:changeData');
        broadcastChannel.onmessage = (message) => {
            const identifier = get('data.identifier', message);
            const newValue = get('data.value', message);
            this.editor.model.change( writer => {
                if (identifier) {
                    this._replaceAttribute(writer, identifier, newValue);
                }
            });
        };

现在唯一的缺点是,我需要重新加载页面,但是已经读到,这可能是由我的元素向下转换和我更改属性造成的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72601461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档