CKEditor widget example

by HugeHugh

HTML

<script src="http://ckeditor.com/apps/ckeditor/4.4.0/ckeditor.js"></script>
<textarea id="editor">
    <div class="tagSpecialClass">{{birthYear}}</div>
    <p>Some text.</p>
    <p>And there's the widget</p>
    <div class="tagSpecialClass">{{birthYear}}</div>
    <p>Some text.</p>
    <div class="tagSpecialClass">{{birthYear}}</div>
</textarea>

JavaScript

// Some CSS for the widget to make it more visible.
CKEDITOR.addCss( '.tagSpecialClass { background: green; padding: 3px; color: #fff } ' );

CKEDITOR.replace( 'editor', {
    // A clean-up in the toolbar to focus on essentials.
    toolbarGroups: [ 
        { name: 'document', groups: [ 'mode' ] },
        { name: 'basicstyles' },
        { name: 'insert' }
    ],
    removeButtons: 'Image,Table',
    extraPlugins: 'widget',
    on: {
        pluginsLoaded: function() {
            var editor = this;
            
            // Define a new widget. This should be done in a separate plugin
            // to keep things clear and maintainable.
            editor.widgets.add( 'sampleWidget', {
                // This will be inserted into the editor if the button is clicked.
                template: '<div class="tagSpecialClass">23</div>',
                
                // A rule for ACF, which permits span.tagSpecialClass in this editor.
                allowedContent: 'div(tagSpecialClass)',
                
                // When editor is initialized, this function will be called
                // for every single element. If element matches, it will be
                // upcasted as a "sampleWidget".
                upcast: function( el ) {
                    return el.name == 'div' && el.hasClass( 'tagSpecialClass' );
                },
                
                // This is what happens with existing widget, when
                // editor data is returned (called editor.getData() or viewing source).
                downcast: function( el ) {
                    el.setHtml( '{{birthYear}}' );
                },
                
                // This could be done in upcast. But let's do it here
                // to show that there's init function, which, unlike
                // upcast, works on real DOM elements.
                init: function() {
                    this.element.setHtml( '23' );
                }
            } );
           ...