Leveraging CKeditor template to theme Drupal contents

February 1, 2014 | 3 Comments | Submitted by sivaji

WYSIWYG (a.k.a HTML Editor) has become a De facto for quickly formatting and publishing contents from dynamic site like Drupal. This is certainly a time saver and prevents from getting hands dirty with HTML.

In this connection, CKEditor has been a pioneer and around in use and development cycle for a decade (first release was on March 2003, in the name FCKeditor).

This solid and interesting tool plays good with Drupal content publishing system via Wysiwyg module. The recent CKEditor, version 4.2.x brings something more interesting to our desk. I'm talking about Templates plugin in specific.

Note: As of now this version of CKEditor requires dev version 2.x-dev of Wysiwyg contrib module.

Our project requirements were to create a Newsletters sending site with Drupal as base. (Having admired by Mailchimp, I considered this project as a trimmed version of the same).

Essentially we put together contrib modules - Simplenews, Mandrill, Wysiwyg (with CKEditor), Mime Mail and Media to get started. 

  • Simplenews for managing newsletter and subscription 
  • Mandrill for sending out emails via Web services
  • Wysiwyg for composing newsletter contents
  • and Media for Image handling 

Sounds cool! Isn't it?

Simplenews module offers a new content type newsletter. Essentially the body content of this node type is what sent out as newsletter to subscribers on cron run. The newsletter content to be composed using CKEditor buttons (and plugins). Each newsletter category had its own template (specific layout and Typography).

We initially thought of having dummy newsletter nodes for all templates in place and cloning the same whenever the actual newsletter to be sent. Along the way we noticed the Templates addition in CKEditor.

We thought it would be cool to have newsletter templates integrated with CKEditor button (like Media module does for Image). On further analysis we found that it would be possible to have our custom templates as well.

From official documentation it was found that adding the below snippet will add custom templates to CKEditor.

(Though the doc page says it is for 3.x but works good for 4.x as well),

// Register a template definition set named "default".
CKEDITOR.addTemplates( 'default',
{
    // The name of the subfolder that contains the preview images of the templates.
    imagesPath : CKEDITOR.getUrl( CKEDITOR.plugins.getPath( 'templates' ) + 'templates/images/' ),

    // Template definitions.
    templates :
        [
            {
                title: 'My Template 1',
                image: 'template1.gif',
                description: 'Description of My Template 1.',
                html:
                    '<h2>Template 1</h2>' +
                    '<p><img src="/logo.png" style="float:left" />Type your text here.</p>'
            },
            {
                title: 'My Template 2',
                html:
                    '<h3>Template 2</h3>' +
                    '<p>Type your text here.</p>'
            }
        ]
});

The above snippet to be added to mytemplates.js. In your CKEditor's config.js file need to mention that template file to use is as mytemplates.js.

Code for the same is below,

config.templates_files = [ '/mytemplates.js' ];

But Wysiwyg module didn't make use of config.js. However to suggest Wysiwyg to consider config.js we had to use the below hook_wysiwyg_editor_settings_alter() implementation in custom module. 

/**
 * Implements hook_wysiwyg_editor_settings_alter().
 */
function mymodule_wysiwyg_editor_settings_alter(&$settings, $context) {
  if ($context['profile']->editor == 'ckeditor') {
    // load template file content
    $data = array(
      'myModule' => array(
        'template_a' => theme('mymodule_email_template_a'),
        'template_b' => theme('mymodule_email_template_b'),
      ),
    );
    drupal_add_js($data, 'setting');        
    // Example of setting customConfig option. Just note it gets overridden by values in $settings.
    $settings['customConfig'] = 'config.js';
  }
}

As we can see, the above implementation suggests to obey the 'config.js' configuration file found in root folder of ckeditor library. 

In addition a call to drupal_add_js() can be noted. We used the same to pass the templates html to ckeditor as JavaScript variables. In fact these can be programmed directly in mytemplates.js too.

But passing from backend offers the following advantages,

  • clean HTML in template file / theme function (instead of having it as a Javascript's concatenated strings)
  • to add dynamic stuffs (tokens for instance to view email in brower, add unsubscribe link, etc.)
  • to leverage the Intercepts and Overrides of Drupal framework (preprocess function for instance)

After all these steps the updated mytemplates.js looks as below,

/**
 * Define custom templates for Winprijzen and Gratis newsletter
 */
CKEDITOR.addTemplates('default', {
    // The name of the subfolder that contains the preview images of the templates.
    imagesPath : CKEDITOR.getUrl( CKEDITOR.plugins.getPath( 'templates' ) + 'templates/images/' ),
    // Template definitions.
    templates :
        [
            {
                title: 'Template A',
                image: 'template_a.gif',
                description: 'Description of Template A',
                html: Drupal.settings.myModule.template_a
            },
                  {
                title: 'Template B',
                image: 'template_b.gif',
                description: 'Description of Template B',
                html: Drupal.settings.mdModule.template_b
            }
        ]
});

Now clicking the Templates Button in CKEditor will offer to select custom templates, similar to above snapshot.

Comments

3 Comments

Great post, Sivaji. At LevelTen, we've been experimenting with CK Editor and tight integrations with Bootstrap 3. We are using Content Templates and additional widgets for CK Editor including one-click sliders, hero banners, featurettes, tri-folds, etc. Like you, we are finding that page layouts become much faster and you remove many of the frustrations found with Panels.

Keep up the good work!

Great blog post! Though, what I found missing is actual content of theme functions - mymodule_email_template_a and mymodule_email_template_b (some tpl.php content). It would be practical if you add some examples of how you done that for your use case.

Anyway, thanks for sharing.

It is worth to mention that there is already a Drupal module using integrating the templates functionality - https://drupal.org/project/wysiwyg_template