我正在使用jquery对话框来呈现表单(通过AJAX获取)。在某些形式上,我使用CKEditor作为textareas。编辑器在第一次加载时显示正常。
当用户取消对话框时,我将删除内容,以便在以后的请求中重新加载它们。问题是,一旦重新加载对话框,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()”上。有没有人经历过这个并找到了不同的解决方案?
是否可以'重新渲染'现有编辑器,而不是销毁和替换它?
已更新 Here is another question处理同样的问题,但他提供了downloadable test case。
答案 0 :(得分:97)
要使其工作,您需要在销毁实例时传递布尔参数 true :
var editor = CKEDITOR.instances[name];
if (editor) { editor.destroy(true); }
CKEDITOR.replace(name);
答案 1 :(得分:27)
function loadEditor(id)
{
var instance = CKEDITOR.instances[id];
if(instance)
{
CKEDITOR.remove(instance);
}
CKEDITOR.replace(id);
}
答案 2 :(得分:18)
我也有这个问题,但我用更简单的方式解决了它......
我在我的jQuery脚本中使用了类“ckeditor”作为我想要用于CKEditor的textareas的选择器。默认的ckeditor JS脚本也使用此类来标识要用于CKEditor的textareas。
这意味着我的jQuery脚本和默认的ckeditor脚本之间存在冲突。
我只是将textarea和我的jQuery脚本的类更改为'do_ckeditor'(你可以使用除“ckeditor”之外的任何东西)并且它有效。
答案 3 :(得分:10)
这是对我有用的最简单(也是唯一)解决方案:
if(CKEDITOR.instances[editorName])
delete CKEDITOR.instances[editorName];
CKEDITOR.replace(editorName);
在数组中删除此条目会阻止此表单安全检查破坏您的应用程序。
destroy()和remove()对我没用。
答案 4 :(得分: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()); }
});
}
UPDATE :我已经改变了我的答案,使用了正确的方法 - 即.destroy()。 .remove()意味着是内部的,并且在某一时刻被错误地记录下来。
答案 5 :(得分:5)
var e= CKEDITOR.instances['sample'];
e.destroy();
e= null;
答案 6 :(得分:5)
对于ajax请求,
for(k in CKEDITOR.instances){
var instance = CKEDITOR.instances[k];
instance.destroy()
}
CKEDITOR.replaceAll();
此剪切会从文档中删除所有实例。 然后创建新实例。
答案 7 :(得分:5)
我遇到了类似的问题,我们为通过ajax加载的内容制作了几个CKeditor实例。
CKEDITOR.remove()
将DOM保留在内存中并且没有删除所有绑定。
CKEDITOR.instance [INSTANCE_ID] .destroy()
每当我使用ajax中的新数据创建新实例时,都会出现错误 i.contentWindow 错误。但直到我发现我在清除DOM后才破坏了实例。
在实例&中使用 destroy()它的DOM存在于页面上,然后它完美地运行。
答案 8 :(得分:3)
这对我有用:
for(name in CKEDITOR.instances)
{
CKEDITOR.instances[name].destroy()
}
答案 9 :(得分:3)
在与DOM中不再存在的textarea关联的编辑器实例上调用destroy时,似乎发生i.contentWindow is null
错误。
CKEDITORY.destroy
采用参数noUpdate
。
APIdoc声明:
如果实例正在替换DOM元素,则此参数指示是否使用实例内容更新元素。
因此,为了避免错误,要么在从DOM中删除textarea元素之前调用destroy,要么调用destory(true)以避免尝试更新不存在的DOM元素。
if (CKEDITOR.instances['textarea_name']) {
CKEDITOR.instances['textarea_name'].destroy(true);
}
(使用带有jQuery适配器的3.6.2版本)
答案 10 :(得分:2)
您可以通过删除ckeditor的方法删除任何ckeditor实例。实例将是textarea的id或名称。
if (CKEDITOR.instances[instance_name]) {
CKEDITOR.remove(CKEDITOR.instances[instance_name]);
}
答案 11 :(得分: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
});
答案 12 :(得分: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结构。
答案 13 :(得分:2)
CKEDITOR.instances = new Array();
我在调用之前使用它来创建一个实例(每页加载一次)。不知道这会如何影响内存处理,什么不会。这只有在您想要替换页面上的所有实例时才有效。
答案 14 :(得分:1)
我处于必须控制生成对话框的情况下,每个对话框都需要嵌入一个ckeditor。事实上,文本区域共享相同的ID。 (通常这是非常糟糕的做法,但我有2个jqGrids,一个已分配的项目和另一个未分配的项目。)它们共享几乎相同的配置。因此,我使用通用代码来配置它们。
所以,当我从jqGrid加载一个对话框,添加行或编辑它们时;我必须删除所有textareas中的所有CKEDITOR实例。
$('textarea').each(function()
{
try
{
if(CKEDITOR.instances[$(this)[0].id] != null)
{
CKEDITOR.instances[$(this)[0].id].destroy();
}
}
catch(e)
{
}
});
这将循环遍历所有textareas,如果有CKEDITOR实例,则将其销毁。
或者,如果你使用纯jQuery:
$('textarea').each(function()
{
try
{
$(this).ckeditorGet().destroy();
}
catch(e)
{
}
});
答案 15 :(得分:1)
我选择重命名所有实例而不是destroy / replace - 因为有时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];
}
}
答案 16 :(得分:1)
删除class="ckeditor"
,它可能已触发ckeditor初始化
答案 17 :(得分:1)
我遇到了与jQuery Dialog相同的问题。
如果您只想删除以前的数据,为什么要销毁实例?
function clearEditor(id)
{
var instance = CKEDITOR.instances[id];
if(instance)
{
instance.setData( '' );
}
}
答案 18 :(得分:1)
确实,从代码中删除“.ckeditor”类可以解决问题。我们大多数人都遵循ckeditor文档中的jQuery集成示例:
$('.jquery_ckeditor')
.ckeditor( function() { /* callback code */ }, { skin : 'office2003' } );
并且想“......也许我可以摆脱或'.jquery_'部分”。
我一直在浪费时间调整回调函数(因为{skin:'office2003'}实际上有效),而问题来自其他地方。
我认为文档应该提到不推荐使用“ckeditor”作为类名,因为它是一个保留关键字。
干杯。
答案 19 :(得分:1)
我了解到了
删除CKEDITOR.instances [editorName];
本身,实际上删除了实例。我读过和看过的所有其他方法,包括在其用户的stackoverflow中找到的内容,对我来说都不起作用。
在我的情况下,我使用ajax调用来拉取包含在和的内容的副本。问题恰巧是因为我使用jQuery .live事件来绑定“编辑此文档”链接,然后在ajax加载成功后应用ckeditor实例。这意味着,当我点击另一个链接与另一个.live事件的链接时,我必须使用删除CKEDITOR.instances [editorName]作为清除内容窗口(保存表单)的任务的一部分,然后重新获取所持有的内容在数据库或其他资源中。
答案 20 :(得分:0)
试试这个:
for (name in CKEDITOR.instances)
{
CKEDITOR.instances[name].destroy(true);
}
答案 21 :(得分:0)
如果您知道编辑器的名称,那么这样做很简单。
例如,如果编辑器的名称为editor1 (this is the id of div or textarea)
,则只需像这样检查
if(CKEDITOR.instances['editor1']){
// Instance present
}else{
// Instance not present
}
如果要获取已初始化的编辑器的数量,请执行以下操作
for(let inst of CKEDITOR.instances){
// inst is an Obj of editor instance
// inst.name will give the name of the editor instance
}
答案 22 :(得分:0)
CKeditor 4.2.1
这里有很多答案,但对我来说我需要更多的东西(有点脏,所以如果有人可以提高请做)。对我来说,我的问题是MODAL。
我使用Foundation在模式中渲染CKEditor。理想情况下,我会在关闭时让编辑失去理智,但我不想惹恼基金会。
我打电话给删除,我尝试删除和另一种方法,但这是我最终解决的问题。
我使用的是textarea来填充DIV。
我的解决方案
//hard code the DIV removal (due to duplication of CKeditors on page however they didn't work)
$("#cke_myckeditorname").remove();
if (CKEDITOR.instances['myckeditorname']) {
delete CKEDITOR.instances['myckeditorname'];
CKEDITOR.replace('myckeditorname', GetCKEditorSettings());
} else {
CKEDITOR.replace('myckeditorname', GetCKEditorSettings());
}
这是我返回特定格式的方法,您可能不需要。
function GetCKEditorSettings()
{
return {
linkShowAdvancedTab: false,
linkShowTargetTab: false,
removePlugins: 'elementspath,magicline',
extraAllowedContent: 'hr blockquote div',
fontSize_sizes: 'small/8px;normal/12px;large/16px;larger/24px;huge/36px;',
toolbar: [
['FontSize'],
['Bold', 'Italic', 'Underline', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink'],
['Smiley']
]
};
}
答案 23 :(得分:0)
这个函数适用于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);
答案 24 :(得分:0)
非常简单。在我的例子中,我运行了下面的jquery方法,该方法将在页面加载期间销毁ckeditor实例。这样就解决了问题 -
JQuery方法 -
function resetCkEditorsOnLoad(){
for(var i in CKEDITOR.instances) {
editor = CKEDITOR.instances[i];
editor.destroy();
editor = null;
}
}
$(function() {
$(".form-button").button();
$(".button").button();
resetCkEditorsOnLoad(); // CALLING THE METHOD DURING THE PAGE LOAD
.... blah.. blah.. blah.... // REST OF YOUR BUSINESS LOGIC GOES HERE
});
就是这样。我希望它可以帮助你。
干杯, Sirish。
答案 25 :(得分:0)
这是jquery .load()api和ckeditor的完全正常工作的代码,在我的情况下,我将带有ckeditor的页面加载到具有一些jquery效果的div中。我希望它会对你有所帮助。
$(function() {
runEffect = function(fileload,lessonid,act) {
var selectedEffect = 'drop';
var options = {};
$( "#effect" ).effect( selectedEffect, options, 200, callback(fileload,lessonid,act) );
};
function callback(fileload,lessonid,act) {
setTimeout(function() {//load the page in effect div
$( "#effect" ).load(fileload,{lessonid:lessonid,act:act});
$("#effect").show( "drop",
{direction: "right"}, 200 );
$("#effect").ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) {
loadCKeditor(); //call the function after loading page
});
}, 100 );
};
function loadCKeditor()
{//you need to destroy the instance if already exist
if (CKEDITOR.instances['introduction'])
{
CKEDITOR.instances['introduction'].destroy();
}
CKEDITOR.replace('introduction').getSelection().getSelectedText();
}
});
===================== button for call the function ================================
<input type="button" name="button" id="button" onclick="runEffect('lesson.php','','add')" >
答案 26 :(得分:0)
对于那些使用jquery“适配器”而且遇到麻烦的人(就像我一样),因为超级hackish但工作解决方案是做这样的事情:
// content editor plugin
(function($){
$.fn.contentEditor = function( params ) {
var xParams = $.extend({}, $.fn.contentEditor.defaultParams, params);
return this.each( function() {
var $editor = $(this);
var $params = $.extend({}, xParams, $editor.data());
// if identifier is set, detect type based on identifier in $editor
if( $params.identifier.type ) {
$params.type = $editor.find($params.identifier.type).val();
}
$editor.data('type', $params.type);
// edit functionality
editButton = $('<button>Edit Content</button>').on('click',function(){
// content container
var $cc = $('#' + $editor.data('type'));
// editor window
var $ew = $('<form class="editorWindow" />');
$ew.appendTo('body');
// editor content
$ec = $('<textarea name="editorContent" />').val($cc.html());
$ec.appendTo($ew);
$ec.ckeditor();
//$ec.ckeditorGet().setMode('source');
$ew.dialog({
"autoOpen": true,
"modal": true,
"draggable": false,
"resizable": false,
"width": 850,
"height": 'auto',
"title": "Content Editor",
"buttons": {
'Save': function() {
$cc.html( $ec.val() );
$ec.ckeditorGet().destroy();
$ew.remove();
},
'Cancel / Close': function() {
$ec.ckeditorGet().destroy();
$ew.remove();
}
},
'close': function() {
$ec.ckeditorGet().destroy();
},
'open': function() {
$ew.find('a.cke_button_source').click();
setTimeout(function(){
$ew.find('a.cke_button_source.cke_on').click();
}, 500);
}
});
return false;
});
editButton.appendTo( $editor );
});
}
// set default option values
$.fn.contentEditor.defaultParams = {
'identifier': {
'type': 'input[name="type"]'
}
};
})(jQuery);
$(function(){
$('form.contentEditor').contentEditor();
});
这一部分的关键点是:
'open': function() {
$ew.find('a.cke_button_source').click();
setTimeout(function(){
$ew.find('a.cke_button_source.cke_on').click();
}, 500);
}
这解决了下次打开对话框时编辑器文本无法显示的问题。我意识到这是非常hackish,但考虑到其中大部分将用于管理工具,我不认为这是通常会有的大问题..这是有效的,所以希望它会节省一些人时间;)
答案 27 :(得分:0)
我碰到了同样的事情,问题是wordcount插件花了太长时间来初始化。 30秒以上。用户将点击显示ckeditor的视图,然后取消,从而将新页面加载到dom中。这个插件很抱怨,因为当它准备好将自己添加到contentWindow时,iframe或任何contentWindow所指向的内容都不再可见。您可以通过单击视图然后等待编辑器右下方显示字数来验证这一点。如果你现在取消,你就不会有问题。如果你不等它,你将得到i.contentWindow为null错误。要修复它,只需废弃插件:
if (CKEDITOR.instances['textarea_name'])
{
CKEDITOR.instances['textarea_name'].destroy();
}
CKEDITOR.replace('textarea_name', { removePlugins: "wordcount" } );
如果您需要一个字计数器,请在编辑器上注册粘贴和键盘事件,并使用一个计算单词的函数。
答案 28 :(得分:0)
我有像jackboberg一样的问题。我使用动态表单加载到jquery对话框然后附加各种小部件(datepickers,ckeditors等...)。 我尝试了上面提到的所有解决方案,但没有一个能为我工作。
由于某些原因,ckeditor仅在我第一次加载表单时附加,第二次我得到了与jackboberg完全相同的错误消息。
我已经分析了我的代码并发现如果你在“半空”中附加ckeditor,那么当表单内容仍未放入对话框时,ckeditor将无法正确附加其绑定。那是因为ckeditor附加在“半空中”,第二次将它附加在“半空中”......噗......由于第一个实例没有从DOM中正确删除,所以会抛出错误。
这是我的代码,它产生了错误:
var $content = $(r.content); // jQuery can create DOM nodes from html text gotten from <xhr response> - so called "mid-air" DOM creation
$('.rte-field',$content).ckeditor(function(){});
$content.dialog();
这是有效的解决方法:
var $content = $(r.content).dialog(); // first create dialog
$('.rte-field',$content).ckeditor(function(){}); // then attach ckeditor widget
答案 29 :(得分:0)
支持动态(Ajax)加载表单(没有页面刷新),其中包含相同的textareas(再次调用相同的表单)或不同的ID(以前卸载的表单)并将它们转换为CKEditor元素,我做了以下(使用JQuery适配器):
页面完成每个传递textarea的Ajax调用后,我调用以下函数:
setupCKeditor()
这看起来像这样(它假设您的textareas转换为RTE的 class =“yourCKClass”):
/* Turns textAreas into TinyMCE Rich Text Editors where
* class: tinymce applied to textarea.
*/
function setupCKeditor(){
// define editor configuration
var config = {skin : 'kama'};
// Remove and recreate any existing CKEditor instances
var count = 0;
if (CKEDITOR.instances !== 'undefined') {
for(var i in CKEDITOR.instances) {
var oEditor = CKEDITOR.instances[i];
var editorName = oEditor.name;
// Get the editor data.
var data = $('#'+editorName).val();
// Check if current instance in loop is the same as the textarea on current page
if ($('textarea.yourCKClass').attr('id') == editorName) {
if(CKEDITOR.instances[editorName]) {
// delete and recreate the editor
delete CKEDITOR.instances[editorName];
$('#'+editorName).ckeditor(function() { },config);
count++;
}
}
}
}
// If no editor's exist in the DOM, create any that are needed.
if (count == 0){
$('textarea.yourCKClass').each( function(index) {
var editorName = $(this).attr('id');
$('#'+editorName).ckeditor(function() { $('#'+editorName).val(data); },config);
});
}
}
我应该提一下:
$('#'+editorName).ckeditor(function() { $('#'+editorName).val(data); },config);
可以(而且应该)简单地说:
$('#'+editorName).ckeditor(function() { },config);
然而,我发现编辑器经常会在加载后显示正确的内容一秒钟,并清空所需内容的编辑器。因此,具有回调代码的那一行强制CKEditor内容与原始textarea内容相同。使用时会产生闪烁。如果您可以避免使用它,请执行此操作。
答案 30 :(得分:0)
我遇到了同样的问题,我收到了一个空引用异常,并且“null”这个词会在编辑器中显示。我尝试了一些解决方案,包括将编辑器升级到3.4.1无济于事。
我最终不得不编辑源代码。在_source \ plugins \ wysiwygarea \ plugin.js的第416到426行,有一个这样的片段:
iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + ... + '></iframe>' );
至少在FF中,iframe在需要时并未完全实例化。我使用setTimeout函数在该行之后包围了函数的其余部分:
iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + ... + '></iframe>' );
setTimeout(function()
{
// Running inside of Firefox chrome the load event doesn't bubble like in a normal page (#5689)
...
}, 1000);
};
// The script that launches the bootstrap logic on 'domReady', so the document
...
文本现在在模态对话框中一致呈现。
答案 31 :(得分:-1)
你不需要销毁对象CKeditor,你需要删除():
改变这个:
CKEDITOR.instances['textarea_name'].destroy();
为此:
CKEDITOR.remove(CKEDITOR.instances['textarea_name']);