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>
    //--OR--
    <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:

    if(window.CKEDITOR){
                    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 node.name == 'a' && node.attributes.href || CKEDITOR.dtd.$removeEmpty[ node.name ];
    		return CKEDITOR.dtd.$removeEmpty[ node.name ];
    	}
    

    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:
    http://ckeditor.com/forums/CKEditor/How-to-stop-removing-empty-anchor-element

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:

    if(window.CKEDITOR){
                    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:

if(window.CKEDITOR){
                CKEDITOR.on('instanceCreated', function (ev) {
                    CKEDITOR.config['autoParagraph'] = false
                    
                    //or for certain editor instance
                    if (ev.editor.name == 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:

if(window.CKEDITOR){
                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:

if(window.CKEDITOR){
                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:
    if(window.CKEDITOR){
                    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

Leave a Reply

Your email address will not be published. Required fields are marked *