CKEditor实例已经存在
我正在使用jQuery对话框来呈现窗体(通过AJAX提取)。 在某些forms上,我正在使用texEdre的CKEditor。 编辑器在第一次加载时显示正常。
当用户取消对话框时,我将删除内容,以便在稍后的请求中加载新内容。 问题是,一旦对话框重新加载,CKEditor声称编辑器已经存在。
uncaught exception: [CKEDITOR.editor] The instance "textarea_name" already exists.
这个API包括一个销毁现有编辑器的方法,而且我看到有人声称这是一个解决scheme:
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()”上。 有没有人经历过这个,find了不同的解决scheme
有可能“重新渲染”现有的编辑器,而不是销毁和replace它?
更新 这里是另一个问题处理同样的问题,但他提供了一个可下载的testing用例 。
为了这个工作,你需要在销毁实例时传递布尔参数true :
var editor = CKEDITOR.instances[name]; if (editor) { editor.destroy(true); } CKEDITOR.replace(name);
function loadEditor(id) { var instance = CKEDITOR.instances[id]; if(instance) { CKEDITOR.remove(instance); } CKEDITOR.replace(id); }
我也有这个问题,但是我用一种更简单的方法解决了这个问题。
我在我的jQuery脚本中使用类“ckeditor”作为我想用于CKEditor的textareas的select器。 默认的ckeditor JS脚本也使用这个类来标识CKEditor使用哪个textareas。
这意味着我的jQuery脚本和默认ckeditor脚本之间有冲突。
我只是把textarea的类和我的jQuery脚本改成了“do_ckeditor”(你可以使用除“ckeditor”以外的任何东西),它的工作。
这是为我工作的最简单(也是唯一的)解决scheme:
if(CKEDITOR.instances[editorName]) delete CKEDITOR.instances[editorName]; CKEDITOR.replace(editorName);
在数组中删除这个条目可以防止这种forms的安全检查破坏你的应用程序。
destroy()和remove()对我不起作用。
也许这将帮助你 – 我已经做了类似的使用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()意味着是内部的,并且在一个点上logging不当。
我有类似的问题,我们正在做一些CKeditor的实例通过ajax加载的内容。
CKEDITOR.remove()
保持内存中的DOM,并没有删除所有的绑定。
CKEDITOR.instance [INSTANCE_ID] .destroy()
每当我使用来自ajax的新数据创build新实例时,发生错误i.contentWindow错误。 但是直到我发现在清除DOM之后我才销毁这个实例。
在页面上存在实例和DOM的时候使用destroy() ,那么它工作的很好。
var e= CKEDITOR.instances['sample']; e.destroy(); e= null;
对于Ajax请求,
for(k in CKEDITOR.instances){ var instance = CKEDITOR.instances[k]; instance.destroy() } CKEDITOR.replaceAll();
这剪去了文档中的所有实例。 然后创build新的实例。
i.contentWindow is null
错误似乎发生时调用一个编辑器实例绑定到一个textarea不再在DOM中的销毁。
CKEDITORY.destroy
采用参数noUpdate
。
APIdoc指出:
如果实例正在replaceDOM元素,则此参数指示是否更新具有实例内容的元素。
所以,为了避免这个错误,可以在从DOM中删除textarea元素之前调用destroy,或者调用destory(true)来避免尝试更新不存在的DOM元素。
if (CKEDITOR.instances['textarea_name']) { CKEDITOR.instances['textarea_name'].destroy(true); }
(使用版本3.6.2与jQuery适配器)
您可以通过删除ckeditor的方法删除任何ckeditor实例。 实例将是textarea的id或名称。
if (CKEDITOR.instances[instance_name]) { CKEDITOR.remove(CKEDITOR.instances[instance_name]); }
这对我来说是有效的:
for(name in CKEDITOR.instances) { CKEDITOR.instances[name].destroy() }
CKEDITOR.instances = new Array();
我在调用之前使用这个来创build一个实例(每页加载一个)。 不知道这是如何影响内存处理,什么不是。 这只会在你想要replace页面上的所有实例时才起作用。
我已经准备好了基于上述所有代码的解决scheme。
$("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结构。
我遇到了与实例相同的问题,我到处寻找,最后这个实现对我有用:
//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 });
我了解到
删除CKEDITOR.instances [editorName];
本身实际上删除了该实例。 我已阅读和看到的所有其他方法,包括从它的用户在这里find的stackoverflow,没有为我工作。
在我的情况下,即时通讯使用ajax调用拉和包装的内容的副本。 问题发生的原因是因为我正在使用jQuery .live事件绑定“编辑此文档”链接,然后在ajax加载成功后应用ckeditor实例。 这意味着,当我点击另一个链接与另一个.live事件的链接时,我必须使用删除CKEDITOR.instances [editorName]作为我的任务清理内容窗口(持有表单)的一部分,然后重新抓取内容在数据库或其他资源。
我讨厌与jQuery对话框相同的问题。
为什么要删除实例,如果你只是想删除以前的数据?
function clearEditor(id) { var instance = CKEDITOR.instances[id]; if(instance) { instance.setData( '' ); } }
我select重命名所有的实例,而不是销毁/replace – 因为有时AJAX加载的实例并不真正取代页面核心的实例…保持更多的内存,但这样less的冲突。
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]; } }
我处于这种情况下,我必须控制产生的对话框,他们每个人都需要在这些对话框中embedded一个ckeditor。 而恰恰相反,文本区域共享相同的ID。 (通常这是非常糟糕的做法,但我有2 jqGrids,其中一个分配的项目和另一个未分配的项目。)他们共享几乎相同的configuration。 因此,我使用通用代码来configuration两者。
所以,当我加载一个对话框,添加行或编辑它们,从任何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) { } });
删除class="ckeditor"
,它可能已经触发ckeditor初始化
事实上,从代码中删除“.ckeditor”类可以解决这个问题。 我们大多数人都遵循ckeditor文档中的jQuery集成示例:
$('.jquery_ckeditor') .ckeditor( function() { /* callback code */ }, { skin : 'office2003' } );
并认为“…也许我可以摆脱或”.jquery_“部分”。
我一直在浪费时间调整callback函数(因为{skin:'office2003'}实际上工作),而问题来自其他地方。
我认为文档应该提到,不推荐使用“ckeditor”作为类名,因为它是一个保留关键字。
干杯。
我遇到了同样的问题,我收到一个空引用exception,并在编辑器中显示“空”字。 我尝试了一些解决scheme,包括升级编辑器到3.4.1无济于事。
我最终不得不编辑源代码。 在_source \ plugins \ wysiwygarea \ plugin.js的第416到426行,有一个这样的代码片段:
iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + ... + '></iframe>' );
至less在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 ...
现在,文本在modal dialog中呈现一致。
为了支持包含textareas(重新调用相同的表单)或不同的ID(之前卸载的表单)的dynamic(Ajax)加载表单(无页面间刷新),并将它们转换为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);
但是我发现编辑器在加载后经常会显示正确的内容,并清空所需内容的编辑器。 因此,使用callback代码的行强制CKEditor内容与原始textarea内容相同。 使用时会导致闪烁。 如果你可以避免使用它,那么这样做..
我有像jackboberg一样的问题。 我使用dynamic表单加载到jQuery对话框中,然后附加各种小部件(dateselect器,ckeditors等)。 我尝试了上面提到的所有解决scheme,但都没有为我工作。
由于某种原因,ckeditor只附加了我第一次加载表单,第二次我得到了完全相同的错误信息jackboberg做的。
我已经分析了我的代码,发现如果将ckeditor附加到“mid-air”,即表单内容尚未放入对话框中,ckeditor将不会正确附加其绑定。 那是因为ckeditor是在“半空中”附加的,第二次是在“半空中”附加的… poof …由于第一次没有正确删除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
我遇到了这个完全相同的事情,问题是wordcount插件花了太长的时间来初始化。 30+秒。 用户可以点击显示ckeditor的视图,然后取消,从而将一个新的页面加载到dom中。 该插件抱怨,因为iframe或contentWindow指向的任何内容已准备好添加到contentWindow时不再可见。 您可以通过点击您的视图来validation这一点,然后等待字数出现在编辑器的右下angular。 如果你现在取消,你不会有问题。 如果你不等它,你会得到i.contentWindow为空的错误。 要解决这个问题,只需要删除插件:
if (CKEDITOR.instances['textarea_name']) { CKEDITOR.instances['textarea_name'].destroy(); } CKEDITOR.replace('textarea_name', { removePlugins: "wordcount" } );
如果您需要一个字计数器,请在编辑器中注册粘贴和键入事件,并使用计数字的function。
对于那些使用jQuery的“适配器”,并有麻烦(因为我是),作为超级hackish但工作的解决scheme是做这样的事情:
// 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); }
这解决了编辑器文本在下次打开对话框时不可见的问题。 我意识到这是非常黑客,但考虑到其中大部分将被用于pipe理工具,我不认为这是一个大的问题,因为它通常会..这个工程,所以希望它可以节省一些一些时间 ;)
这是jquery .load()api和ckeditor的完整工作代码,在我的情况下,我加载一个页面与ckeditor到div与一些jQuery的影响。 我希望这会帮助你。
$(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')" >
它非常简单。 在我的情况下,我运行了下面的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 });
而已。 我希望它可以帮助你。
干杯,干杯。
这个函数在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);
CKeditor 4.2.1
这里有很多答案,但对我来说,我需要更多的东西(有点太脏,所以如果有人可以改善,请做)。 对于我MODALs我的问题。
我使用Foundation来渲染CKEditor。 理想情况下,我会在编辑结束时使其失效,但是我不想与基金会混淆。
我叫删除,我试图删除和另一种方法,但这是我最终解决了。
我正在使用textarea的填充不DIVs。
我的解决scheme
//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'] ] }; }
尝试这个:
for (name in CKEDITOR.instances) { CKEDITOR.instances[name].destroy(true); }