CKEditor实例已经存在。

99

我正在使用jQuery对话框呈现通过AJAX获取的表单。在某些表单中,我使用CKEditor来处理文本区域。编辑器在第一次加载时显示得很好。

当用户取消对话框时,我会删除内容,以便它们在稍后的请求中重新加载。问题是,一旦对话框重新加载,CKEditor就会声称编辑器已经存在。

uncaught exception: [CKEDITOR.editor] The instance "textarea_name" already exists.

这个API包含一个销毁现有编辑器的方法,我看到有些人声称这是一个解决方案:

if (CKEDITOR.instances['textarea_name']) {
CKEDITOR.instances['textarea_name'].destroy();
}
CKEDITOR.replace('textarea_name');

这对我来说不起作用,因为我收到了一个新的错误:

TypeError: Result of expression 'i.contentWindow' [null] is not an object.

这个错误似乎发生在“destroy()”而不是“replace()”。是否有人遇到过这种情况并找到了不同的解决方法?

是否可以“重新渲染”现有的编辑器,而不是销毁和替换它?

更新:这里还有一个问题涉及相同的问题,但他提供了可下载的测试案例

32个回答

104
为了使此操作生效,您需要在销毁实例时传递布尔参数true
    var editor = CKEDITOR.instances[name];
    if (editor) { editor.destroy(true); }
    CKEDITOR.replace(name);

2
“true”选项会产生很大的不同。值得一提的是,下面给出的“CKEDITOR.remove(instance)”答案并不是一个好的解决方案,因为它是一个内部API,可能会产生错误,最好使用instance.destroy(true)。 - Bala Clark
谢谢,这真的帮了我很多。 - incomplete
6
加入感谢的合唱中!我喜欢 Stack Overflow 总是能在一次搜索中解决我所有的问题。 - Tommi Forsström
1
这个答案非常有用,我很惊讶它被埋藏得如此深。 - Petr Vostrel
2
应该有一个选项可以按照回答收到的投票数对其进行排序,这样最好的答案就会排在前面。 - shasi kanth
当我使用这个方法时,我的新编辑器实例从未加载。它总是显示为loaded: false和status: unloaded。还有其他人遇到过这种情况吗? - Will Hitchcock

28
function loadEditor(id)
{
    var instance = CKEDITOR.instances[id];
    if(instance)
    {
        CKEDITOR.remove(instance);
    }
    CKEDITOR.replace(id);
}

这让我有些困扰,但是你的解决方案帮了我很大的忙。谢谢! - Ben Scheirman
我在Firefox中遇到了类似的问题,页面上有三个CKEditor实例,第一个没有显示,但其他两个都有。我添加了上面的代码,现在所有编辑器都出现了。 - Craig Angus
18
不要使用CKEDITOR.remove,因为它只从数组中清除元素,但所有的DOM都保留在内存中。文档中指出它是用于内部使用的:http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.html#.remove正如madhaviaddanki所说,应该使用instance.destroy()来替代它。 - AlfonsoML
2
遇到了相同的情况,正如所指出的那样,这个答案是不正确的。使用 destroy() 并传递 true 参数是最终为我工作的方法,如下所述。 - Mathachew

19

我也曾经遇到这个问题,但我以一种更简单的方式解决了它...

我在我的jQuery脚本中使用了"class:ckeditor"作为选择器来确定我想要使用CKEditor的哪些文本区域。默认的 CKEditor JS 脚本也使用此类来识别应使用哪些文本区域进行 CKEditor。

这意味着我的 jQuery 脚本和默认的 CKEditor 脚本之间存在冲突。

我只需将文本区域和我的 jQuery 脚本的 class 更改为“do_ckeditor”(除 "ckeditor" 以外您可以使用任何其他名称),然后它就可以工作了。


谢谢,是的,“auto” ckeditorizing 也让我感到困扰。另请参见 https://dev59.com/mnA65IYBdhLWcg3w1SXU#3631391。 - D.Tate

12

这是我用过的最简单(也是唯一)有效的解决方案:

if(CKEDITOR.instances[editorName])
   delete CKEDITOR.instances[editorName];
CKEDITOR.replace(editorName);

在数组中删除此条目会防止此表单安全检查破坏您的应用程序。

destroy() 和 remove() 对我没有起作用。


1
这是唯一一个对我有效的解决方案,感谢您的发布! - Michael Robinson
我已经成功使用destroy()方法了。但是无论是delete还是destroy()都不能完全清除编辑器实例的所有内容,例如字典和其他相关对象仍然存在。 - adu
我尝试了instance.destroy(true),但是它对我没有起作用。但这个可以用。请问有什么副作用吗? - Manjeet

7
也许这会对您有所帮助 - 我使用jquery做了类似的事情,只是我正在加载未知数量的ckeditor对象。我花了一段时间才发现这个问题 - 在文档中并不清楚。
function loadEditors() {
    var $editors = $("textarea.ckeditor");
    if ($editors.length) {
        $editors.each(function() {
            var editorID = $(this).attr("id");
            var instance = CKEDITOR.instances[editorID];
            if (instance) { instance.destroy(true); }
            CKEDITOR.replace(editorID);
        });
    }
}

以下是我用来从编辑器获取内容的代码:

    var $editors = $("textarea.ckeditor");
    if ($editors.length) {
        $editors.each(function() {
            var instance = CKEDITOR.instances[$(this).attr("id")];
            if (instance) { $(this).val(instance.getData()); }
        });
    }

更新:我已经更改了我的答案,使用了正确的方法——即 .destroy()。.remove() 是内部使用的,曾经被错误地记录在文档中。


这似乎已经解决了错误,但在第二次渲染时,文本区域现在包含“null”,我无法再与工具栏或文本区域交互。如果我单击工具栏按钮,我会收到诸如:“TypeError:表达式'this.$.focus' [undefined]的结果不是函数”或“TypeError:表达式'this.document.getWindow().$' [undefined]的结果不是对象”的错误。您在何时/何处调用该函数?我将我的脚本与jquery加载的内容内联。(ckeditor.js在父html的头部) - jackboberg
在所有文本区域都已添加到页面并填充内容后,我会调用此函数。 - ScottE

6
var e= CKEDITOR.instances['sample'];
e.destroy();
e= null;

5

对于ajax请求,

 for(k in CKEDITOR.instances){
    var instance = CKEDITOR.instances[k];
    instance.destroy()
 }
  CKEDITOR.replaceAll();

这段代码会从文档中删除所有实例,然后创建新的实例。


5

我曾经遇到过类似的问题,我们通过ajax加载内容时需要创建多个CKeditor实例。

CKEDITOR.remove()

这将使DOM保留在内存中,并未移除所有绑定。

CKEDITOR.instance[instance_id].destroy()

使用上述代码会出现i.contentWindow错误,每当我用新数据从ajax创建新实例时。但是直到我发现我是在清除DOM后销毁实例,才解决了这个问题。

要使它正常工作,请在实例和其DOM存在于页面上时使用destroy()


3
i.contentWindow is null 错误似乎在调用已绑定到不再在DOM中的textarea的编辑器实例上的destroy时发生。 CKEDITOR.destroy 需要一个 noUpdate 参数。
APIdoc说明如下:

如果该实例正在替换DOM元素,则此参数指示是否更新实例内容。

因此,为了避免错误,请在从DOM中删除textarea元素之前调用destroy,或者调用destroy(true)以避免尝试更新不存在的DOM元素。
if (CKEDITOR.instances['textarea_name']) {
   CKEDITOR.instances['textarea_name'].destroy(true);
}

(使用带有jQuery适配器的版本3.6.2)

3
这是我亲测有效的方法:
for(name in CKEDITOR.instances)
{
  CKEDITOR.instances[name].destroy()
}

确保你的“取消”代码调用类似于这样的东西!我的问题是我的取消没有调用destroy :) - ROunofF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接