CKeditor, Stop Altering Elements!!!

CKEditor is very opinionated on what needs to be altered/removed. It parses and filters html too strict for our needs, so this post will cover how to loosen up CKeditor to stop removing/altering html.

Before we move on, lets clarify that we can alter CKEditor behavior in 3 ways:

  • From HTML – by adding attributes provided by CKEditor such as data-cke-survive, data-cke-filter, etc
  • From Configurations – by changing CKEditor configurations in CKEDITOR.dtd
  • From Implementation – by implementing additional custom processor,filter,rules and attaching it to CKEditor mechanism

We will not cover the “From Implementation” in this post. Our perfect solution is to accomplish our task from configuration but we will also show how its done from HTML with CKEditor provided attributes.

Stop Removing Empty Anchor Tag in CKEditor

CKEditor is removing empty anchor tags such as the following:

<a data-original-title="youtube" class="youtube" href="#"> </a>
  • From HTML
    To stop removing anchors if the html is altered as following:

    <a data-original-title="youtube" class="youtube" href="#" data-cke-survive="true"> </a>
    <a data-original-title="youtube" class="youtube"> </a>

    So, by adding new attribute of data-cke-survive or by removing attribute href, the empty anchor elements are not being removed

  • From Configurations
    We like to stop removing empty anchor tags from configurations as following:

                    CKEDITOR.on('instanceCreated', function (ev) {
                        CKEDITOR.dtd.$removeEmpty['a'] = 0;

    This works if we alter the CKeditor library by changing function RemoveEmpty to

    function isRemoveEmpty( node ) {
    		// Keep marked element event if it is empty.
    		if ( node.attributes[ 'data-cke-survive' ] )
    			return false;
    		// Empty link is to be removed when empty but not anchor. (#7894)
    		//return == 'a' && node.attributes.href || CKEDITOR.dtd.$removeEmpty[ ];
    		return CKEDITOR.dtd.$removeEmpty[ ];

    We realize this is not often times acceptable to update CKEditor library, however. This was only way we know to accomplish this from configurations. If you know how to do that without altering CKEditor library, please, let us know. We have also asked at the CKEditor forums:

Stop Removing ANY Empty Tag in CKEditor

There is a defined list of tags that is going to be removed if empty(see dtd.js and $removeEmpty or run CKEDITOR.dtd.$removeEmpty from console).

  • From HTmL
    To ensure the certain empty tag are not being removed, add attribute ‘data-cke-survive’:

    <span data-cke-survive="true" ></span>
  • From Configurations
    Or you can configure the particular tag from not be removed:

                    CKEDITOR.on('instanceCreated', function (ev) {
                        CKEDITOR.dtd.$removeEmpty['span'] = 0;
                        CKEDITOR.dtd.$removeEmpty['TAG-NAME'] = 0;

By setting an element to 0 in the CKEDITOR.dtd.$removeEmpty, it prevents the empty tags from being removed by CKEditor.

Stop Auto Wrap Tags in CKeditor

The default behavior is for CKEditor to wrap any inline elements into paragraph tags. To stop that globally:

                CKEDITOR.on('instanceCreated', function (ev) {
                    CKEDITOR.config['autoParagraph'] = false
                    //or for certain editor instance
                    if ( == textId) {
                        ev.editor.on('customConfigLoaded', function () {
                            ev.editor.config.autoParagraph = false;

This will stop automatically wrapping every element into paragraph tag.
To stop wrap a certain element such as anchor tag into paragraph tag:

                CKEDITOR.on('instanceCreated', function (ev) {
                      delete CKEDITOR.dtd.$inline['a'];

This will change the declaration of the anchor tag to not be an inline element, thus, no any wrapping takes place

Perhaps, you like to wrap inline elements, but instead of paragraph tags, you like to wrap into ‘div’, ‘br’ or any tag of your choice, then:

CKEDITOR.config['entermode'] = CKEDITOR.ENTER_BR;//or config.entermode=2 in config.js
CKEDITOR.config['entermode'] = CKEDITOR.ENTER_DIV;//or config.entermode=23 in config.js

This will add BR or DIV tag to every inline element

Stop Wrap UL around LI in CKEditor

By default, CKeditor is wrapping UL element around LI if one is not present. To stop:

                CKEDITOR.on('instanceCreated', function (ev) {
                  //make sure LI is not wrapped within UL
                    delete CKEDITOR.dtd.$listItem['li'];
                    delete CKEDITOR.dtd.$intermediate['li'];    

By removing the LI form the list, you ensure that CKEditor is not wrapping LI elements with additional “UL”.

Stop Filtering in CKEditor

By default, CKEditor runs its processors and filters when outputing content.

  • From Html – To disable the filter or processing on a particular tag and children add the the attribute as following:
    • data-cke-filter=”off”
    • data-cke-processor=”off”
    • autocomplete=”off”

    The data-cke-filter stops the filering, the data-cke-processor stops the processor and the autocomplete for both. This will apply for the tag and all of its children

  • From Configuration – To disable processing/filtering from configurations, add the following:
                    CKEDITOR.on('instanceCreated', function (ev) {
                        //disable filters
                        ev.editor.on('customConfigLoaded', function () {
                            ev.editor.config.allowedContent = true;

Here by setting configuration allowedContent to true, it disables the filtering/processing editor content output

Taking CKEditor a Apart

In this post, we dive into the code of CKEditor to learn internals. We needed to do so to understand how the empty tags are being removed by default. This was not acceptable behavior because frameworks like Twitter Bootstrap or Foundation use empty tags part of the layout.

The dev version none minimized CKEditor are located at

Boot from Console

When troubleshooting or learning, it always easer to move everything else out of the way but the thing of your interest. In our case, we decided to run CKEditor without Drupal in the browser console for quick, easy changes. In the following are steps to boot CKEditor from console:

1. Disable Drupal

To take Drupal out of way, we disable the CKEditor module

2. Import CKEditor

There were several ways to load CKEditor all of which are listed here

A)From HTML Layout
By inserting the following in top of your page within ‘head’ tag

<script src="http://dev-ckeditor/sites/all/libraries/ckeditor/ckeditor.js?n83a0r"></script>

B) From Drupal API
By executing the following code in hook_preprocess_page() or any other appropriate place for that matter

drupal_add_js('http://dev-ckeditor/sites/all/libraries/ckeditor/ckeditor.js', array('scope' =>; 'header', 'type' =>; 'external'));

C)From JS Console
By calling the following, ckeditor library will be loaded


NOTE: In console, I run into errors when ckeditor.js was trying to load its dependences such ad load.js due to unable configure base path. I believe it should work if using the production ckeditor.js instead the development version that is not compiled into one

This will import the library as well as initialize CKeditor after which making the global variable CKEDITOR available and ready, so we can call CKEditor API

Let’s check the status


It gives status – ‘loaded’ on success and its ready to start ckeditor
There are 4 different status – loaded, basic_load, ???

4. Load Into Textarea

To start up CKEditor in the textarea is as simple as initializing it that can be done from console as following:

//or particular element with certain id

Here, we start up all of the textareas by calling replaceAll(). In the second, we enable CKEditor on certain element not necessaryly ‘textarea’ with id of ‘id_name’. This should bring up the text editor

Other Stuff

1. Editor Instances

This will display all the ckeditor instances

2. See Editor Configuration

From console:

var editor = CKEDITOR.instances.editor1;
alert( ); // e.g. 'moono'
3. Filters

To see what input is about to be filtered:


Setting custom filters:

var filter = new CKEDITOR.filter( 'p strong em br' );
editor.setActiveFilter( filter );
// Create standalone filter passing 'p' and 'b' elements.
		 *		var filter = new CKEDITOR.filter( 'p b' ),
		 *			// Parse HTML string to pseudo DOM structure.
		 *			fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<p><b>foo</b> <i>bar</i></p>' ),
		 *			writer = new CKEDITOR.htmlParser.basicWriter();
		 *		filter.applyTo( fragment );
		 *		fragment.writeHtml( writer );
		 *		writer.getHtml(); // -> '<p><b>foo</b> bar</p>'

For hooking into all enable active filters:

editor.on( 'activeFilterChange', function() {
     if ( editor.activeFilter.check( 'cite' ) )
        // Do something when <cite> was enabled - e.g. enable a button.
        // Otherwise do something else.
   } );

To disable filters:

//before the editor is initiated
 CKEDITOR.config.allowedContent = true;
textarea_settings = Drupal.ckeditorLoadPlugins(textarea_settings);
CKEDITOR.replace(textarea_id, textarea_settings);

Here, the textarea_id is the ‘id’ of the element(textarea or div). I am not sure the textarea_settigns???

5. Drupal and CKEditor

In the modules/ckeditor/ckeditor.utils.js, is where the CKEditor instances are created and attached to textarea.
From ckeditor.utils.js, the function CKEditor.replace is called that is defined in the themedui.js that calls CKEDITOR.editor from editor.js

6. Fragmenting in CKEditor
var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<p>foo<b>bar</b>bom</p>' );
 fragment.forEach( function( node ) {
 console.log( node );
} );
		 *		// Will log:
		 *		// 1. document fragment,
		 *		// 2. <p> element,
		 *		// 3. "foo" text node,
		 *		// 4. <b> element,
		 *		// 5. "bar" text node,
		 *		// 6. "bom" text node.
		 * @since 4.1
		 * @param {Function} callback Function to be executed on every node.
		 * **Since 4.3** if `callback` returned `false` descendants of current node will be ignored.
		 * @param {CKEDITOR.htmlParser.node} callback.node Node passed as argument.
		 * @param {Number} [type] If specified `callback` will be executed only on nodes of this type.
		 * @param {Boolean} [skipRoot] Don't execute `callback` on this fragment.
7. Stop Removing Empty Tags

There is defined list of tags that is going to be removed if empty(see dtd.js and $removeEmpty). To ensure the certain empty tag are not being removed, add attribute ‘data-cke-survive’:

<span data-cke-survive="true" ></span>

or pass the following to the CKEditor configuration file:

CKEDITOR.dtd.$removeEmpty['span'] = 0;
CKEDITOR.dtd.$removeEmpty['TAG-NAME'] = 0;

This make the empty tags to not being removed
NOTE: If you working with the production CKEditor.js, you will have to alter section starting “CKEDITOR.dtd” as following:

 CKEDITOR.dtd=function(){var,e=function(a,d){for(var [...]
span:0//set the 

You will have to grep the CKEditor.js file for section starting “CKEDITOR.dtd” and then change value from 1 to 0 for each tags you like to not be removed if empty(see above example for ‘span’ tag)

8. Update Styles

Here is an example for console to update styles:

var editor = CKEDITOR.instances['edit-body-und-0-value'];

Here, we start by retrieving the CKEditor Instance with id “edit-body-und-0-value”. Afterwards, we set the font-size.

if you like append the whole style sheet than:

9. Stop Auto Wrap

The default behavior is for CKEditor to wrap text into paragraph tags. To stop that:

//from console
CKEDITOR.config['autoParagraph'] = false

In the ckeditor.config.js file:

config.autoParagraph = false

This will stop automatically wrapping every element into paragraph tag. You can also set to add ‘br’ or ‘div’ instead of pargraph tags as following:

CKEDITOR.config['entermode'] = CKEDITOR.ENTER_BR;//or config.entermode=2 in config.js
CKEDITOR.config['entermode'] = CKEDITOR.ENTER_DIV;//or config.entermode=23 in config.js

This will add BR or DIV tag to every element

To stop wrap a certain element such as anchor tag into paragraph tag:

                delete CKEDITOR.dtd.$inline['a'];

This will change the declaration of the anchor tag to not be an inline tag, thus, no any wrapping takes place

Stop remove Empty Anchor tags

To stop removing empty tags, add the attribute – “data-cke-survive” to the anchor tag as following:

<a href="#" data-original-title="github" class="github" data-cke-survive="true">

Or ensure attribute “href” is not present as following:

<a data-original-title="linkedin" class="linkedin">
Stop Wrap UL around LI

By default, CKeditor is wrapping UL element around LI if one is not present. To stop alter CKEDITOR.dtd.$listItem in DTD.js

//OLD:$listItem: { dd: 1, dt: 1, li: 1 },
        $listItem: { dd: 1, dt: 1},

By editing CKEditor directly will cause problems sooner or later. Instead, hook into CKeditor and update from outside

                CKEDITOR.on('instanceCreated', function (ev) {
                  //make sure LI is not wrapped within UL
                    delete CKEDITOR.dtd.$listItem['li'];
                    delete CKEDITOR.dtd.$intermediate['li'];    

Here, we hook into the event triggered when CKEditor instance is created to remove “li’ tag from inline tags list.
By removing the LI form the list, you ensure that CKEditor is not wrapping LI elements with additional “UL”. For production, you will have to grep ckeditor.js file to make the change since everything is compiled into one JS file

Hook Into Events

There are lot of events available either on CKEDITOR App variable – CKEDITOR or on each editor instance itself

To listen for event on CKEDITOR APP variable

CKEDITOR.on( 'instanceReady', function( ev ) {
    editor = ev.editor;
    if( == 'edit-body-value'){
         console.log( 'appending style - sites/all/themes/metronic/assets/drupal/custom_metronic.css' );

Here, we sign up for event “InstanceReady” to append custom stylesheets.

To listen for event on editor instance itself

CKEDITOR.on( 'instanceCreated', function( ev ) {
    if( == 'edit-body-value'){
       ev.editor.on( 'contentDom', function(){
         var ck_dom = ev.editor.document.$;
         var s0= ck_dom.createElement( 'script' );
         s0.type = 'text/javascript';
         s0.onload = function() {
             console.log( 'script /path/jquery-1.11.0.min.js loaded' );
         s0.src = '/path/jquery-1.11.0.min.js';
         s0.$ = s0;
      } );

Here, we first use event on the CKEDITOR App itself to get handle of the editor obj. Once we got the editor object, we sign up for an event “contentDom” that is triggered once the DOM of editor content is constructed. During this event we are importing JQuery lib

See What’s Going On

To see what is filtered, processed and actually sitting in the editor content(DOM) at any give time from console:

var editor = CKEDITOR.instances['edit-body-value'];
editor.document.$.body //to see what is within BODY tags
editor.document.$.head //to see what is within HEAD tags

Here, we first retrieve the particular textarea of our interest and then navigate to the BODY or HEAD. It will display the DOM in real time

How To Find Which Config.js CKEditor Is Using

To see which config.js the CKEditor is actually using, once the instance is up, go to console and type:


This will print out the path and the name of config file CKEditor is using. Note, there may be different config files used at the same time. The CKEDITOR app using one and then each different editor instance(i.e.CKEDITOR.instances.editor1) using another one(perhaps one loaded from the theme folder,etc)

Some Tags are Removed

you can disable the filter with allowedContent configuration as described above. You can also disable processing on a particular tag as following:

  • data-cke-filter=”off”
  • data-cke-processor=”off”
  • autocomplete=”off”

This will apply for the tag and all of its children

Manipulate Editor Content

To remove some element from the the editor:

var element = ev.editor.document.getById( 'ckeditor-wrapper-end' );

This will remove element with id ckeditor-wrapper-end while keeping parent and children elements intact.
The better way API for manipulated data of editor is available on “editable” object:

var editable = CKEDITOR.instances['.textId'].editor.editable();
if(editable.find('ckeditor-wrapper-end').count()) editable.find('.ckeditor-wrapper-end').remove();

As you can see, the “editable” API has similar API as jQuery. Please, reference editable.js for complete list of function available.

Update Editor

To update editor content:

var editor = CKEDITOR.instances['TEXTAREA-ID'];
var newHtml = '<p>Hello World!</p>";
       callback: function() {

Here, we first retrieve editor and then update its content via setData() API. At last, the textarea itself is updated in the DOM

Summary of Events

Event Scope comments
loaded editor triggered once editor is loaded before initiating the editor content
instanceLoaded CKEDITOR triggered once CKEDITOR is loaded
customConfigLoaded editor
configLoaded editor
destroy editor
save editor
key editor
dblclick editor
doubleclick editor
click editor
beforeGetData editor Handle the load/read of editor data/snapshot.
getSnapshot editor sets event data from the editor data
saveSnapshot editor ???
lockSnapshot editor ???
unlockSnapshot editor ???
afterSetData editor sets the data from editor data
loadSnapshot editor takes event data and sets it to the editor data
beforeFocus editor Delegate editor focus/blur to editable.
insertHtml editor takes the data from event and inserts in CKEDITOR.DOM via insertHTML()
insertElement editor takes the data from event and inserts in CKEDITOR.DOM via insertElement()
insertText editor takes the data from event and inserts in CKEDITOR.DOM via insertText()
beforeSetMode editor Before any mode is set on the Editor(i.e. editor.mode)(see plugin.js)
beforeModeUnload editor after mode is set on the editor(i.e. editor.mode)(see plugin.js)
beforeGetModeData editor before getting data after setting the mode(see plugin.js)
afterModeUnload editor passing data to be able update at last step in mode setup(see plugin.js)
toHtml editor at the time data is process including filters applied(see htmlprocessor.js)
dataFiltered editor after some filter applied(see htmldataprocessor.js)
dataReady editor when data is ready before processing and filtering(see htmldataprocessor.js)

To fire any of the events: 'saveSnapshot' );

Here, we trigger one of the events – saveSnapshot attached to the editor.
To listen an event:

			editor.on( 'saveSnapshot', function( evt ) {
                                //do something with or
			} );

Here we listen of event – save Snapshot and then grab the new data via or

Encode and Decode

To decode or encode a string:

var result =;
var encodedText =;

Here, the editor data is decoded and encoded. See for much more utilities


1.Resource interpreted as Script but transferred with MIME type text/html: “http://dev-ckeditor/node/add/core/loader.js”

This happened when I was trying to load CKEditor library from console and the CKEditor was trying to load its dependencies. The dependency URL(path) came up wrong resulting in this error. I tried to set CKEditor Base path but it didn’t work because the base path needed to be set before the CKEdiotr library is loaded. I tried that and it didn’t work

The changes doesn’t take an effect

Make sure you clear browser cache as well as Drupal cache for the most current config.js loaded

Adding CKEditor Plugins Manually in Drupal

CKEditor has a lot of new good plugins that doesn’t have supporting Drupal module for easy integration. In this post, we go over how to integrate any native CKEditor plugin without supporting Drupal module present. Specifically, we cover how to install the plugin as part of CKEditor module and how to do the same but as separate custom module. In this post, we have CKEditor installed as a stand alone module not part of Drupals WYSIWYG install. How to install stand alone editor such as CKEditor, please, see post Wysiwyg With Ckeditor In Drupal

To make it more practical, lets install CKEditor plugin – Leaflet that adds map functionality to the editor

Add Plugin Part of CKEditor Module

1.) Download and unzip the plugins here (depending on your setup):

“sites/all/modules/ckeditor/plugins” or “sites/all/modules/contrib/ckeditor/plugins”.

After that, you should have the following folder structures:

2.) We should now activate the new plugins and add them to the toolbar.

This is done by configuring the Ckeditor Profile Settings, in which by default is located in:

A. Activate the Plugins
In EDITOR APPEARANCE >>> Plugins section:
Enable the corresponding checkboxes for the Leaflet, Line Utilities, and Widget plugins.
These are the texts displayed adjacent to their checkboxes:
“Plugin file: leaflet”
“Plugin file: lineutils”
“Plugin file: widget”

B. Add them to the Toolbar
We should make the activated plugins visible in the toolbar,
skipping this step will make the Leaflet plugin inaccessible in the toolbar.

In EDITOR APPEARANCE >>> Toolbar section:
Drag the Leaflet Maps icon (black-colored) from the ‘All Buttons’ section to the ‘Used Buttons’ section.

We need to configure the Leaflet Maps icon only since the Line Utilities and Widget plugins
have no toolbar icons and they will just load in the background.

3.) Then, click the Save button. Clear the Drupal’s overall cache AND clear the browser’s cache.

Clearing the browser’s cache is also very important since the CKEditor’s JS and CSS assets/components are cached also in the browser.

As indicated above, using the “sites/all/modules/ckeditor/plugins” or “sites/all/modules/contrib/ckeditor/plugins”
will work with no additional custom hooks programming since by default CKEditor utilize that folder
in the CKEditor Global Profile Settings: “admin/config/content/ckeditor/editg”.

Adding Plugins As Stand Alone Module

The above approach requires the plugins to be part of the CKEditor Module, but it may not be desirable especially in case for distributing your custom module that requires one of the CKEditor plugin. In that case, its good idea to keep CKEditor plugins in stand alone module part of your custom module perhaps. Here is how to do so:

Lets say your custom module name is ‘custom-module’ and you are going to keep CKEditor plugins in sub-folder ‘ckeditor-plugins’, then the destination location would be:

After that, you should have the following folder structures:

2.) Hook Plugins Into CKEditor

Next, lets hook the plugins into CKEditor via hook_ckeditor_plugin as following in custom-module.module file:

/********CKEditor plugins********/
function custom-module_ckeditor_plugin()
    $module_path = drupal_get_path('module', 'custom-module');
    $plugins     = array();

    $plugins['leaflet'] = array(
        'name'    => 'leaflet',
        'desc'    => t(' CKEditor: Leaflet plugin'),
        'path'    => $module_path . '/ckeditor-plugins/leaflet/',
        'default' => 't',
        'buttons' => array(
            'leaflet' => array(
                'label' => 'Leaflet Map',
                'icon'  => 'icons/leaflet.png',

    $plugins['lineutils'] = array(
        'name'    => 'lineutils',
        'desc'    => t(' CKEditor: LineUtils plugin'),
        'path'    => $module_path . '/ckeditor-plugins/lineutils/',
        'default' => 't'

    $plugins['widget'] = array(
        'name'    => 'widget',
        'desc'    => t(' CKEditor: Widget plugin'),
        'path'    => $module_path . '/ckeditor-plugins/widget/',
        'default' => 't'

    return $plugins;

Here, the variable ‘name’ is as specified in the plugin.js that is part of all CKEditor Plugins (look for – CKEDITOR.plugins.add(“NAME”‘) – in the plugin.js for each plugin). The button index(highlight line) has to be exactly as specified in the plugin.js(look for ‘ui.addButton(“BUTTON-NAME”). The variable ‘icon’ specifies the location for the image of the button. Ensure it is there.

Afterwards, the plugins will show up in the CKEditor Configuration section(admin/config/content/ckeditor/edit/Full(or Advance). The rest is the same from the first approach where you would check the plugins in ‘Plugins’ section at admin/config/content/ckeditor/edit/Full(or Advance) and then move the icon into Toolbar.


1. Unable To Add Icons in Toolbar

Turn off the toolbar and add icons manually. To turn off the toolbar go to the admin/config/content/ckeditor/editg and select ‘disable’ for ‘Use toolbar Drag&Drop feature’. I am guessing that the toolbar misbehaves because CKEditor Module imports JQuery UI sortable lib that is already imported once by the core. As result, it causes js fatal errors. I am out of time to verify.

2. Uncaught TypeError: Cannot read property ‘icons’ of null

Ensure the name of the plugin as specified in the plugin.js(i.e. CKEDITOR.plugins.add(‘Here-comes-name’,) is the same used in the hook_ckeditor_plugin(). Set a break point with condition of ‘s === null’ where s is the variable the attribute ‘icons’ is called on(i.e s.icons) to help identified which plugin is causing issue in ckeditor.js



WYSIWYG with CKEditor in Drupal

It appears that CKEditor is the most advance and aesthetic WYSIWYG editor available for Drupal. As of February 2014, we run into issues installing the CKEditor as regular way WYSIWYG editors are installed in Drupal. In Part I, we summarize it. In the second part, we cover alternative integration of CKEditor as a stand alone editor

Install CKEditor Part of DRUPAL WYSIWYG

1. Enable WYSIWYG [wysiwyg] editors

To enable WYSIWYG editors in Drupal, install and enable wysiwyg module
With drush:

drush dl wysiwyg
drush en wysiwyg
2. Install Editor of your choice

Once module wysiwyg installed, then got to ‘admin/config/content/wysiwyg’ to see all the available wysiwyg editors with instructions how to install and enable any from the list.

We follow instruction and download the CKEditor library(in our case 4.3.2) from their site and extract it into the ‘site/all/libraries’ so that ‘ckeditor/ckeditor.js’ is as specified in the WYSIWYG configuration page.

After doing all this, the CKEDitor is not working and we have error:

The version of CKEditor could not be detected.

An alternative approach to install CKEditor as a separate module not part of WYSIWYG setup

Install CKEditor As Separate Module

Before continuing with this approach, make sure to disabale module – wysiwyg. The first step is as described above step 2 – Install Editor of Your Choice

A) Install the CKEditor Library

Download and past the CKEditor library into folder sites/all/libraries, so that ckeditor.js is in ‘sites/all/libraries/ckeditor/ckeditor.js’

B) Installing CKEditor Module

With Drush:

drush dl ckeditor
drush en ckeditor
C) Configure to use CKEditor for input fields

Go to admin/config/content/ckeditor/edit/Advanced or admin/config/content/ckeditor/edit/Full and ensure the checkbox ‘Text Formats’ for “Filtered HTML” or “Full HTML” is selected under ‘Basic Setup’ section.

For more custom configuration, go to ‘admin/config/content/ckeditor/’

D) Test Drive

Just open a node to ensure the editor is coming up for the input field with ‘full’ or ‘filter’ text formats

Other Stuff

Configure CKEditor Outside Drupal

If limited to what Drupal module – CKEditor configurations(admin/config/content/ckeditor) provides then you can configure CKEditor described in the CKEditor documentation native of CKEditor by updating the modules/ckeditor/ckeditor.config.js

For example:
To disable the advance auto filtering so that when CKEditor is enabled, it does not add and change extra html of the content:

CKEDITOR.editorConfig = function(config) {
    config.allowedContent = true;

This will disable the auto advance filtering. There other configurations to make like changing the color of the editor:

CKEDITOR.editorConfig = function(config) {
    config.uiColor = '#AADC6E';
Configure Allowed HTML Tags

To configure which html tags are allowed, consider to use wysiwyg_filter

sudo drush dl wysiwyg_filter
drush en wysiwyg_filter

Also uncheck ‘Limit allowed HTML tags’ in the Home » Administration » Configuration » Content authoring » Text formats

In addition, the CKEditor itself comes preconfigured to remove empty tags such span, em by default. Please see post Taking CKeditor Apart on how to avoid removing empty tags

Insert Photos in Content via IMCE Module

In order to insert photos in content via WYSIWYG, there is a Drupal Module called IMCE. To install and enable:

sudo drush dl imce
sudo drush en imce

This will install the necessary module to be able upload and insert photos via WYSIWYG editor in our case CKEditor

A) Make part of Image Dialog
The IMCE can be integrated in the CKEditor Image dialog. One of the benefits is that the functionality is add to current UI control(image button) so there is no need for additional buttons in the CKEditor Toolbar. Go to admin/config/content/ckeditor/edit/Full(or Advance) and select ‘IMCE’ for ‘File browser type (Image dialog window)’ in the section ‘FILE BROWSER SETTINGS’.

B)Make IMCE As Separate Control
The IMCE can be used as separate with its own button to upload files. To do that, check ‘Plugin for inserting files from IMCE without image dialog’ in the admin/config/content/ckeditor/edit/Full under ‘Plugins’ section. This will enable a separate IMCE button to be added to the CKEditor Toolbar.

Enhance Images to Resize, Align and Wrap text

With the newest version of CKEditor lib (4.4.0 and above) there is no more need for Drupal ckeditor_image module to have image enhancements such us resizing, aligning and wrapping text around. It comes out of box. You may want to combine the CKEditor Full source with plugin ‘Enhanced Image‘(image2) to have additional UI functionality for resizing by simply dragging a mouse.

Insert Photos in Content via Media & CKEditor_Media Module

Another module to insert images into content is Media. The benefit of using the Media module is that with ckeditor_media you are able to use the Media browser UI instead the CKEditor.
To install:

drush dl media
drush dl ckeditor_media
drush en media, ckeditor_media

Afterwards, configure the CKeditor toolbar to have the button for media browser by going to admin/config/content/ckeditor/edit/Full and drag/drop the media button.

Enabling CKEditor For Textarea

If you have custom form with textarea, then to enable the CKEditor, add the following:

          'some_textarea' => array(
            '#type' => 'text_format',
            '#format' => 'full_html',
            '#rows' => '5',
            '#prefix' => t('Content'),
            '#default_value' => variable_get('some_textarea', ''),

By adding ‘text_format’ and ‘full_html’ to the textarea element,it will trigger the CKEditor to load

Adding Theme Styles!/guide/dev_styles

How to Externalized CKeditor settings?

Thomas asked the question how to externalized CKeditor settings(ckeditor/ckeditor.config.js)
Here is list of alternative potential solutions:

      1. It is possible to force ckeditor to read config file from theme path instead of module path. Its a setting under ckeditor / advanced – and then you can just copy the custom config file into the theme folder.
      2. [NEED TO BE TESTED] Use hook_js_alter to replace default ckeditor with your custom one. See post How To Upgrade JQuery UI In Drupal for the same approach just instead altering jQuery lib you would alter ckeditor.config.js location.
      3. [NEED TO BE TESTED] If overlays are not used for admin content then you can have custom Js floated with your custom settings set on the CKEDITOR variable. See post Taking CKEditor a Apart and look how CKEditor is started from console. This should give you idea on how to call CKEditor API on CKEDITOR global js variable with your custom settings
      Note:I don’t remember anymore, was it because overlays are in separate iframe or because CKEditor Drupal module removes CKEDITOR global var on load that makes it unavailable for calling CKEditor API directly. That being said, the second approach may not work

The first approach is more for UI development, the second is more for Drupal developers and third is more JS developers that like to have it done in js instead within Drupal framework


1. Many of the CKEditor Toolbar buttons doesn’t show

Make sure you have installed the FULL CKEditor library and not the other two. If a particular button don’t show up then the plugin or the code for that functionality is not present

2. The text doesn’t show up in CKEditor

This may be because the text color of theme is white and with CKEditor background color being white as well, the text appears missing. By changing “Editor CSS” in admin/config/content/ckeditor/edit/TEXT_FORMAT to “CKEditor Default” will use the CKEditor Theme with text font of color black

3. IMCE doesn’t work

The IMCE needs to be configured to work for all users. Go to admin/config/media/imce and create profile. Afterwards, assign this profile to user role

The Upload, Insert File, Resize,etc Buttons Doesn’t Show Up In IMCE Browser

Make sure the permissions for the public dir is set correctly

Useful links

  • CKeditor Source