hpique
hpique

Reputation: 120334

Change CKEditor toolbar dynamically

How do you change the CKEditor toolbar dynamically (without using a pre-defined toolbar)?

The CKEditor Developer's Guide only tells you how to set the toolbar during initialization.

I'm using CKEditor 3.6.4.

Upvotes: 15

Views: 30624

Answers (10)

ThangTD
ThangTD

Reputation: 1684

Or:

   $(document).ready(function() {
      CKEDITOR.config.customConfig = 'configSimple';
   }); 

   //the configSimple.js file is the same folder with config.js

Upvotes: 1

Mitja Gustin
Mitja Gustin

Reputation: 1781

You can create toolbar dynamically as you like. I found that the best approach is to listen to CKE events regarding instance creation.

CKEDITOR.on('instanceCreated', function(event) {
    var editor = event.editor;
    editor.config.toolbar = [
        { name: 'basicstyles', groups: [ 'basicstyles'], items: [ 'Bold', 'Italic','Subscript', 'Superscript' ] },
    ]; // could be from synchronous!!! XHR as well 
});

CKEDITOR.on('instanceReady', function(event) {
    var editor = event.editor;
    editor.config.toolbar = [
        { name: 'basicstyles', groups: [ 'basicstyles'], items: [ 'Bold', 'Italic','Subscript', 'Superscript' ] },
    ];
});

Upvotes: 0

Guest
Guest

Reputation: 1

I am assuming you want to add button via plugin file. Here is how. Add your button to ui.

editor.ui.addButton('ButtonName', {
  label: lang.lockediting.locked,
  icon: this.path + 'icons/locked.png',
  command: 'lockediting'});

Then you can push ButtonName to toolbar.

//Here it is pushed as a new group
editor.config.toolbar.push(['ButtonName']);

If you check console.log(editor.config.toolbar); you will see toolbar ise an object with toolbar groups as arrays [Array[10], Array[2], Array[5]]. [Array[10] means there are 10 button in first group. You can push your button into any of those arrays.

Upvotes: 0

jnl
jnl

Reputation: 447

If you want a simple way to swap toolbars in different areas, all you need to do is add the toolbars to the config, then select the one you want when you instantiate the editor.

In config.js:

CKEDITOR.editorConfig = function(config)
{
// default toolbar
config.toolbar = [
    { name: 'source',       items: [ 'ShowBlocks', 'Source' ] },
    { name: 'clipboard',    items: [ 'Undo', 'Redo', '-', 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord'  ] },
    { name: 'editing',      items: [ 'Find', 'Replace', 'SelectAll', 'Scayt' ] },

    { name: 'p2',           items: [ 'Blockquote', 'Outdent', 'Indent', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
    { name: 'links',        items: [ 'Link', 'Unlink', 'Anchor' ] },
    { name: 'paragraph',    items: [ 'NumberedList', 'BulletedList' ] },
    { name: 'insert',       items: [ 'CreatePlaceholder', 'CreateDiv', 'Image', 'Table', 'HorizontalRule', 'SpecialChar', 'Iframe' ] },

    //{ name: 'styles',         items: [ 'Styles', 'Format' ] },
    { name: 'basicstyles',  items: [ 'Bold', 'Italic', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
    { name: 'styles',       items: [ 'Format' ] },
    { name: 'morestyles',   items: [ 'Font', 'FontSize' ] },
    { name: 'colors',       items: [ 'BGColor', 'TextColor' ] }
];

// here is one custom toolbar
config.toolbar_mycustom1 = [
    { name: 'source',       items: [ 'ShowBlocks', 'Source' ] },
    { name: 'clipboard',    items: [ 'Undo', 'Redo', '-', 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord'  ] },
    { name: 'editing',      items: [ 'Find', 'Replace', 'SelectAll', 'Scayt' ] }
];

// here is another custom toolbar
config.toolbar_mycustom2 = [
    { name: 'styles',       items: [ 'Format' ] },
    { name: 'morestyles',   items: [ 'Font', 'FontSize' ] },
    { name: 'colors',       items: [ 'BGColor', 'TextColor' ] }
];

// ...other config vars here

In your page where you instantiate a editor instance do so this way:

<script>
    CKEDITOR.replace('MyObject', {toolbar: 'mycustom2'});
</script>

Upvotes: 0

Sami Viitala
Sami Viitala

Reputation: 81

According to [CKEditor documentation][1] they have given up the concept of 'theme' and thus the 'loadToolbar()' method mentioned above have to be modified a bit to work with the newest version of CKEditor.

This worked for me (CKEditor 4.4.4):

CKEDITOR.editor.prototype.setToolbar = function(tbName) {
		if (!this._.events.themeSpace) {
		  CKEDITOR.plugins.registered.toolbar.init(this);
		// causes themeSpace event to be listened to.
		}
		// If a different toolbar was specified use it, otherwise just reload
		if (tbName){
			this.config.toolbar = tbName;
		}
		//According to CKEditor documentation
		var obj = this.fire( 'uiSpace', { space: 'top', html: '' } ).html;
		console.log("Received from themespace:");
		console.log(obj);
		// Replace the toolbar HTML 
		var tbEleId = this.id +"_" + this.config.toolbarLocation;
		console.log("Editor element id: " + tbEleId);
		var tbEle = document.getElementById(tbEleId);
		//tbEle.innerHTML = obj.html;
		$(tbEle).html(obj);
      }
[1]: http://docs.ckeditor.com/#!/guide/dev_api_changes

Upvotes: 3

pgee70
pgee70

Reputation: 3984

for me at least this got a little complicated....

and to answer the question i thought i would share the working code.

i have a user-defined snippets of text -- known as templates in ckeditor parlance i needed to load in. i also dynamically change the toolbar depending on the window width, and dynamically resize on window resize. each browser size gets its own custom toolbar. (XS,SM,MD) . i expect all elements with a CKEDITOR have a class of .ckeditor and they have an ID assigned. Additionally i have an on blur ajax save handler set up, so on loss of focus the control is automatically saved (via the ajax_post function) if required.

I call the procedure using setupCKEdit. thanks to hpique for the inspiration of removing the old object and creating a new instance. on the resize event i do this with a slight delay (resizeTimeout= 200msec), so it doesn't fire so often whilst changing the window size.

// ********* ck editor section starts **************

var resizeTimeout;
var ckeditorXSToolbar = Array(
    { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste','-', 'Undo', 'Redo' ] },
    { name: 'document', groups: [ 'mode' ], items: [ 'Source'] },
    { name: 'tools', items: [ 'Maximize'] },
    { name: 'styles', items: [ 'Format', 'Font', 'FontSize'] ,class:'hidden-xs'},
    { name: 'basicstyles', groups: [ 'basicstyles'], items: [ 'TextColor','Bold', 'Italic'] }

);

var ckeditorSMToolbar = [
    { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize'] ,class:'hidden-xs'},
    { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
    { name: 'editing', groups: [ 'find', 'selection' ], items: [ 'Find', 'Replace', '-', 'SelectAll' ] },
    { name: 'document', groups: [ 'mode', 'document', 'doctools' ], items: [ 'Source', '-', 'Save', 'NewPage', 'Preview', 'Print'] },

    { name: 'forms', items: [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
    { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'TextColor','Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
    { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl', 'Language' ] },
    { name: 'tools', items: [ 'Maximize', 'ShowBlocks' ] }
];
var ckeditorMDToolbar = [
    { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize'] ,class:'hidden-xs'},
    { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
    { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ], items: [ 'Find', 'Replace', '-', 'SelectAll', '-', 'Scayt' ] },
    { name: 'document', groups: [ 'mode', 'document', 'doctools' ], items: [ 'Source', '-', 'Save', 'NewPage', 'Preview', 'Print'] },

    { name: 'forms', items: [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
    { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'TextColor','Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
    { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl', 'Language' ] },
    { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
    { name: 'insert', items: [ 'Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe' ] },

    { name: 'tools', items: [ 'Maximize', 'ShowBlocks' ] },
    { name: 'others', items: [ '-' ] },
    { name: 'about', items: [ 'About' ] }
];

function setupCKEdit(selector){
    if (typeof(o.snippets) == 'object'){
        var template = {
            imagesPath:url_img ,
            templates: o.snippets
        };
        CKEDITOR.addTemplates('myTemplate', template);
    }   
    resizeCKEdit();

    $('.ckeditor',selector).not('.hasCKEDITOR').each(function(index,element){
        $(this).addClass('hasCKEDITOR');
        var ckConfig = {
            templates_replaceContent:false,
            scayt_slang:'en_GB',
            scayt_autoStartup:scayt_autoStartup,
            toolbarCanCollapse:true,
            extraPlugins:'templates,colorbutton',
            toolbar:getCKtoolbar(),
            toolbarStartupExpanded:getCKToolbarStartup()
        };
        // inject the snippets after the toolbar[].name = 'document'
        if (typeof(o.snippets) == 'object'){
            ckConfig.templates = 'myTemplate';
            for(var i = 0 ; i < ckConfig.toolbar.length ; i++){
                if (ckConfig.toolbar[i].name == 'document'){
                    // iterate throught each document element to make sure template is not already there.
                    var hasTemplate = false;
                    for ( var j = 0 ; j < ckConfig.toolbar[i].items.length; j++){
                        if (ckConfig.toolbar[i].items[j] == 'Templates'){
                            hasTemplate = true;
                        }
                    }
                    if (hasTemplate == false){
                        ckConfig.toolbar[i].items.push('-'); // add to documents group.
                        ckConfig.toolbar[i].items.push('Templates');
                    }

                }
            }           
        }
        $(this).ckeditor(ckConfig);
        var editor = CKEDITOR.instances[this.id];
        if(typeof(editor) == 'object'){
            editor.on('blur',function(event){
                if (event.editor.checkDirty()){
                    var ta = $('#'+event.editor.name); // ta = textarea
                    if ( (typeof(ta) == 'object')
                        && (typeof(ta[0]) == 'object')
                        && ( $(ta[0]).hasClass('noajax') == false )
                        && ( $(ta[0]).data('id')) 
                        && ( ta[0].name)) {
                        var data = {
                            field_name:ta[0].name,
                            field_value:event.editor.getData(),
                            id:$(ta[0]).data('id')
                            };
                        data[ta[0].name]=event.editor.getData();
                        ajax_post(url_ajax + 'update_field', data);
                        event.editor.resetDirty();
                    }
                }
            });
        }
    });
}
function getCKtoolbar(){
    // returns the CK editor toolbar array based on window width
    var dw = $(document).width();
    if (dw < 768){
        return ckeditorXSToolbar;
    } else if(dw < 991){
        return ckeditorSMToolbar;
    }
    else {
        return ckeditorMDToolbar;
    }
}

function getCKToolbarStartup(){
    // returns the toolbarStartupExpanded parameter, based on window width
    var dw = $(document).width();
    if (dw < 768){
        return false;
    } else if(dw < 991){
        return true;
    }
    else {
        return true;
    }
    return true;
}
function resizeCKEdit(){
    // when there is a document resize, update the toolbar buttons.
    if ($('body').data('resize_enabled') == undefined){
        $('body').data('resize_enabled',true);
        $(window).resize(function(event){
            // only do the reize 100msec after the resizing finishes.
            window.clearTimeout(resizeTimeout);
            resizeTimeout = window.setTimeout(function(){

            // iterate through all CKEDITOR instances, and update their toolbars.
                var ckConfig = {
                    templates_replaceContent:false,
                    scayt_slang:'en_GB',
                    scayt_autoStartup:scayt_autoStartup,
                    toolbarCanCollapse:true,
                    extraPlugins:'templates,colorbutton',
                    toolbar:getCKtoolbar(),
                    toolbarStartupExpanded:getCKToolbarStartup()
                };
                if (CKEDITOR.editor.length){
                    // need to get all instances before deleting them,
                    var instances = Array();
                    var i = 0;
                    for (var instance in CKEDITOR.instances) {
                        instances[i] = instance;
                        i++;
                    }
                    for (i = 0 ; i < instances.length ; i ++){
                        CKEDITOR.instances[instances[i]].destroy();
                        $('#'+instances[i]).removeClass('hasCKEDITOR');
                        setupCKEdit($('#'+instances[i]).parent());
                    }
                }
            },200);

        });
    }
}
// ********* ck editor section ends **************

Upvotes: 1

shasi kanth
shasi kanth

Reputation: 7094

var editor = CKEDITOR.instances['text_id'];
if (editor) { editor.destroy(true); }

CKEDITOR.config.toolbar_Basic = [['Bold','Italic','Underline',
'-','JustifyLeft','JustifyCenter','JustifyRight','-','Undo','Redo']];
CKEDITOR.config.toolbar = 'Basic';
CKEDITOR.config.width=400;
CKEDITOR.config.height=300;
CKEDITOR.replace('text_id', CKEDITOR.config);

Upvotes: 8

user2173985
user2173985

Reputation: 11

Just a quick one.

You may need to add this line to the loadToolbar function if your toolbar contains the textcolor and/or backgroundcolor buttons:

//Need to call init for colorbutton so that we can re-draw the color buttons
CKEDITOR.plugins.registered.colorbutton.init(this);

Upvotes: 1

Ribo
Ribo

Reputation: 3429

You can reload or change the toolbar, without reloading the editor, with this code:

  CKEDITOR.editor.prototype.loadToolbar = function(tbName) {
    // If the 'themeSpace' event doesn't exist, load the toolbar plugin
    if (!this._.events.themeSpace) {
      CKEDITOR.plugins.registered.toolbar.init(this);
    // causes themeSpace event to be listened to.
    }
    // If a different toolbar was specified use it, otherwise just reload
    if (tbName) this.config.toolbar = tbName;

    // themeSpace event returns a object with the toolbar HTML in it
    var obj = this.fire( 'themeSpace', { space: 'top', html: '' } );

    // Replace the toolbar HTML 
    var tbEleId = "cke_"+this.config.toolbarLocation+"_"+this.name;
    var tbEle = document.getElementById(tbEleId);
    tbEle.innerHTML = obj.html;
  } // end of loadToolbar

Adding the function the the editor.prototype makes it a method of any editor instance. Your editor object is probably CKEDITOR.instances.editor1

The argument to loadToolbar is the name of the toolbar to load, or if null, the current toolbar is reloaded. The name of the current toolbar is in CKEDITOR.instances.editor1.config.toolbar. If you specify toolbar 'foo' then there must be a CKEDITOR.instances.editor1.config.toolbar_foo array that defines the contents of the toolbar.

You can add or remove things from the current toolbar array of arrays variable and then cause it to be reloaded with: edObj.loadToolbar(null);


(Meta issue not affecting the method above: I don't understand why the listeners for the 'themeSpace' event go away after the editor originally loads the theme. (The toolbar plugin init() method does an event.on("themeSpace"...) but the listens go away after the editor is intialized. I didn't see where it did a removeListener(). So the call ...toolbar.init(this) was needed to restablish those event listeners so the toolbar code would rebuild the new toolbar.)

Upvotes: 3

hpique
hpique

Reputation: 120334

Following mb21's suggestion I managed to load a new toolbar by reinitialising the whole editor:

CKEDITOR.instances.editor.destroy();
CKEDITOR.replace('editor', configWithNewToolbar);

Upvotes: 10

Related Questions