CKEditor Plugin to Embed D3 Viz in Drupal
The Drupal module Embed Block allows embedding blocks in CKEditor. But I needed a way to both provide a button with dialog and to control what kinds of blocks are embedded.
Controller, Router, Dialog, Plugin
The following controller passes the list of allowed blocks:
<?php
...
public function getVizBlocks(Request $request) {
// Get config settings.
$config = ??
$block_field_manager = \Drupal::service('block_field.manager');
$definitions = $block_field_manager->getBlockDefinitions();
$selected_viz_blocks = [];
foreach ($definitions as $id => $definition) {
if ($definition['provider'] === 'mymodule') { // Only blocks provided by our custom module
if (!empty($config->get('allowed_viz.' . $id))) {
$selected_viz_blocks[] = $id;
}
}
}
return new JsonResponse($selected_viz_blocks);
}
A router like /mymodule/blocks
that points to the above controller and method would return a JSON object with the block names. And this route can be called by our CKEditor dialog (shown below) to allow the user to select a block:
(function ($, Drupal, drupalSettings) {
CKEDITOR.dialog.add('mypluginDialog', function (editor) {
// Get allowed list.
let options = [];
$.ajax({
type: "GET",
url: '/mymodule/blocks',
success: function (result) {
options = result;
},
async: false,
cache: false
});
// Queue select list.
let items = [];
$.each(options, function (key, value) {
items.push(...some array here...);
});
return {
title: 'Add a visualization',
contents: [
{
id: 'tab-basic',
elements: [
{
},
]
}
],
onShow: function () {
},
onOk: function () {
}
};
});
})(jQuery, Drupal, drupalSettings);
Finally, we need a plugin that calls this dialog:
(function ($, Drupal, drupalSettings) {
CKEDITOR.plugins.add('myplugin', {
requires: 'dialog',
init: function (editor) {
editor.addCommand('viz', new CKEDITOR.dialogCommand('mypluginDialog'));
editor.ui.addButton('viz', {
label: 'Add viz block',
command: 'viz',
icon: this.path + 'images/viz.png'
});
CKEDITOR.dialog.add('mypluginDialog', this.path + 'dialogs/myvizplugin.js');
}
});
})(jQuery, Drupal, drupalSettings);
Of course, we will need a few other things to complete this, including a settings form to manage allowed blocks, a filter to replace the tokens with a block, the CKEditor plugin definition (that points to the library), and an image for the CKEditor button.