撤消不会将文档内容恢复到 editor.insertHtml 之前的状态

Undo does not revert document contents to the state before editor.insertHtml

我在编写 ckeditor 插件时遇到 undo 问题。 我正在使用 editor.insertHtml 将带有特定 class 的 div 添加到文档中。如果我从一个空文档开始,撤消和重做是不亮的。当我执行命令时,撤消将亮起。如果我按撤消,两者都会点亮。 "undoing" 不会还原文档内容。

为什么不呢?

CKEDITOR.plugins.add('plugin_name',
{
  init: function(editor)
  {
    editor.ui.addButton('Button_name',
    {
      label: 'some text',
      command: 'Command_name',
      icon: this.path + 'images/icon.png'
    });

    editor.addCommand('Command_name', { canUndo: true, exec: function()
    {
      editor.fire('saveSnapshot');
      editor.insertHtml("<div contenteditable='false' class='foobar'></div>\r\n");
      editor.fire('saveSnapshot');
    }});
  }
});

我也不明白为什么插入html之前和之后都需要保存快照,但那是另外一回事了。

首先 - editor.insertHtml() 负责拍摄快照,因为它是一种高级方法。如果您停止射击 editor#saveSnapshot.

可能会有所帮助

第二件事 - 由于您的命令 canUndo 设置为 true 快照将在您执行时自动记录。所以我建议将它设置为 false 以使 editor.insertHtml() 成为唯一保存快照的人。

如果以上方法没有帮助,那么您需要检查拍摄了哪些快照。为此,只需访问 editor.undoManager.snapshots。在您的情况下,应该有两个 - 一个包含初始内容,一个在执行命令后获取。不幸的是,调试撤消管理器是一种痛苦...

I also do not understand why saving of snapshots is needed both before and after the insertion of html, but that is another story.

这是个好问题。但让我们概括一下 - 为什么我需要在更改内容之前 和更改内容之后 和之后拍摄快照?

IIRC在CKEditor 4.4.3之前有两个原因,现在只剩下第二个:

  • 因为初始快照栈是空的,所以记录初始内容,
  • 将键入的文本与之后所做的更改分开。

第一个是一个古怪的行为,在几个版本前终于得到修复。现在初始快照拍摄于 editor#instanceReady.

但第二个仍然是正确的。当您开始键入时,编辑器开始计算键数,每 25 个键就会记录一次快照。但是,如果例如您键入 5 个字符,然后按粗体按钮,您希望这 5 个字符作为单独的操作保存,然后按粗体作为第二个操作。这就是粗体命令在执行之前拍摄快照的原因 - 记录包含这 5 个新字符的快照,然后拍摄另一个快照来记录 <strong></strong> 元素的插入。

事实是,记录击键最有可能以一种无需在操作前拍摄快照的方式实现。这将需要在插入每个字符后拍摄快照,然后将它们分组。可以,但是会更重

可悲的是,最近我们无论如何都需要开始对每个键进行快照,以处理键入和删除文本时的一些棘手情况。没有可靠的方法来判断 keydown 上的字符是否会是 inserted/removed 并且好的撤消管理器应该将输入与删除分开。所以我们需要知道前面的字符插入后的内容是什么,以防按下backspace/delete press,反之亦然。

换句话说 - 在我们对撤消管理器进行了最近的更改之后,也许今天所有这些都可以简化。但可以肯定的是 - 实施一个好的撤消管理器(尤其是在您不控制字符插入的情况下)非常棘手,很少有人能做到这一点。

PS。 "\r\n"末尾的HTML要插入没有区别。