Impact factor for posts is a measurement of importance.

Impact factor for users reflect their authority, reputation and contribution on a particular topic.

Rating reflects the quality of posts.

Rating on Voofie is not a simple average of all ratings, but a weighted average of rating, weighted by the impact factor of users who rated.

Explore exciting communities of

CKEditor Plugin Development

11 Jan 10

CKEditor is a one of the most flexible online WYSIWYG editor on the market.  Its flexible design, open API and detail documentation enable users to extend the functionality of the editor easily.  This tutorial outlines the basics of CKEditor plugin development, including adding buttons, dialogs, and executing commands.

Bookmark and Share

Content

Source file organization

Before getting started, it is useful to get a sense how CKEditor code is organized.  CKEditor is originally consist of many files, organized under ckeditor\_source directory.  The core functionalities, such as DOM element manuipulation, event handling, initialization scripts and some other environmental settings are included in ckeditor\_source\core folder.  All other functionalities, such as formating, copy & paste, image and links, are implemented as plugins under ckeditor\_source\plugins folder.  Each folder represents one plugin.  And under each folder, there is a plugin.js containing the code for that plugin.

You can see the source code is organized into different files.  To reduce the number of HTML requests, CKEditor compress and pack different files into ckeditor.js and ckeditor_basic.js, which is the "default" way of running the editor.  During development, you will want to execute from source code by using ckeditor_source.js instead of ckeditor.js.

Now, create ckeditor\_source\plugins\footnote folder and plugin.js under that folder.

Plugin Configuration

To start developing your plugin, you will have to register the plugin in order for the CKEditor to load it.  In ckeditor/config.js, add

config.extraPlugins = 'footnote';

This config will tell the editor to load the plugin.js under the footnote folder.  The basic layout for plugin.js is:

CKEDITOR.plugins.add('footnote',
{
init: function(editor)
{
//plugin code goes here
}
});

Buttons

Majority of the function in CKEditor is implemented in form of commands.  Commands can be triggered by events, function calls and of course by clicking a toolbar button.  The following code add a 'Footnote' button and 'footnote' command.

CKEDITOR.plugins.add('footnote',
{
init: function(editor)
{
var pluginName = 'footnote';
CKEDITOR.dialog.add(pluginName, this.path + 'dialogs/footnote.js');
editor.addCommand(pluginName, new CKEDITOR.dialogCommand(pluginName));
editor.ui.addButton('Footnote',
{
label: 'Footnote or Citation',
command: pluginName
});
}
});

The editor.ui.addButton function declare button with two parameters, the button name and the button definition.  The possible properties for button definition:

  • label: Title hint when hovering on the button
  • className: CSS class for the button icon.  Default: 'cke_button_' + command name
  • click: function call on clicking the button.  Default: executing command specified by command key value
  • command: default command to be executed on button click.

The above code take advantage of CKEDTIOR.dialogCommand, which will be covered in Dialog section.  After adding a button, you will have to add 'Footnote' to your toolbar defination in config.js to put the button into a correct location in toolbar.  After that, you will see an empty button is added to the toolbar.

An empty button is added.  However, nothing will occur when the button is clicked.

An empty button is added. However, nothing will occur when the button is clicked

Button Icon

It is important to give an icon to represent the icon.  To add an icon, you have to edit the editor.css file of the skin you are using.  For example, if you use the default kama skin, you have to edit skins\kama\editor.css.   Add the following code to the CSS file:

.cke_skin_kama a.cke_button_ICONNAME .cke_icon{background-image:url(/*url to your 16*16 icon */);}

Commands

CKEditor provides a majority of function in terms of commands.  The difference between Commands and normal functions is that Commands are stateful with "ON", "OFF" and disabled states.

Defining Commands

The editor.addCommand function declare command with two parameters, the command name and the command definition object.  The possible properties for command definition:

  • exec: At minimium, the definition object has to have a exec method, which define action to be taken when the command is executed.
  • modes: dictionary of modes that the command can be executed.  Default: {wysiwyg:1}   (avaiable modes: wysiwyg, source)
  • editorFocus: Whether giving the editor focus when executing the command.  Default: true
  • state: The state of the command.  Default: CKEDITOR.TRISTATE_OFF
  • canUndo: Whether the command need to be hooked into the redo/undo system.
  • async: Used for asynchronous functions like ajax.  The afterCommandExec event will not be fired automatically after executing the command.  It is expected that the programmer will fire the event manually.

Executing commands

Triggaring commands is easy, simply by executing:

editor.execCommand(commandName); 

Command States

Commands have three states, ON, OFF and DISABLED.  The state can be set by calling setState on the command object as following:

editor.getCommand(commandName).setState(state);

where state is one of: CKEDITOR.TRISTATE_ON, CKEDITOR.TRISTATE_OFF, CKEDITOR.TRISTATE_DISABLED

When set to disabled, the button representing the command will be grayed out and executing the command by execCommand will have no effect.  When set to on, the button will be highlighted.  When the state of the command is changed, the command will fire a "state" event.

Dialogs

Dialogs are key to many plugins.  To use dialog, they have to be registered in the plugin.js file along with command definitions, by calling CKEDITOR.dialog.add as following:

CKEDITOR.dialog.add(pluginName, this.path + 'dialogs/pluginName.js');

After that, if you want the dialog to be triggered by clicking a button, you can make use of CKEDITOR.dialogCommand to simply the task.

editor.addCommand(pluginName, new CKEDITOR.dialogCommand(pluginName));

Dialog definition

The convention is putting the code for dialog in dialogs/<pluginName>.js .  Similar to buttons and commands, dialogs are defined writing a dialog definition with properties and methods.  The following code shows a standard template for <pluginName>.js

( function(){

var exampleDialog = function(editor){
return {
title : /* title in string*/,
minWidth : /*number of pixels*/,
minHeight : /*number of pixels*/,
buttons: /*array of button definitions*/,
onOk: /*function*/ ,
onLoad: /*function*/,
onShow: /*function*/,
onHide: /*function*/,
onCancel: /*function*/,
resizable: /* none,width,height or both */,
contents: /*content definition, basically the UI of the dialog*/
}
}

CKEDITOR.dialog.add('insertHTML', function(editor) {
return exampleDialog(editor);
});

})();

The definition has the following properties/methods:

buttons

This property defines the buttons available at the buttom of the dialog.  It is an array of CKEDITOR.dialog.buttonDefinition objects.  The default value is [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ].  To add your own button, write your own buttonDefinition and add it to the array.  For example:

buttons:[{
type:'button',
id:'someButtonID', /* note: this is not the CSS ID attribute! */
label: 'Button',
onClick: function(){
//action on clicking the button
}
},CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton],

The effect will be like this:

New button can be added along with OK and Cancel

New button can be added along with OK and Cancel

Dialog Events

onOK, onLoad, onShow, onHide, onCancel events will be triggered on various moments.  onLoad will be triggered when the dialog is opened for the first time, it can be used to hold initialization script for the dialog.  onShow will be fired when the dialog is diaplayed.  The difference between onLoad and onShow is that onLoad will only be fired once no matter how many times the dialog is opened and closed, while onShow will fire each time when the dialog is displayed.  It is because on pressing ok or cancel, the dialog will be hided (and fires onHide) instead of completely unloaded.  onOk and onCancel are fired when ok or cancel button is clicked.

Resizable

This attribute control whether the dialog can be resized.  Possible values are: CKEDITOR.DIALOG_RESIZE_NONE, CKEDITOR.DIALOG_RESIZE_WIDTH, CKEDITOR.DIALOG_RESIZE_HEIGHT and CKEDITOR.DIALOG_RESIZE_BOTH.  Default is CKEDITOR.DIALOG_RESIZE_NONE

Dialog UI

The user interface of dialog is defined as the contents property of dialog definition.  The dialog UI is first organized into different pages, with each page representing a Tab page of the dialog.  Under each page, the input elements (button, textInput, textArea, radio, select, checkBox and file) are organized with help of structural elements (vbox, hbox and label).  By writing definitions for these UI elements, you can define the behaviour and look of the UI without writing any HTML code.  Of course, instead of using provided objects to construct the user interface, you can still use the html UI element to build the user interface using raw HTML code.

Dialog Pages

The contents field is an array of contentDefinitions, with each definition refer to one dialog page.  Here is an example template:

contents: [{
id: 'page1', /* not CSS ID attribute! */
label: 'Page1',
accessKey: 'P',
elements:[ /*elements */]
}, {
id:'page2',
label:'Page2',
accessKey: 'Q',
elements:[/*elements*/]
}]

The result dialog will look like this:

Tabs will appear when there is more than one contentDefinition

Tabs will appear when there is more than one contentDefinition

UI Elements

After defining the tab pages, you can design the UI of each tab page by passing an array of uiElements as the elements property of the contentDefinition.  There are two types of uiElements, structual ones and input ones.  Structual elements (vbox and hbox) use tables to help laying out the locations of the elements.  The structual elements can be nested to give a complicated layout.  While the input uiElements have several important features that makes them more useful than plain DOM input elements.

Structual elements
elements:[{
type : 'hbox',
widths : [ '100px', '100px', '100px' ],
children :
[{
type:'html',
html:'<div>Cell1</div>',
},{
type:'html',
html:'<div>Cell2</div>',
},{
type: 'vbox',
children:[{
type:'html',
html:'<div>Cell3</div>',
},{
type:'html',
html:'<div>Cell4</div>'
}]
}]
Example layout of the structual elements

Example layout of the structual elements

Input Elements

Input elements have more properties and methods available.  For detail please refer to the uiElement documentation, meanwhile here is some important ones:

  • id:(required) Note that this is not the CSS ID attribute, but instead an identifier to be used by CKEditor.  CKEditor will set the CSS ID attribute automatically with value unrelated to this ID attribute.  To get the object representing the element, you can use getContentElement. For example, if you want to get the an uiElement inside the scope of another uiElement, you can use:
    this.getDialog().getContentElement(pageIdName,elementIdName)  //pageIdName is the ID for page containing the element
  • type:(required)  one of the following: text, password, textarea, checkbox, button, select, file, fileButton, html
  • label: The textual label show alongside with the input element.
  • labelLayout: 'horizontal' or 'vertical'.  When set to vertical, the label will be on top of the element.
  • on* events:  Function for events.  The first character have to be capitalized.  Event can be DOM events such as onChange, onClick, etc. as well as onShow, onHide and onLoad, which are called after the corresponding event for the dialog is fired.
  • validate: Function to validate the value of the input element.  For example, to validate the value is not empty, you can use:
    validate : CKEDITOR.dialog.validate.notEmpty(ErrorMessage)
    The ErrorMessage will popup when the OK button is clicked and the field is empty.  The built-in validators are:
    • regex(regex, msg)
    • notEmpty(msg)
    • integer(msg)  //regex: /^\d*$/
    • number(msg)  //regex: /^\d*(?:\.\d+)?$/
    • equals(value, msg)
    • notEqual(value, msg)
  • setup:  function to be run when setupContent method of the parent dialog is called.   It can be used to initialize the value of the field.  For example, when editing a pre-existing image on the document, you may want to initialize the width field to be the width of the original image.  Here is the example:
    onShow : function(){ //onShow function for the dialog definition
    //... other code ...
    var elem= this.getParentEditor().getSelection().getSelectedElement(); //get the current selected element
    this.setupContent(elem); //this function will call all the setup function for all uiElements
    //... other code...
    },
    contents: [{
    id: 'InfoTab',
    label: 'Info Tab',
    elements:[
    { //input element for the width
    type: 'text',
    id: 'widthInput',
    label: 'Width',
    labelLayout: 'horizontal',
    setup: function(element){
    this.setValue(element.getAttribute('width'));
    }
    }]
    }]
    The initial value for width field will be the same as the selected image

    The initial value for width field will be the same as the selected image

  • commit: function to be run when commitContent method of the parent dialog is called.  For example, it can be used to change the width of the image when the "OK" button is clicked. 

Context Menu

Context Menu is the menu that will pop up when you right click inside CKEditor.  Similar to other features of CKEditor, it can be easily customized.  The following code shows how to add a "Code" menu item when right click on the "pre" (code) element:

if(editor.addMenuItems)
{
editor.addMenuItems( //have to add menu item first
{
insertCode: //name of the menu item
{
label: 'Code',
command: 'insertCode',
group: 'insertCode' //have to be added in config
}
});
}
if(editor.contextMenu)
{
editor.contextMenu.addListener(function(element, selection) //function to be run when context menu is displayed
{
if(! element || !element.is('pre'))
return null;
return { insertCode: CKEDITOR.TRISTATE_OFF };
});
}

The above code add an extra item insertCode to the context menu.  When right click on elements that is not "pre", the insertCode menu item will not be displayed.  When right click on "pre" element, the insertCode menu will be displayed as the OFF state. 

Besides the above code, you still have to add 'insertCode' group to config, which define the order of displaying the menus.  Here is the code to be added in config.js:

config.menu_groups = 'clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,
flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,insertCode';

You can see that the insertCode in inserted to theend of the menu_groups config.  The end result will look like this:

Code menu is added

Code menu is added

Source Code Packing

After writing all the code, it is time to put your code into production.  As mentioned before, the source code that is consist of muiltiple files are compressed into a few files to reduce the number of HTTP requests.  It is neccessary to incorporate your plugin source code into these files.

The packing of the files are actually controled by ckeditor.peck.  Add your source code files to the list of 'ckeditor.js' entry will add the file into that file.

To actually pack the file, you need two extra files ckpackager.exe or ckpackager.jar that can be downloaded here.  After downloading, run the following command on the CKEditor root directory:

ckpackager.exe ckeditor.pack

Now the source files will be packed and copied to the CKEditor root directory.  And it is time to enjoy your plugin!

29 Comments

c_schmitz

Avatar for c_schmitz
2
10 Feb 10

Easier way to add an icon to the toolbar

There is an easier way to have an icon for your toolbar button. Editing the CSS is always the least desirable for me.

 

CKEDITOR.plugins.add('myplugin',
{
init: function(editor)
{
//plugin code goes here
editor.ui.addButton('myplugin',
{
label: 'myplugin',
command: FCKCommand_myplugin,
icon: CKEDITOR.plugins.getPath('myplugin') + 'myplugin.png'
});
}
});
2
comments

Reply

MailSpamToMe

Avatar for MailSpamToMe
0
17 Feb 10

Hello George,

I have studied the code for days and cannot confirm how to change the css colors for the OK, Cancel and Close Buttons on the dialog. The green and orange and red is so uggggggggggggggly :-) Can you please explain how to change the css styles for the buttons on the dialog?

1
comment

Reply

alex_hill

Avatar for alex_hill
0
22 Feb 10

How to propagate a select box

This tutorial seems very in depth, but I cant see how to propagate the options for a select box. How can I set these options?

1
comment

Reply

davecohen

Avatar for davecohen
0
08 Mar 10

Ajax/Select/Dialog

Thanks for the tutorial. I need a dialog box that can pull some stuff from server (ajax), generate code/text to insert in ckeditor at cursor. Similar to WIRIS formula editor (http://www.wiris.com/documents/plugin-CKEditor.html), but on much smaller scale. Do you or others know of a simpler example (I can't find one). And, while I don't know if this is done on this site --- can you do something like that on a contract basis?

1
comment

Reply

onlygio

Avatar for onlygio
0
21 Apr 10

Change button on fly

Hi, good tutorial, but I have a problem i can't raise.


I want to change one toolbar's button on fly, when my plugin is making something.

How can I make it? Is there something like CKEDITOR.updateButton() ...

3
comments

Reply

Joan Teixidó (joanteixi)

Avatar for joanteixi
0
21 Apr 10

Pass a parameter to plugin from config parameters

Great tutorial. Thks! It's possible to pass a parameter to plugin throw the config params of ckeditor?

I created a ajax save button but i want to send a parameter to ajax call that i would like create when i call ckeditor.

 

Joan

1
comment

Reply

George Wu (georgewu)

Avatar for georgewu
1
26 Apr 10

I am very happy to answer any question that is related to CKEditor, or even any questions that I probably know

but it will be better for you to raise a question through the "Question" function in this site, which basically works like Stack Overflow.  By raising a question post, it is easier for others to find the question and participate in answering the question.


Reply

n2lose

Avatar for n2lose
0
21 May 10

How to disable okButton and cancelButton  of dialog. I try this method CKEDITOR.dialog.disable(okButton) but it's doesn't work. Here is my code plugin :

 

CKEDITOR.plugins.add('helloworld',
{
requires : ['iframedialog'],
init : function(editor) {
var pluginName = 'helloworld';
var mypath = this.path;
editor.ui.addButton(
'helloworld.btn',
{
label : "My Plug-in",
command : 'helloworld.cmd',
icon : mypath + 'images/helloworld.gif'
}
);
var cmd = editor.addCommand('helloworld.cmd', {exec:showDialogPlugin});
CKEDITOR.dialog.addIframe(
'helloworld.dlg',
'Hello Title',
mypath + 'helloworld.html',
400,
300,
function(){
}
);
}
}
);

function showDialogPlugin(e){
e.openDialog('helloworld.dlg');
}
1
comment

Reply

George Wu (georgewu)

Avatar for georgewu
0
28 Jul 10

I have written a tutorial on developing a citation plugin.  You maybe interested in using the code in your CKEditor as well.

Building Citation & Footnote Plugin for CKEditor


Reply

George Wu (georgewu)

Avatar for georgewu
0
13 Aug 10

I have compiled a resources list, covering many aspects of CKEditor, especially on the ready-made plugins:

http://www.voofie.com/content/124/community-resources-guide---fckeditor/

this page is editable by everyone.  Feel free to add your plugin to the list.

1
comment

Reply

srakesh

Avatar for srakesh
0
14 Sep 10

Button does not show on a sample plugin?

Hi,

I am trying to create a test plugin on CKEditor 3.4. I created a plugin.js in plugins/test directory and it has the foll code:-

CKEDITOR.plugins.add( 'test',

{

    init : function( editor )
    {

        editor.ui.addButton( 'test',
            {
                label : 'test label',               
                icon: CKEDITOR.plugins.getPath('test') + 'images/myicon.gif'
            
            });   
    }
} );

I also changed the ckeditor/config.js to load the plugin.

CKEDITOR.editorConfig = function( config )
{
    // Define changes to default configuration here. For example:
    // config.language = 'fr';
    // config.uiColor = '#AADC6E';
    config.plugins = 'basicstyles,toolbar,wysiwygarea';
    config.extraPlugins='test';
};

The plugin.js is loaded fine. I don't see any javascript errors. Why doesn't the button icon show up? Thanks in advance
 


Reply

aksh27

Avatar for aksh27
0
16 Dec 10

ckeditor fails to load after repackaging it

Hi, im very thankful to you for such a great contribution on CKEDITOR.

i have followed all steps, but there is a problem.

 

I repackaged the editor  from _source directory using the packager and it went success, but, after that the editor failed to load. i have tried this several times, but no use.

 

Please guide me??


Reply

dineshmalhotra

Avatar for dineshmalhotra
0
22 Dec 10

please tell me how to delete the cancel button from the dialogue box

please tell me how to delete the cancel button from the dialogue box


Reply

djmitzlplick

Avatar for djmitzlplick
0
02 Mar 11

In the config.js file, "extraPlugins" is intended to engage additional plugins ... OK.  Even though I have tested the individual plugins and each works fine if they are added individually like this:

config.extraPlugins='test';

However, every time I attempt to list MORE THAN ONE "extraPlugin", like this:

config.extraPlugins = 'basicstyles,toolbar,wysiwygarea';

the editor instance disappears ... whether I add the buttons to the toolbar or not.

1. I have checked to see that plugins do not share the same code
2. I have checked to see that spelling, commas, semicolons, and brackets are in the right spots ...

I am at a loss.  I love the editor.  Your tutorial is great, but I'm losing my hair trying to find what's wrong.

2
comments

Reply

elcioeff

Avatar for elcioeff
0
24 Mar 11

CKEditor with ZK

i´m using CKEditor with ZK and i´d like to customize som buttons.

As CKEditoris embeded into a JAR file, i dont have access to place  any new files  under ckeditor\_source\plugins folder

So i created a new folder just like i did to place the config.js file where i actually use the editor.

When i do that i get this error:

/js/ckez/ext/CKeditor/_source/plugins/editor/plugins/ntButtons/plugin.js not found

How do i implement this using ZK ?


Any help is welcome. Tks


Reply

Please login to post comment.

What is Voofie?

Voofie organizes knowledge, discovers useful resources and recognizes knowledgable users.

Bookmark your blog in Voofie to get more traffic as well as building a reputation in your field!

Explore more about it. Become a member—our FREE Registration takes just seconds.

Page Info
189Impacts
3.6/12 rates
72187
Your Rating:
Version: 3
Last update: 20 Jan 10
History Permalink
Author
Avatar for georgewu

George Wu (georgewu)


Hong Kong

  • JavaScript
  • 1.6k
  • FCKeditor
  • 1.6k