繁体   English   中英

无法输入到CKEditor5的EditableElement

[英]Can not input to EditableElement of CKEditor5

在CKEditor5中,我尝试实现自定义元素以将模型转换为视图以进行编辑。 然后,容器元素(@ ckeditor / ckeditor5-engine / src / view / containerelement)中的可编辑元素(@ ckeditor / ckeditor5-engine / src / view / editableelement)集中在父容器元素上,无法进行编辑。

例如,如果实现如下:

buildModelConverter().for(editing.modelToView)
            .fromElement('myElement')
            .toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));

插入“ myElement”和按下“ abc”后实际编辑dom的结果。 (我希望将“ abc”的文本输入到h4标签中,但是...)

<div>​​​​​​​
  abc
  <h4>
    <br data-cke-filler="true">
  </h4>
</div>

我也尝试使用小部件来应用contenteditable属性。 但是,无法在h4中输入文本。

<div class="ck-widget" contenteditable="false">​​​​​​​
  <h4 class="ck-editable" contenteditable="true">
    <br data-cke-filler="true">
  </h4>
</div>

是此错误,还是我对容器元素的理解有误?

[额外细节]

我假设要制作一个用于排名列表的小部件插件。

首先,由于具有多个项目,因此排名列表由<ol><li>标记构成。 我通过定义两个模式(例如“ rankingList”和“ rankingListItem”)解决了这一问题,因此我使用嵌套的模型元素实现了动态元素。

const item1 = new ModelElement('rankingListItem');
const item2 = new ModelElement('rankingListItem');
const model = new ModelElement('rankingList', {}, [item1, item2]);
// and insert

接下来,排名列表的项目具有链接,图像,标题和注释。 因此,排名列表项具有以下DOM结构:

<ol><!-- apply toWidget -->
  <li>
    <a href="link[editable]">
      <img src="image[editable]">
      <h3>title[editable]</h3>
      <p>notes[editable]</p>
    </a>
  </li>
  ...
</ol>

我希望view元素如下:

const {ref, src, title, notes} = data; // how to get data?
const view = new ContainerElement('a', {ref}, [
    new EmptyElement('img', {src}),
    new EditableElement('h3', {}, new Text(title)),
    new EditableElement('p', {}, new Text(title)),
  ]);
// maybe incorrect ...

总之,我想使用可编辑视图不破坏定义的DOM树。 我怎么知道呢?

感谢您描述您的情况。 目前,对于我们而言,了解开发人员如何使用该编辑器以及您的期望是非常重要的。

不幸的是,这看起来像一个非常复杂的功能。 看起来还需要自定义UI(以编辑链接url和image src-除非添加到编辑器后它们没有更改)。 您似乎遇到了两个问题:

  • 模型和视图之间的位置映射,
  • 嵌套的可编辑内容。

首先,回答有关EditableElement的问题-将它们用于h3p元素似乎是正确的。

但是,这种复杂功能需要自定义转换器。 转换器构建器(您使用过的)专用于简单情况下,例如元素到元素的转换或属性到属性的转换。

在漂亮的API后面,构建转换器是一个函数工厂,它创建一个或多个函数。 那些然后加入作为回调来ModelConversionDispatcher (其editor.editing.modelToView是一个实例)。 ModelConversionDispatcher在转换期间触发一系列事件,这是将模型中的更改转换为视图的过程。

如前所述,您将必须自己编写这些转换函数。

由于没有太多主题可以提供详细且详尽的答案,所以我仅向您简要介绍您应该感兴趣的内容。遗憾的是,目前还没有有关从头开始创建自定义转换器的指南。 这是一个非常广泛的主题。

首先,让我从大多数问题的根源向您解释。 如您所知,编辑器具有三层:模型(数据),视图(类似于DOM的结构)和DOM。 将模型转换为视图,然后将视图呈现为DOM。 同样,另一种方式是,当您加载数据时,DOM被转换为视图,而视图被转换为模型。 这就是为什么您需要为功能提供模型到视图转换器和视图到模型转换器的原因。

这个难题的重要部分是engine.conversion.Mapper 它的作用是从模型到视图映射元素和位置。 您可能已经看到,模型可能与视图完全不同。 这些之间正确的位置映射是关键。 当您在插入符号位置(在DOM中)键入字母时,该位置将映射到模型,并且该字母会插入模型中,然后才转换回视图和DOM。 如果视图到模型的位置转换错误,则您将无法在该位置键入或做任何事情。

Mapper本身非常简单。 它所需要的只是指定哪些视图元素绑定到哪些模型元素。 例如,在模型中,您可能具有:

<listItem type="bulleted" indent="0">Foo</listItem>
<listItem type="bulleted" indent="1">Bar</listItem>

在视图中时,您有:

<ul>
  <li>
    Foo
    <ul>
      <li>Bar</li>
    </ul>
  </li>
</ul>

如果映射器知道第一个listItem与第一个<li>绑定,第二个listItem与第二个<li>绑定,则它能够正确转换位置。

回到你的情况。 每个转换器必须为Mapper提供数据。 由于您使用的是转换器构建器,因此由它生成的转换器已经做到了。 但是它们很简单,因此当您提供以下信息时:

buildModelConverter().for(editing.modelToView)
        .fromElement('myElement')
        .toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));

假定myElement<div>绑定。 因此,在<div>写入的所有内容将直接进入myElement ,然后在myElement的开头myElement

<div>
  <h4></h4>
</div>

假设您只是在<h4>处写了x ,该位置将被映射到模型中的myElement偏移量0 ,然后在<div>的开头呈现给视图。

模型:

<myElement>x</myElement>

视图:

<div>x<h4></h4></div>

如您所见,您的情况是<h4>应该与myElement绑定。

目前,我们处于重构阶段。 目标之一是为转换器制造商提供更多实用程序功能。 这些实用程序之一是具有包装器元素的元素的转换器,例如上述“ div + h4”情况。 这也是图像特征的情况。 该图像在模型中由<image>表示,但在视图中为<figure><img /></figure> 您可以查看ckeditor5-image来查看这些转换器的外观。 我们要简化它们。

不幸的是,您的实际情况更加复杂,因为内部有多个元素。 CKE5体系结构应该能够处理您的情况,但是您必须了解,如果没有适当的指导,这几乎是不可能写的。

如果您想ckeditor5-image ,则应该研究 ckeditor5-image库。 这并不容易,但这是最好的方法。 Image插件以及ImageCaption与您的情况非常相似。

模型:

<image alt="x" src="y">
  <caption>Foo</caption>
</image>

视图:

<figure class="image">
  <img alt="x" src="y" />
  <figcaption>Foo</caption>
</figure>

在您的情况下,我会在两行之间看到模型:

<rankItem imageSrc="x" linkUrl="y">
  <rankTitle>Foo</rankTitle>
  <rankNotes>Bar</rankNotes>
</rankItem>

而且我会让视图更重一点,但是编写转换器会更容易:

<li contenteditable="false">
  <a href="y">
    <img src="x" />
    <span class="data">
      <span class="title" contenteditable="true">Foo</span>
      <span class="notes" contenteditable="true">Bar</span>
    </span>
  </a>
</li>

对于rankTitlerankNotes基于caption元素( ckeditor5-image/src/imagecaption/imagecaptionengine.js )。

对于rankItem基于image元素( ckeditor5-image/src/image/ )。

再次提醒您-我们正在简化所有步骤。 我们希望人们编写自己的功能,甚至像您这样的复杂功能。 但是,我们知道它现在有多么复杂。 因此,目前没有文档-我们正在寻求更改和简化操作。

最后,您可以使用Link插件和使用Converter Builder构建的元素来更简单地创建该排名列表:

  • rankList > <ol class="rank">
  • rankItem > <li>
  • rankImage > <img />
  • rankNotes > <span class="notes">
  • rankTitle > <span class="title">

但是,由于整个结构都是可编辑的,因此有可能将其弄乱。

模型:

<rankList>
  <rankItem>
    <rankImage linkHref="" />
    <rankTitle>Foo</rankTitle>
    <rankNotes>Bar</rankNotes>
  </rankItem>
  ...
</rankList>

其中“ Foo”和“ Bar”也设置了linkHref属性。

视图:

<ol class="rank">
  <li>
    <a href=""><img src="" /></a>
    <span class="title"><a href="">Title</a></span>
    <span class="notes"><a href="">Foo</a></span>
  </li>
  ...
</ol>

这样的事情虽然远非完美,但只要我们在重构之前和编写指南之前就应该容易编写得多。

当然,您还必须提供视图模型转换器。 您可能想要自己编写它们(请查看ckeditor5-list/src/converters.js viewModelConverter() -尽管您会更轻松,因为它是平坦的,而不是嵌套列表)。 或者,您可以通过转换器生成器生成它们。

也许可以使用上面的方法(更简单),但是使用contentEditable属性来控制结构。 rankList必须使用contentEditable="false"转换为<ol> 例如,也许您可​​以以某种方式使用toWidget进行更好的选择处理。 rankNotesrankTitle必须转换为具有contentEditable="true"元素(可能使用toWidgetEditable() )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM