H5P Guides

WYSIWYG Text Editor Buttons

In this short guide, we'll go through the process of adding extra buttons to the WYSIWYG text editor. This can be useful if you wish to allow a custom plugin in the text editor, or if you simply wish to add a formula editor.

Please note that when you're adding custom buttons on your site, other people might have issues downloading the content and using it on their site. This is because the custom HTML you allow on your site might not be allowed on theirs, i.e. it is stripped away for security reasons.

Let's say we want to add a button for inserting tables into the multichoice question type.

  1. We need a place in the CMS where we can put our custom code. This could be a plugin, module or theme. Modifying the H5P code is discouraged as you'll have issues upgrading and maintaining your patch. We recommend putting the code in a separate "mods" module or plugin, where you keep all the custom code for your CMS.
  2. See your CMS's documentation on how to create and set up a simple module or plugin, and activating it without any errors.
  3. Implement the "hook" that will modify the semantics of the content types.
    In Drupal this is done by naming convention, like so:
    function mymods_h5p_semantics_alter(&$semantics) {
      // Code that alters semantics goes here.
    Remember that in Drupal you have to clear the cache before the function starts working.
    On WordPress, you can add the same function, but you'll have to register it as an action listener:
    function mymods_h5p_semantics_alter(&$semantics) {
      // Code that alters semantics goes here.
    add_action('h5p_alter_library_semantics', 'mymods_h5p_semantics_alter');
  4. Inside the function, we need to look for text fields that use the html editor:
    function mymods_h5p_semantics_alter(&$semantics, $library_name = NULL) {
      // Check if this is the multichoice question type.
      if ($library_name !== 'H5P.Multichoice') {
        return; // Nope, do not continue.
      foreach ($semantics as $field) {
        // Go through list fields
        while ($field->type === 'list') {
          $field = $field->field;
        // Go through group fields
        if ($field->type === 'group') {
          mymods_h5p_semantics_alter($field->fields); // Check your function name!
        // Check to see if we have the correct type and widget
        if ($field->type === 'text' && isset($field->widget) && $field->widget === 'html') {
          // Found a field. Add support for table tags.
          if (!isset($field->tags)) {
            $field->tags = array();
          $field->tags = array_merge($field->tags, array(
  5. Now if you open up your H5P editor and select the multichoice question type, you should be able to insert tables! 

    Are you using a custom plugin? Then there's an additional step you'll have to take. This is because the table plugin is already built into the editor and you simply have to declare the tags. With a custom plugin, you'll have to add the plugin to CKEditor's config as well.

  6. You have to add a custom JS file that will add the extra plugin to the CKEditor config. This file might look something like this:
    (function ($) {
      $(document).ready(function () {
        if (!window.CKEDITOR) {
        // Register our plugin
        CKEDITOR.plugins.addExternal('cooltext', '/wp-content/plugins/mymods/cooltext');
        H5PEditor.HtmlAddons = H5PEditor.HtmlAddons || {};
        H5PEditor.HtmlAddons.text = H5PEditor.HtmlAddons.text || {};
        H5PEditor.HtmlAddons.text.cool = function (config, tags) {
          // Add the plugin.
          config.extraPlugins = (config.extraPlugins ? ',' : '') + 'cooltext';
          // Add plugin to toolbar.
            name: "cooltext",
            items: ['CooltextButton']
          // Add our special tag

    And in order for this file to load inside the H5P editor's iframe it has to be registered like this:

    Or if you're in Drupal you can add it through a hook which runs after the form has been built:
    function mymods_form_h5p_content_node_form_alter(&$form, &$form_state) {
      $form['#after_build'][] = 'mymods_h5p_content_node_form_after_build';
    function mymods_h5p_content_node_form_after_build($form, &$form_state) {
      $settings = array(
        'cooltextPath' => base_path() . drupal_get_path('module', 'mymods') . '/cooltext/',
        'h5peditor' => array(
          'assets' => array(
            'js' => array(
              drupal_get_path('module', 'mymods') . '/extraplugins.js'
      drupal_add_js($settings, 'setting');
      return $form;