2012/05/23

Creating a button to insert some HTML in CKEditor

Sometimes it can be useful to have a toolbar button in CKEditor to insert a predefined block of HTML. The fact is that creating such option is quite easy, but for those that don't know much about javascript it might look more complex than it really is.
So this plugin allows to define as many new toolbar buttons as desired just by specifiying their properties in a config object.
After adding the "htmlbuttons" plugin you can add to your configuration a new entry "htmlbuttons" (yes, the same name I didn't want to think today). That entry must be an array of javascript objects, and each object has four properties; here's one example:
{
 name:'button1',
 icon:'icon1.png',
 html:'<a href="http://www.google.com">Search something</a>',
 title:'A link to Google'
},
First, the name for the command and button that you can use in the toolbar. Then the icon to use (place them in the plugin folder), next is the block of HTML that you want to insert, and finally a title to show up while hovering the button.
So now you can add those new buttons to your toolbar and when you reload the editor you can use those buttons to insert the HTML.
This sample shows the plugin in action with the default sample buttons (icons picked randomly from the Tango! project, if someone has some suggestions about better code samples and icons they're welcome).
The buttons (the three smileys) are from left to right:
  1. Insert a link pointing to Google
  2. Insert a 2x2 table
  3. Insert a nested list


Download:
Edit 2016: go to CKEditor plugins repository:
HTML Buttons plugin

2012/05/20

White list of elements and attributes for CKEditor

Sometimes you want to use CKEditor in a page where you can't fully trust the users, so they will have a restricted version with just some basic features: headings, bold, maybe links and images...

Of course it's easy to adjust the toolbar to show only those options, and with a good filter at the server you can be quite safe to accept the situation, but it would be even better if anything that will be stripped out at the server couldn't be added to the editor for example by pasting.

The fact is that using the dataProcessor of CKEditor it isn't too hard to setup something basic to perform the task: listen for each element and reject the ones that aren't whitelisted.

I've created a little plugin that does that job. It comes preconfigured with just some basic elements and attributes, but it's possible to modify that as it's just a simple javascript object that you can define in the CKEditor configuration.

Download: Whitelist plugin for CKEditor 1.1

Please, remember that you must use a filter at the server to perform at the very least the same filtering (or better) because this is not a real security option.

For PHP you can use HTML Purifier, in the case of Asp.Net previously the solution was the Microsoft AntiXss library but in January they released a broken version and haven't fixed it despite the complains. (Does anyone know an alternative solution)

 

This sample uses the default whitelist so it won't allow most HTML elements, and only basic attributes on links or images.

Edit: 20/01/13

Updated to version 1.1 to fix the attributes bug mentioned by Chris Hough

2012/05/01

Recipe: Live preview of CKEditor

Today we're gonna prepare a live preview of the contents edited with CKEditor.

A live preview with a WYSIWYG editor is not so important compared to other text-based editors, but anyways the behavior inside the editor might not match exactly the final output, so in those cases we can provide this option for those that want it.

Ingredients:

1 Instance of CKEditor

1 Preview container (for example a Div)

1 Copy of the onChange plugin

In case that you want to use this method with more than one instances, then you'll need as many preview containers as CKEditor instances you want to use.

Method:

1. Create the CKEditor instance in your page using any method that you like, and add the OnChange plugin to the list of extra plugins:

For example:

<textarea name='contents' id='contents'>This is an editor</textarea>
<script type='text/javascript'>
var config = { extraPlugins: 'onchange'};
CKEDITOR.replace('contents', config);
</script>

2. Now add add a little extra javascript to listen for changes in the editor instance and mirror those changes in the preview div, (based on this StackOverflow question)

CKEDITOR.on('instanceCreated', function (e) {
    e.editor.on('change', function (ev) {
        document.getElementById( ev.editor.name + '_preview').innerHTML = ev.editor.getData();
    });
});

That code will take care of any CKEditor instance and automatically copy its contents into the container with an id like the editor instance with an ending "_preview".

3. The only missing part is to initialize the preview before the user starts typing:

document.getElementById( e.editor.name + '_preview').innerHTML = e.editor.getData();

All the code together

<textarea id="contents" name="contents">This is an editor</textarea></p>
<div id="contents_preview"></div>

<script type='text/javascript'>

CKEDITOR.on('instanceCreated', function (e) {
    document.getElementById( e.editor.name + '_preview').innerHTML = e.editor.getData();
    e.editor.on('change', function (ev) {
        document.getElementById( ev.editor.name + '_preview').innerHTML = ev.editor.getData();
    });
});
var config = { extraPlugins: 'onchange'};
CKEDITOR.replace('contents', config);
</script>

This code in action: