AnApprentice
AnApprentice

Reputation: 110960

CKEditor, AJAX Save

Can you provide an example on how to setup CKEditor to save via AJAX using the Save button in the CKEditor toolbar?

I'm interested in creating a CKEditor AJAX save page but am not seeing any examples on their site.

Thanks!

Upvotes: 6

Views: 29408

Answers (10)

Phil
Phil

Reputation: 131

This is the method I use, no plugins required:

It's simple and reliable and uses the CKEditors built in save button.

Add a non-visible submit button (display:none) to the same form where the CKEditor is and set it's ID and Name to "submit" then both the input's onclick and the forms onsubmit will both be executed when the CKEditor's standard save button is clicked. you can hook up your event handlers inline or with jquery.bind() or any other way. Then add a function attached to the forms onsubmit event to serialize the form and ajax post it to the url set in the form 'action' attribute. Just return 'False' from the event handler to ensure the form does not post. Now any code or button (including the ckeditor save button) that submits the form will run your handler instead. No CKeditor plugins or CKeditor configuration required. Here's a simplified example (assumes JQuery ).

<form id="myform" name="myform" action="" method="post" onsubmit="alert('form.onsubmit()');return false;">
<input type="submit" id="submit" name="submit" style="display:none" onclick="SaveText(this);"/>
<textarea id="ckeditor1"></textarea>
</form>

<script>
function SaveText (eventargs){
   var form = $(eventargs).closest("form");
   var data = form.serialize();
   var url = form.attr('action');
$.post(url, data);
return false;
}
</script>

A more realistic approach might use JQuery.Bind() and the script would be in an external JS file etc. but the end result is the same. It works because the input hides the form's submit function so any call to form.submit() calls the submit button's onclick() function instead (std behavior for all browsers). Because it's a 'submit' button it causes the form's 'onsubmit' event to fire which would not normally happen if you called form.submit() directly. so you get reliable loosely coupled interception of the save event without plugins or using the CKEditor API. you can use it for more than ajax save too, its nice for any pre-save processing you need to do.

Upvotes: 4

Grim
Grim

Reputation: 1986

If you have no html-form around the element you may notice that initially the button is disabled, this behave is unfortunately hardcoded. To enable it you must change the state of the button.

This is my code:

<script>
    function editor(domElement, callback){
        var editor = CKEDITOR.replace(domElement);
        // save-command currently unavailable because we have no form.
        editor.on('instanceReady',function(){
            // find the save-command
            var command = editor.getCommand('save');
            // set the initail state to enabled/unpressed
            command.setState(CKEDITOR.TRISTATE_OFF);
            // overwrite the exec-command
            command.exec = function (){
                var newHtml = editor.getData();
                callback(newHtml);
                editor.destroy();
            }
        });
    }
</script>

Upvotes: 0

Hemant Maurya
Hemant Maurya

Reputation: 174

 <textarea cols="80" id="editor1" name="editor1" rows="10"></textarea>

 <button id="save" onclick="save()"></button>

 <script type="text/javascript">
         function save() {

             var question = CKEDITOR.instances.editor1.getData();
             alert(question);

             $.ajax({
                type: 'POST',
                data: {file: question},
                url: "aiq_save.php?xyz="+question+"",
                success: function (html) {
                    alert('may be saved');
                    $("#show").html(html);
                }
            });
            return false;
 </script> 

 <div id="show"></div>

Create a new page aiq_save.php, then:

<?php
    ECHO  $_GET['xyz'];

    ECHO $_POST['file'];//post method
?>

And you've done it.

Upvotes: 0

Korikulum
Korikulum

Reputation: 2599

You can use the beforeCommandExec event & cancel() method:

<script type="text/javascript">
$(document).ready(function () {

    $('.ckeditoriz').ckeditor(/* config */);

    $('.ckeditoriz').each(function () {
        var id = $(this).attr('id'),
            form = this.form;

        CKEDITOR.instances[id].on('beforeCommandExec', function (event) {
            if (event.data.name === 'save') {
                event.cancel();
                $(form).submit();
            }
        });

    });

    $('.ajaxForm').submit(function (event) {
        event.preventDefault();
        var $this = $(this);
        $.ajax({
            type: $this.attr('method'),
            url: $this.attr('action'),
            data: $this.serialize()
        });
    });

});
</script>

<form action="url" method="post" class="ajaxForm">
  <!-- Your textarea must have an ID! -->
  <textarea id="textarea1" name="textarea1" class="ckeditoriz"></textarea>
</form>

Update:

This doesn't work in CKEditor versions 4.0, 4.1, 4.2, however it works again since version 4.3.

Since CKEditor version 4.2 you can use the save event with the cancel() method:

CKEDITOR.instances[id].on('save', function (event) {
    event.cancel();
    $(form).submit();
});

Upvotes: 8

Matthew
Matthew

Reputation: 6609

Lots of answers already but I think my solution is way easier and cleaner than everything here so far. This will simply override the existing save button's functionality with javascript that you specify with ckeditor 4:

html:

<textarea id="CKEditor1"></textarea>

javascript:

<script>
    // Need to wait for the ckeditor instance to finish initialization
    // because CKEDITOR.instances.editor.commands is an empty object
    // if you try to use it immediately after CKEDITOR.replace('editor');
    CKEDITOR.on('instanceReady', function (ev) {

        // Create a new command with the desired exec function
        var overridecmd = new CKEDITOR.command(editor, {
            exec: function(editor){
                // Replace this with your desired save button code
                alert(editor.document.getBody().getHtml());
            }
        });

        // Replace the old save's exec function with the new one
        ev.editor.commands.save.exec = overridecmd.exec;
    });

    CKEDITOR.replace('CKEditor1');

</script>

Upvotes: 3

Dmitry
Dmitry

Reputation: 7266

I've tried Korikulum's method on CKEditor 4 but it posts the form twice so I've come up with this:

$(function () {
    setTimeout(function () {
        CKEDITOR.instances.MyEditor.on('beforeCommandExec', function (event) {
            if (event.data.name === 'save') {
                event.cancel();//this does not seem to prevent the form post
                $(MyEditor).val(CKEDITOR.instances.MyEditor.getData());//copy data from the editor to the textarea
                $.ajax({
                    type: $(editorForm).attr('method'),
                    url: $(editorForm).attr('action'),
                    data: $(editorForm).serialize(),
                    success: function (data) {
                        alert(data.message);
                    }
                });
            }
        });
    }, 100);//CKEditor is heavy and needs time to initialize

    editorForm.submit = function (e) {//this is needed to prevent the 2nd post
        return false;
    };
});

MyEditor is the id of the text area with ckeditor class

editorForm is the id of the form that wraps the text area

CKEditor overrides form.submit() function when it's initialized within a form and event.cancel() does not seems to prevent the form being posted. So I had to override the function with one that just returns false.

EDIT: I forgot to copy the newly edited data to the textarea so it could be sent along with the rest of the form.

Upvotes: 1

Peter Krauss
Peter Krauss

Reputation: 13930

More one solution variation, using AJAX from jQuery. 1) declare the function CKEDITOR.ajaxSAVE; 2) call it for save updated HTML of the textarea.

 CKEDITOR.ajaxSAVE = function ( editor ) {
    editor.updateElement();
    var htm = editor.getData();
    var otherParameter = '...';
    if (htm) $.ajax({
        type: "POST",
        url: "saveHtmFromCKEditor.php",
        data: { content: htm, other: otherParameter }
      }).done(function( msg ) { // string or JSON object
        if (!parseInt(msg)>0) alert( "ERROR WHEN SAVING: " + msg );
      });
    else 
      alert('EMPTY HTM. NOT SAVED');
 };

Then, for call, at any time, use

 var oEditor = parent.main.CKEDITOR.instances['YourTextAreaID'];
 CKEDITOR.ajaxSAVE(oEditor);  

Upvotes: 0

Ryan
Ryan

Reputation: 11

Additional Note: If you don't want to create your own Icon, change

{ 
            label : editor.lang.save, 
        command : pluginName, 
        icon: "/img/save.png" 
     });

to

{ 
            label : editor.lang.save, 
            command : pluginName, 
            className: 'cke_button_save'
         });

Upvotes: 1

dhrubo
dhrubo

Reputation: 179

I have posted the simplest ajax save plugin here Ajax save plugin for CKEDITOR 3.x with jquery 1.4.x

Upvotes: 3

Ben
Ben

Reputation: 2077

Try copying straight from _source/plugins/save/plugin.js and changing as needed. Create your new plugin in /path/to/ckeditor/plugins (i.e. Not in /path/to/ckeditor/_source/plugins). For example, in /path/to/ckeditor/plugins create a new directory "AjaxSave", then in that directory create a file "plugin.js". Then in that file do something like this (adapted from the normal "save" plugin in the source folder):

(function()
{
  var saveCmd =
  {
    modes : { wysiwyg:1, source:1 },
    exec : function( editor )
    {
      var $form = editor.element.$.form;
      if ( $form )
      {
          try
          {
            editor.updateElement();
//Here is where you put your ajax submit function. For example... if you are using
// jQuery and the ajaxform plugin, do something like this:
            $($form).ajaxSubmit({
               success: function(response){
                 //do something with the response
               }
            });
          } catch ( e ) {
            //alert(e);
          }
      }
    }
  }
  var pluginName = 'ajaxsave';
  CKEDITOR.plugins.add( pluginName,
  {
     init : function( editor )
     {
        var command = editor.addCommand( pluginName, saveCmd );
        command.modes = { wysiwyg : !!( editor.element.$.form ) };
        editor.ui.addButton( 'AjaxSave',
         {
            label : editor.lang.save,
            command : pluginName,
            icon: "/img/save.png"
         });
     }
   });
})();

Then in the config, where you define your toolbar, change 'AjaxSave' for 'Save'.

EDIT: you must also add config.extraPlugins = "ajaxsave"; to the config.

Upvotes: 5

Related Questions