views:

6709

answers:

6

I am using jquery dialogs to present forms (fetched via AJAX). On some forms I am using a CKEditor for the textareas. The editor displays fine on the first load.

When the user cancels the dialog, I am removing the contents so that they are loaded fresh on a later request. The issue is, once the dialog is reloaded, the CKEditor claims the editor already exists.

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

The API includes a method for destroying existing editors, and I have seen people claiming this is a solution:

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

This is not working for me, as I receive a new error instead:

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

This error seems to occur on the "destroy()" rather than the "replace()". Has anyone experienced this and found a different solution?

Is is possible to 're-render' the existing editor, rather than destroying and replacing it?

UPDATED Here is another question dealing with the same problem, but he has provided a downloadable test case.

A: 

Perhaps this will help you out - I've done something similar using jquery, except I'm loading up an unknown number of ckeditor objects. It took my a while to stumble onto this - it's not clear in the documentation.

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

And here is what I run to get the content from the editors:

    var $editors = $("textarea.ckeditor");
    if ($editors.length) {
        $editors.each(function() {
            var instance = CKEDITOR.instances[$(this).attr("id")];
            if (instance) { $(this).val(instance.getData()); }
        });
    }
ScottE
This seems to have removed the errors, but on the second rendering the textarea now contains 'null' and I can no longer interact with the toolbar or the textarea. If I do click on toolbar buttons I receive errors like: "TypeError: Result of expression 'this.$.focus' [undefined] is not a function" -or- "TypeError: Result of expression 'this.document.getWindow().$' [undefined] is not an object". Where/when do you call that function? I have my script inline with the jquery loaded content. (ckeditor.js in the head of the parent html)
jackboberg
I call this after all textareas have been added to the page and filled with content.
ScottE
+1  A: 

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

madhaviaddanki
+2  A: 
function loadEditor(id)
{
    var instance = CKEDITOR.instances[id];
    if(instance)
    {
        CKEDITOR.remove(instance);
    }
    CKEDITOR.replace(id);
}
Jim
This caused me a bit of grief, but your solution helped out. Thanks!
Ben Scheirman
I had a similar problem in firefox which had three instances of the CKEditor on the page, the first one was not displaying but the other two where, I added the above code and all teh editors now appear
Craig Angus
Don't use CKEDITOR.remove because it only clears the element from the array, but leaves all the DOM in memory. It's stated in the docs that it's meant for internal use: http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.html#.remove You should use instead instace.destroy() as madhaviaddanki said.
AlfonsoML
+1  A: 

This is the simplest (and only) solution that worked for me:

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

Deleting this entry in the array prevents this form safety check from destroying your application.

destroy() and remove() did not work for me.

adu
This is the only solution that worked with me also, thanks for posting it!
Michael Robinson
I did get destroy() to work. But neither `delete` or `destroy()` fully clean up the editor instance. Things like the dictionary and other associated objects will still lurk around.
adu
A: 

Hi,

I had this problem too, but I solved it in a much simpler way...

I was using the class ".ckeditor" in the jQuery as the selector for which textares's I wanted ckeditorized.

The default ckeditor js you include before the also uses this class to identify which textareas to ckeditorized. This means both your jQuery ckeditor function and the default ckeditor js are trying to run on the textarea.

What you need to do is simply change the class of the jQuery, I use '.do_ckeditor' and remove the 'ckeditor' class from your html.

I was pulling my hair out about this and felt the need to come back and post my answer.

Hope this helps.

Smickie
A: 

Indeed, removing the ".ckeditor" class from your code solves the issue. Most of us followed the jQuery integration example from the ckeditor's documentation:

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

and thought "... maybe I can just get rid or the '.jquery_' part".

I've been wasting my time tweaking the callback function (because the {skin:'office2003'} actually worked), while the problem was coming from elsewhere.

I think the documentation should mention that the use of "ckeditor" as a class name is not recommended, because it is a reserved keyword.

Cheers.

ramkam