Advanced examples - lokothodida/ckeditor-plugin-template GitHub Wiki

Index

CSS

Styling your dialog

CKEditor dialogs are wrapped in an enormous number of <div>s, <span>s and <table>s in order to maintain their appearances. The UI elements are built using the logic of the editor rather than the developer (i.e. you do not need to write out the markup for a text field to put a text field into your dialog). CSS IDs are generated dynamically, and this leads to the problem that styling an individual plugin's dialog can be very cumbersome.

Luckily, the boilerplate makes this process a bit easier.

your-plugin/dialogs/main.js

...
// tabs
contents: [ /**/ ],


// fired when the dialog loads for the first time
onLoad: function() {
  // add id for easier styling of elements in the dialog
  $(this.getElement()).attr('id', plugin.dialog);
},
...

This takes the main dialog <div> and gives it the id plugin.dialog (which you defined in the plugin object in the your-plugin/plugin.js file (e.g. yourPluginDialog). You can thus namespace your CSS from this id to ensure that the only elements affected are ones in your dialog:

#yourPluginDialog {
  /* main dialog */
}
#yourPluginDialog input {
  /* all input fields in your plugin's dialog */
}

JavaScript

Loading external JavaScript in your dialog

The CKEDITOR.scriptLoader.load() method allows you to load scripts asynchronously. You must be careful with your code however, as the methods and variables from those scripts may not be immediately available.

Example

path/to/external/js/default-values.js

var defaultValueAttribute1 = 'Some text';

your-plugin/dialogs/main.js

...
// attribute-1 field
{
  // ...
  id: 'attribute-1',
  default: defaultValueAttribute1; // ReferenceError: defaultValueAttribute1 is not defined
  // ...
},
...

An error thrown here will prevent the dialog from loading altogether. You must wait for the dialog to load for the variables to safely exist without throwing errors.

Fix

...
// attribute-1 field
{
  // ...
  id: 'attribute-1',
  className: 'attribute-1', // for selecting the field more easily
  onLoad: function() {
    $('#' + plugin.dialog + ' .attribute-1 input').val(defaultValueAttribute1);
  },
  // ...
},
...

So to safely use your loaded scripts, only use those variables in the onLoad() method of the main dialog and dialog fields.

It is also worth noting that variables loaded with CKEDITOR.scriptLoader.load() are put into the global scope. To avoid clashes with other scripts and other plugins, either:

  • Keep your variable names descriptive
  • Namespace your variables
  • Use immediately invoked expressions to shield way possible clashes and only push the required variables/functions into the global scope

Adding helper functions

If you are running procedures in your dialogs that take more than a few lines (and particularly if the code is going to be repeated elsewhere), it makes sense to wrap up that procedure in a function. As noted above, if you load the function with the scriptLoader, it will be put into the global scope, and possible solutions to name-clashing are given.

In the your-plugin/js folder, you will have a helper object that is namespaced by YourPlugin which you can safely add methods to. The API describes how to set up this object.

Example of adding a method to the YourPlugin object

/your-plugin/js/helper-methods.js

var _YourPlugin = function(path) {
...
  this.yourMethod = function(/* params */) {
    /*  */
  };
...
};

/your-plugin/dialogs/main.js

...
// fields
...
{
  // description field
  id: 'description',
  type: 'html',
  html: '',
  className: 'description', // for selecting the field more easily
  onLoad: function() {
    YourPlugin.yourMethod(/* params */);
  },
},
...

Using jQuery plugins on fields

You may want to use jQuery UI or various other plugins to improve the UI elements of CKEditor and provide more functionality to your fields (e.g. a datepicker or improved dropdowns).

Simply load the script with the scriptLoader, then apply the functionality in the onLoad() method definition.

Datepicker example

...
// load jQuery UI css
CKEDITOR.document.appendStyleSheet('//code.jquery.com/ui/jquery-ui-git.css');

// load jQuery UI script
CKEDITOR.scriptLoader.load('//code.jquery.com/ui/1.11.1/jquery-ui.js');

...

    // your field
    {
      // ...
      id: /* */,
      type: 'text',
      className: 'some-attribute', // for jQuery selector below
      onLoad: function() {
        $('#' + plugin.dialog + ' .some-attribute input').datepicker(/* */);
      },
      // ...
    },
...

HTML

Loading HTML into your dialog

CKEditor provides an 'html' field type that lets you provide your own HTML markup in place of a field.

...
// field example
{
  ...
  id: /* */,
  type: 'html',
  html: /* your html string */,
  ...
},
...

It is messy to have to deal with HTML markup as a string inside of JavaScript (i.e. concatenating a series of strings). Ideally, one would want to keep the HTML completely separate. This is possible by using AJAX to call your desired HTML file. Put the HTML in your-plugin/html/ and do the following:

...
// field example
{
  ...
  id: /* */,
  type: 'html',
  className: 'your-html-field', // used for jQuery selector below
  html: '',
  onLoad: function() {
    // path is defined at the beginning of the main.js file
    var file = path + 'html/your-html-markup.html';

    // ajax loads the contents of the file into the div
    $('#' + plugin.dialog + ' .your-html-field').load(file);
  }
  ...
},
...

If you wish to load the HTML synchronously instead:

...
// field example
{
  ...
  id: /* */,
  type: 'html',
  className: 'your-html-field',
  html: '',
  onLoad: function() {
    // path is defined at the beginning of the main.js file
    var file = path + 'html/your-html-markup.html';

    // ajax loads the contents of the file into the div
    $.ajax({
      url: file,
      dataType: 'html',
      async: false,
      success: function(html) {
        $('#' + plugin.dialog + ' .your-html-field').html(html);
      },
      error: function() {
        // error handling (e.g. display an error for your user)
      },
    });
  }
  ...
},
...

The API also describes how to use the helper YourPlugin object's getHTML() method to achieve this.

⚠️ **GitHub.com Fallback** ⚠️