views:

9736

answers:

8

Hey guys, I have this custom written CMS that uses CKEditor *(FCKEditor v3) for editing content. Along with that I'm using the jQuery Validation plugin to check all fields for error prior to ajax-based submission. For passing on the data to the PHP backend, I'm using the serialize() function.

Problem is, serialize manages to grab all other fields correctly, except for the actual content typed in CKEditor. Like every other WYSIWYG editor, this one too overlays an iframe over an existing textbox. And serialize ignores the iframe and looks only into the textbox for content... which of course, it doesn't find - thus returning a blank content body.

My approach to this is to create a hook onto the onchange event of CKEditor and concurrently update the textbox (CKEDITOR.instances.[textboxname].getData() returns the content) or some other hidden field with any changes made in the editor.

However, since CKEditor is still in it's beta stage and severely lacks documentation, I cannot seem to find a suitable API call that'll enable me to do so.

Does anyone have any idea on how to go about this? Or maybe suggest even a better method?

+2  A: 

This should do it...

CKEDITOR.instances["editor1"].document.on('keydown', function(event)
{
    CKEDITOR.tools.setTimeout( function()
    { 
        $("#editor1").val(CKEDITOR.instances.editor1.getData()); 
    }, 0);
});

CKEDITOR.instances["editor1"].document.on('paste', function(event)
{
    CKEDITOR.tools.setTimeout( function()
    { 
        $("#editor1").val(CKEDITOR.instances.editor1.getData()); 
    }, 0);
});

edit: added section to update textbox after pastes, too...

Stobor
Thanks for your reply... but it keeps telling me: "CKEDITOR.instances.editor1.document is undefined" !!
miCRoSCoPiC_eaRthLinG
BTW, can you please explain why you're using a setTimeout here and not just copying over the content directly upon keystroke?
miCRoSCoPiC_eaRthLinG
replace editor1 by your textboxname. The setTimeout is to make sure we get the contents _after_ the pressed key is added, rather than before.
Stobor
+3  A: 

I have also been trying to fix this problem today. I realised that the reason the above code isnt working for me is because the CKEditor instance isnt ready yet when the document property is referenced. So you have to call the "instanceReady" event and within that the document's events can be used, because prior to that it just doesnt exist.

This example might work for you:

CKEDITOR.instances["editor1"].on("instanceReady", function()
{
//set keyup event
this.document.on("keyup", CK_jQ);

 //and paste event
this.document.on("paste", CK_jQ);
}

function CK_jQ()
{

    CKEDITOR.tools.setTimeout( function()
    { 
        $("#editor1").val(CKEDITOR.instances.editor1.getData()); 
    }, 0);
}
Seb Woolford
Thanks to all of you :) The combined code did the trick...
miCRoSCoPiC_eaRthLinG
A: 

I've been trying all night to get this to work but it isn't working yet. Could you please explain where you placed this script?

I am generating my page from an xquery so I can't put this script in the page because it contains "{" which breaks the xquery processing. Putting the script in cdata breaks the script. So I put the on instanceReady listener in the same script that is creating the editor and called an external script to add the rest. eg:

<script type="text/javascript">
  var editor = CKEDITOR.replace( 'editor1' );
  editor.on("instanceReady", updateInstance() )
</script>

then updateInstance contains:

function updateInstance()
{
CKEDITOR.instances["editor1"].document.on('keydown', function(event)
{
    CKEDITOR.tools.setTimeout( function()
    { 
        $("#editor1").val(CKEDITOR.instances.editor1.getData()); 
    }, 0);
});

CKEDITOR.instances["editor1"].document.on('paste', function(event)
{
    CKEDITOR.tools.setTimeout( function()
    { 
        $("#editor1").val(CKEDITOR.instances.editor1.getData()); 
    }, 0);
});

}
Fraser
For a follow-up question like this it would be better to ask it as a new question ("Ask Question" button in the top right of the page), not post it here in an old thread. More people would see it and try to solve your problem...
sth
Ok thanks, new to this site and wasn't sure how it works. I'll delete from here and repost as a new question.
Fraser
Ok I solved my problem. I was mixing xquery and javascript code and didn't properly escape the {. Works nicely now. Thanks for the solution!!
Fraser
+3  A: 

I've just released a CKEditor plugin for jQuery which will take care of all this in the background without any extra code: http://www.fyneworks.com/jquery/CKEditor/

Diego A.
Cool stuff. Thanks. That sure makes it easy.
miCRoSCoPiC_eaRthLinG
Does this plugin still work for the new CKEDITOR?
AnApprentice
A: 

I took a slightly different approach I figured it would be better to use ckeditor's update function and since keyup was being used the timeout wasn't needed

CKEDITOR.instances["editor1"].on("instanceReady", function()
{
//set keyup event
this.document.on("keyup", CK_jQ);

 //and paste event
this.document.on("paste", CK_jQ);
}

function CK_jQ()
{
   CKEDITOR.instances.editor1.updateElement(); 
}
mcgrailm
+6  A: 

Another generic solutions to this would be to run the following whenever you try to submit the form

for ( instance in CKEDITOR.instances )
            CKEDITOR.instances[instance].updateElement();

This will force all CKEDITOR instances in the form to update their respective fields

Gaby
+1  A: 

I had success with this:

console.log(CKEDITOR.instances.editor1.getData());
a.m.
+1  A: 

Wouldn't it be better to do just this:

CKEDITOR.instances.editor1.on('contentDom', function() { CKEDITOR.instances.editor1.document.on('keyup', function(event) {/your instructions/}); });

ref: http://cksource.com/forums/viewtopic.php?f=11&amp;t=18286

netfed