Monday, 25 July 2011

CKEditor image insert plugin

A little new to the ckeditor plugin development, what I found about is that its documentation is really bad! and incomplete too!, struggled two days for finding my appropriate solution. The trick is that ckeditor javascript api documentation will provide you function names, but no examples, maybe a due to a little less support from the community. So you might need to do some hits and trials to get things working.
Anyways, Lets develop a ckEditor image select/insert plugin step by step. Name of our plugin will be 'addassets' which will contain some hardcoded images that a user can select and on pressing OK the image will be inserted in the editor.

1. Create a folder 'addassets'
2. Create a file 'plugin.js' inside the folder.
3. Paste the following code:
    CKEDITOR.plugins.add('addassets',
    {
        init: function(editor)
        {
        var pluginName = 'addassets';
        CKEDITOR.dialog.add(pluginName, this.path + 'dialogs/addassets.js');
        editor.addCommand(pluginName, new CKEDITOR.dialogCommand(pluginName));
        editor.ui.addButton('AddAssets',
            {
                label: 'Add Assets',
            icon: this.path + 'addassets.png',
                command: pluginName
            });
        }
    });
    The above code simply tells ckeditor that we have a plugin 'addassets' in place, it also contains a dialog box whose code lies at location 'dialogs/addassets.js', we define a new button by the label of 'Add Assets' on the editor, its icon's location, and finally the command that will be fired upon clicking our button.

4. Create a new folder inside /addassets by the name of 'dialogs', this folder will contain all the dialog boxes that this plugin will use.
5. Create a new file 'addassets.js' inside /dialogs
6. Paste the following code

( function(){
        var testdialog;
    var exampleDialog = function(editor){
        return {
            title : 'Add Assets',
            minWidth : 300,
            minHeight : 200,
            buttons: [CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton],           
            resizable: CKEDITOR.DIALOG_RESIZE_NONE,
                        onShow:function(){
                                        dialog = this;
                                        testdialog = this;
                                        this.setupContent();
                        },
                        onLoad:function(){
                                        dialog = this;
                                        testdialog = this;
                                        this.setupContent();
                        },
                        onOk:function(){
                                var sInsert=this.getValueOf('page1','selectedimage');
                                if ( sInsert.length > 0 )
                {
                sInsert = '<img src="'+CKEDITOR.plugins.getPath('addassets') + sInsert+'">'
                                editor.insertHtml(sInsert);
                }
                        },
            contents: [{
                    id: 'page1',  /* not CSS ID attribute! */
                    label: 'Page1',
                    accessKey: 'P',
                                        elements:[{
                                                 type:'vbox',
                                                 padding:0,
                                                 children:[
                                                 {
                                                        type:'html',
                                                        html: '<p><img src="'+CKEDITOR.plugins.getPath('addassets') + 'girl1.png'+'"></p>',
                            onClick : function() {
                                testdialog.setValueOf( 'page1','selectedimage','girl1.png');
                            }
                                                 },
                                                 {
                                                        type:'html',
                                                        html: '<p><img src="'+CKEDITOR.plugins.getPath('addassets') + 'pic2.png'+'"></p>',
                            onClick : function() {
                                testdialog.setValueOf( 'page1','selectedimage','pic2.png');
                            }
                                                 },
                          {
                                                        type:'html',
                                                        html: '<p><img src="'+CKEDITOR.plugins.getPath('addassets') + 'pic3.png'+'"></p>',
                            onClick : function() {
                                testdialog.setValueOf( 'page1','selectedimage','pic3.png');
                            }
                                                 },                                               
                                                 {
                                                    type:'text',
                                                    id:'selectedimage',
                        //  hidden: 'TRUE',
                            'default' : '',
                                                    label:'',                                        
                                                    setup: function(element){
                                                                this.setValue('');
                                                    }
                                                 }]
                                         }]
                        }]
                }
        }
   
    CKEDITOR.dialog.add('addassets', function(editor) {
        return exampleDialog(editor);
    });
})();

The above code defines our 'addassets' dialog box. the entry point is CKEDITOR.dialog.add('addassets', function(editor) which calls exampleDialog() that defines the structure and logic of our newly created dialog. Its nothing but a javascript structure that defines different parameters required for a dialog. We defined the title, minimum width, minimum height, whether resizable or not, its contents, its events and its buttons.
Events are quite self explanatory, lets get into the contents section.
Our contents section defines a page 'page1' (you can define multiple pages and they appear in the form of tabs on the top). We give the ID and label attribute, now this ID is not a CSS class ID, neither is it rendered on the front page by the name as it is here, rather you can use this ID for referencing in ckeditor plugin code. just like this:

    testdialog.setValueOf( 'page1','selectedimage','pic2.png');

In the elements section of content is the real html schema for our dialog. We declare only one element and declare its type as 'vbox' which means that all its child elements will be arranged vertically. We can create complex structures through this.
Rest of the story looks good, we have three html child elements that defines three images (all appearing vertical in the dialog) and a text box element, we define an onClick event for each of these elements so to get the track of which image is clicked. On each click we set the value of our text field. Finally when OK button is clicked, we convert the image name into image HTML tag and write it to the editor.

7. Finally if you are using ckeditor with drupal; copy your 'addassets' folder to modules/ckeditor/plugins folder; open your ckeditor.config.js and append your new plugin name at config.extraPlugins after comma like:

config.extraPlugins = 'inserthtml, addassets';

and Goto Configuration > ckeditor > (ckeditor profile) > editor appearance tab; and add 'addassets' to your existing toolbar definition.



The code is easily modifiable as you can create your own design structure and can define different event based functionalities.