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个回答

2
CKEDITOR.instances = new Array();

在我的调用之前,我使用这个来创建一个实例(每个页面加载一次)。不确定这如何影响内存处理等方面。只有当您想要替换页面上所有实例时,才会起作用。


1
我尝试了这个页面上的所有解决方案...对于我的环境来说,这是唯一一个有效的解决方案(但在我的ie9中无法正常工作,只能在FF中工作)...不确定为什么其他解决方案不起作用,但经过一小时的试错,这是唯一一个适合我的解决方案。感谢安德鲁发布这个。 - Ronedog

2

我根据以上所有代码准备了自己的解决方案。

      $("textarea.ckeditor")
      .each(function () {

                var editorId = $(this).attr("id");

                try {    
                    var instance = CKEDITOR.instances[editorId];
                    if (instance) { instance.destroy(true); }

                }
                catch(e) {}
                finally {
                    CKEDITOR.replace(editorId);
                }
            });

我觉得它对我来说完美运作。

有时在 AJAX 请求后,DOM 结构会出现错误。例如:

<div id="result">
   <div id="result>
   //CONTENT
   </div>
</div>

这也会导致问题,ckEditor将无法工作。因此,请确保您拥有正确的DOM结构。

2

您可以使用ckeditor的remove方法来删除任何ckeditor实例。实例将是文本区域的id或名称。

if (CKEDITOR.instances[instance_name]) {
    CKEDITOR.remove(CKEDITOR.instances[instance_name]);
}

2

我也曾遇到同样的实例问题,寻找了很多地方,最终采用了以下实现方式:



    //set my instance id on a variable

    myinstance = CKEDITOR.instances['info'];

    //check if my instance already exist

    if (myinstance) { 
        CKEDITOR.remove(info)
    }

    //call ckeditor again

    $('#info').ckeditor({
        toolbar: 'Basic',
        entities: false,
        basicEntities: false
    });


1

我选择重命名所有实例而不是销毁/替换 - 因为有时 AJAX 加载的实例并没有真正替换页面核心上的实例... 这样可以保留更多的 RAM,但冲突会少一些。

    if (CKEDITOR && CKEDITOR.instances) {
        for (var oldName in CKEDITOR.instances) {
            var newName = "ajax"+oldName;
            CKEDITOR.instances[newName] = CKEDITOR.instances[oldName];
            CKEDITOR.instances[newName].name = newName;
            delete CKEDITOR.instances[oldName];
        }
    }

1

我处于一种境况中,必须控制生成对话框的控件,每个对话框都需要内嵌一个 ckeditor。恰好这些文本区域共享相同的 ID。(通常这是非常糟糕的做法,但我有两个 jqGrids,一个分配项目,另一个未分配项目)。它们共享几乎相同的配置。因此,我正在使用通用代码来配置两者。

所以,当我从任一 jqGrid 加载添加行或编辑行的对话框时,必须删除所有文本区域中的 CKEDITOR 实例。

$('textarea').each(function()
{
    try 
    {
        if(CKEDITOR.instances[$(this)[0].id] != null)
        {
            CKEDITOR.instances[$(this)[0].id].destroy();
        }
    }
    catch(e)
    {

    }
});

这将循环遍历所有文本区域,如果存在 CKEDITOR 实例,则销毁它。
或者,如果您使用纯 jQuery:
$('textarea').each(function()
{
    try 
    {
        $(this).ckeditorGet().destroy();
    }
    catch(e)
    {

    }
});

1
我在使用jQuery Dialog时遇到了同样的问题。
如果你只是想删除先前的数据,为什么要销毁实例呢?
function clearEditor(id)
{
  var instance = CKEDITOR.instances[id];
  if(instance)
  {
    instance.setData( '' );
  }
}

1

事实上,从您的代码中删除“.ckeditor”类可以解决此问题。我们大多数人都遵循了 ckeditor 文档中的 jQuery 集成示例:

$('.jquery_ckeditor')
.ckeditor( function() { /* callback code */ }, { skin : 'office2003' } );

然后想着,“也许我可以只是去掉 '.jquery_' 部分”。

我一直在浪费时间调整回调函数(因为 {skin:'office2003'} 实际上起作用了),而问题实际上是来自其他地方。

我认为文档应该提到不建议使用“ckeditor”作为类名,因为它是一个保留关键字。

干杯。


1

这个函数在CKEditor 4.4.5版本中对我有效,它没有任何内存泄漏

 function CKEditor_Render(CkEditor_id) {
        var instance = CKEDITOR.instances[CkEditor_id];
        if (CKEDITOR.instances.instance) {
            CKEDITOR.instances.instance.destroy();
        }
        CKEDITOR.replace(CkEditor_id);
    }

// 以下是调用该函数的方法

var id = 'ckeditor'; // Id of your textarea

CKEditor_Render(id);

这段代码中有一个小错误 if (CKEDITOR.instances.instance) {,在 if 语句内部应该只有 instance - smarteist

1

我了解到

单独使用delete CKEDITOR.instances[editorName];实际上可以删除实例。我已经阅读和看过的所有其他方法,包括在stackoverflow上从其用户那里找到的方法,对我都没有用。

在我的情况下,我正在使用ajax调用来拉取包装在


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