如何使CKEditor立即将htmlParser.element.addClass所做的更改加载到DOM中?

如何使CKEditor立即将htmlParser.element.addClass所做的更改加载到DOM中?,ckeditor,ckeditor4.x,Ckeditor,Ckeditor4.x,我正在使用CKEditor 4.5.8的一个实例,它使用LoopIndex的LITE更改跟踪插件 目标:当用户删除li元素中的所有内容时,我希望隐藏li本身,而不仅仅是它包含的内容* *删除li中的所有内容时,插件将生成以下标记: 所容纳之物 del元素不允许包装li,因此移动它将不起作用 完成的工作:我在dataProcessor的htmlFilter中添加了一个函数,用于查找每个li元素,然后调用另一个函数来确定是否应该隐藏li。如果应该隐藏li,我将使用htmlParser.element

我正在使用CKEditor 4.5.8的一个实例,它使用LoopIndex的LITE更改跟踪插件

目标:当用户删除li元素中的所有内容时,我希望隐藏li本身,而不仅仅是它包含的内容*

*删除li中的所有内容时,插件将生成以下标记: 所容纳之物 del元素不允许包装li,因此移动它将不起作用

完成的工作:我在dataProcessor的htmlFilter中添加了一个函数,用于查找每个li元素,然后调用另一个函数来确定是否应该隐藏li。如果应该隐藏li,我将使用htmlParser.element.addClass添加一个hideListItem类。我有一个CSS,它将这个类的任何内容的显示设置为“无”

该规则运行良好;删除列表项中的所有内容时,该规则会将hideListItem类添加到li中

问题:DOM不会立即得到更新,现在通过del元素带有更改跟踪标记的列表项会继续显示

在浏览器控制台中,如果我检查CKEDITOR.instances[''u editor1'].\uu.data,或者简单地调用实例上的getData,我会看到文档标记包含带有新添加类的列表项。但是,当我使用浏览器工具中的元素选项卡浏览DOM时,列表项中缺少新类

在控制台中,我可以运行instance.setDatainstance.getData,其中instance是对我的CKEDITOR实例的引用,然后DOM更新。但是如果我把它包括在规则中,我会进入一个无限循环

如何使CKEditor将数据模型写入DOM

代码:

this.editor.on'instancerady',=>{ 常量hideDeletedListItems={ 要素:{ li:元素=>{ IfShouldHideElement元素{ 元素。addClass'hideListItem' } } } } this.editor.dataProcessor['htmlFilter'].addRuleshideDeletedListItems{ 优先事项:10, 阿普利托尔:是的 } }
据我所知,当您尝试设置或获取CKEditor的内容时,会发生过滤。并且您希望将脚本应用于内容编辑

Instaed,如何在更改事件上运行您的函数

像这样的东西没有经过测试

CKEDITOR.on('change', function (event) {
    $(this.document.$).find("li").each(function () {
        if (shouldHideElement($(this))) {
            $(this).addClass('hideListItem')
        }
    });
});

按照SAZ的建议修改“change”上的DOM是我最终采用的一般方法,但做了一些重要的修改

问题 我需要用提议的方法限制或克服两个问题:

频率。我使用代码不仅修改li元素,而且修改头,最终修改表行和列表本身。即使不运行perf测试,似乎也可能需要大量的周期来处理一切

保留撤消的能力。在代码中修改DOM的问题在于,修改的是我的应用程序,而不是用户。如果用户按CTRL+Z,则应撤消用户的最后一个操作,而不仅仅是应用程序的最后一个操作

例如,如果我在代码中修改了20个li元素,以响应用户删除页面上第一个li元素的内容,那么CTRL+Z只会撤消对li编号20进行的类更改,而不会撤消用户删除li编号1的内容

问题决议:

我通过只监听lite:change事件来限制代码的运行频率,实际上只有在我需要它的时候才这样做

我克服了撤消问题,在DOM处理之前锁定了CKEditor快照,然后在完成后解锁并更新快照。这样,CKEditor将我的代码所做的所有DOM更改视为撤消堆栈中的单个帧

解决方案 我在最初的问题中展示了JavaScript。然而,我实际上使用的是 键入脚本,并在下面显示,以帮助澄清正在执行的操作

打字稿:

CSS:


谢谢SAZ的快速回复。您关于何时进行筛选的评论很有帮助。
const trackChangePlugin = this.editor.plugins.lite.findPlugin(this.editor)

const processElementDisplay = (elementTag: string) => {
  const elementCollection: CKEDITOR.dom.nodeList = this.editor.document.getElementsByTag(elementTag)
  // newer versions of CKEditor have a toArray() function, but I'm using an older version, so I created my own:
  const elementArray = this.convertNodeListToArray(elementCollection)
  elementArray.forEach((el:CKEDITOR.dom.element) => {
    if (shouldHideElement(el) && trackChangesPlugin._isVisible) el.$.setAttribute('data-hideElement', 'false')
    else if (shouldHideElement(el)) el.$.setAttribute('data-hideElement', 'true')
    else el.$.removeAttribute('data-hideElement')
  })
}

const fixChangeTrackingDeletions = () => {
  this.editor.fire('lockSnapshot')
  processElementDisplay('li')
  this.editor.fire('unlockSnapshot')
  this.editor.fire('updateSnapshot')
}

this.editor.on('lite:showHide', fixChangeTrackingDeletions)

this.editor.on('lite:change', fixChangeTrackingDeletions)
li[data-hideElement='true'] {
  display:none;
}

li[data-hideElement='false'] {
  display: list-item;
}