Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to reinitialize a CKEditor Combobox/Drop Down Menu?

How do I dynamically update the items in a drop down?

I have a custom plugin for CKEditor that populates a drop down menu with a list of items which I can inject into my textarea.

This list of items comes from a Javascript array called maptags, which is updated dynamically for each page.

var maptags = []

This list of tags gets added to the drop down when you first click on it by the init: function. My problem is what if the items in that array change as the client changes things on the page, how can I reload that list to the updated array?

Here is my CKEditor Plugin code:

CKEDITOR.plugins.add('mapitems', {
    requires: ['richcombo'], //, 'styles' ],
    init: function (editor) {
        var config = editor.config,
        lang = editor.lang.format;       

        editor.ui.addRichCombo('mapitems',
        {
            label: "Map Items",
            title: "Map Items",
            voiceLabel: "Map Items",
            className: 'cke_format',
            multiSelect: false,

            panel:
            {
                css: [config.contentsCss, CKEDITOR.getUrl(editor.skinPath + 'editor.css')],
                voiceLabel: lang.panelVoiceLabel
            },

            init: function () {
                this.startGroup("Map Items");
                //this.add('value', 'drop_text', 'drop_label');
                for (var this_tag in maptags) {
                    this.add(maptags[this_tag][0], maptags[this_tag][1], maptags[this_tag][2]);
                }
            },

            onClick: function (value) {
                editor.focus();
                editor.fire('saveSnapshot');
                editor.insertHtml(value);
                editor.fire('saveSnapshot');
            }
        });
    } 
});
like image 823
user994689 Avatar asked Oct 14 '11 03:10

user994689


1 Answers

I think I just solved this actually.

Change your init like this:

init: function () {
                var rebuildList = CKEDITOR.tools.bind(buildList, this);
                rebuildList();
                $(editor).bind('rebuildList', rebuildList);
            },

And define the buildList function outside that scope.

var buildListHasRunOnce = 0;
        var buildList = function () {
            if (buildListHasRunOnce) {
                // Remove the old unordered list from the dom.
                // This is just to cleanup the old list within the iframe
                $(this._.panel._.iframe.$).contents().find("ul").remove();
                // reset list
                this._.items = {};
                this._.list._.items = {};
            }
            for (var i in yourListOfItems) {
                var item = yourListOfItems[i];
                // do your add calls
                this.add(item.id, 'something here as html', item.text);
            }
            if (buildListHasRunOnce) {
                // Force CKEditor to commit the html it generates through this.add
                this._.committed = 0; // We have to set to false in order to trigger a complete commit()
                this.commit();
            }
            buildListHasRunOnce = 1;
        };

The clever thing about the CKEDITOR.tools.bind function is that we supply "this" when we bind it, so whenever the rebuildList is triggered, this refer to the richcombo object itself which I was not able to get any other way.

Hope this helps, it works fine for me!

ElChe

like image 117
El Che Avatar answered Sep 28 '22 11:09

El Che