我正在为#neoscms的CKEditor5创建一个自定义插件。近地天体正在使用#ckeditor5 5,但使用的是自定义视图。
插件或多或少是占位符插件。用户可以使用键值存储项(标识符和标签)配置数据源。CKEditor中的下拉列表中填充了项,当用户从下拉列表中选择一个项时,它会创建一个占位符元素,该元素应该以带某些数据属性的span元素结尾。
其主要思想是拥有一个空元素和数据属性,以标识元素并能够分配活动数据。但事实证明,实时数据是一件棘手的事情。当我在网站上使用额外的JS片段操作span时,CKEditor无法处理这个问题。
是否有可能操作DOM中的视图元素,并且仍然有一个工作的编辑器?如果我只是在downCasting中添加内部文本,而不替换某些内容,插件就可以正常工作。但现场数据会很好。
也许这段代码给出了一个包的概念。它还没有准备好,因为这或多或少是主要特性;)
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的后端对于不断变化的数据有问题。
发布于 2022-06-13 19:09:40
我找不到CKEditor文档的解决方案,也许我以某种方式滥用了API,但我现在找到了一个可行的解决方案。
我的网站片段现在正在通过广播消息与插件进行通信。然后搜索占位符元素并检查是否需要更改属性。
const broadcastChannel = new BroadcastChannel('placeholder:changeData');
broadcastChannel.postMessage({identifier: name, value});在插件中
// 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);
}
});
};现在唯一的缺点是,我需要重新加载页面,但是已经读到,这可能是由我的元素向下转换和我更改属性造成的。
https://stackoverflow.com/questions/72601461
复制相似问题