Insert images from CKEditor

I have spent over 7 hours trying to understand the instructions in this post in order to add an image button to the WYSIWYG editor in the 'Task description' field for all activity modules. I would love to assist in improving the documentation on this post by creating a video tutorial for the benefit of the community, once I understand the correct steps.

All I am trying to do is get an image button on the WYSIWYG editor (or even just a way to enter direct HTML so that I can write the image code myself) and I really didn't think it would be this difficult... Here are the steps I have taken so far based on my interpretation of the instructions and comments on this page: 

1. I had already created a 'h5pmods' plugin in Wordpress to enable custom css (as per the instructions here) which is located on my server at .../wp-content/plugins/h5pmods. So I followed up to Step 5 from this post and added the following code to the h5pmods.php file. This part was easy – I successfully created a table button on the toolbar which is a good starting point — but after 7 hours it's unfortunately still my end point! :(

function h5pmods_h5p_semantics_alter(&$semantics) {

  foreach ($semantics as $field) {

    // Go through list fields

    while ($field->type === 'list') {

      $field = $field->field;

    }

    // Go through group fields

    if ($field->type === 'group') {

      h5pmods_h5p_semantics_alter($field->fields); // Check function name!

      continue;

    }

    // Check to see if we have the correct type and widget

    if ($field->type === 'text' && isset($field->widget) && $field->widget === 'html') {

      // Found a wysiwyg/CKEditor field. Add image button.

      if (!isset($field->tags)) {

        $field->tags = array();

      }

      if (!in_array('table', $field->tags)) {

        $field->tags[] = 'table';

      }

    }

  }

}

add_action('h5p_alter_library_semantics', 'h5pmods_h5p_semantics_alter');

 

2. I saw the comment by fnok here which said that 'img' was one of the built-in tags in H5P, and I noted the code provided by JRDingwall here which successfully included the 'img' tag (noting the corrections by icc here regarding the straight quotation marks). So I tried the following code instead: 

function h5pmods_h5p_semantics_alter(&$semantics) {

  foreach ($semantics as $field) {

    // Go through list fields

    while ($field->type === 'list') {

      $field = $field->field;

    }

    // Go through group fields

    if ($field->type === 'group') {

      h5pmods_h5p_semantics_alter($field->fields); // Check function name!

      continue;

    }

    

    // Check to see if we have the correct type and widget

    if ($field->type === 'text' && isset($field->widget) && $field->widget === 'html') {

      // Found a wysiwyg/CKEditor field. Add image button.

      if (!isset($field->tags)) {

        $field->tags = array();

      }

      if (!in_array('table', $field->tags)) {

        $field->tags[] = 'table';

      }

      if (!in_array('img', $field->tags)) {

        $field->tags[] = 'img';

      }

    }

  }

}

add_action('h5p_alter_library_semantics', 'h5pmods_h5p_semantics_alter');

 

3. Unfortunately this did not work, even though it worked for JRDingwall. I then noted thomasmars' comment here stating that the Image plugin is actually not bundled with CKEditor, despite the previous comments saying that it was built-in. So I then had to proceed to Step 6 in the post instructions regarding adding an external plugin. 

4. I had no idea where to find this external plugin as this was not explained in the post. After much confusion about what to do next, I tried downloading the Image plugin here and uploaded it to my server in the same folder as my h5pmods plugin (so it's at .../wp-content/plugins/h5pmods/image/). 

5. Next, I was unsure where to find the extraplugins.js file as it was not clear in the instructions. So I thought I would try creating this file myself because I thought maybe that's what was intended... So I created a javascript file called extraplugins.js containing the code below and uploaded it to my /wp-content/plugins/h5pmods/ folder. I used the same code provided in Step 6 in the instructions, but just replaced 'cooltext' with 'Image', and replaced the URL with the URL on my server pointing to the Image plugin that I uploaded. 

(function ($) {

  $(document).ready(function () {

    if (!window.CKEDITOR) {

      return;

    }

  
    // Register our plugin

    CKEDITOR.plugins.addExternal('image', '/wp-content/plugins/h5pmods/image/plugin.js');

    H5PEditor.HtmlAddons = H5PEditor.HtmlAddons || {};

    H5PEditor.HtmlAddons.image = H5PEditor.HtmlAddons.text || {};

    H5PEditor.HtmlAddons.image.image = function (config, tags) {

      // Add the plugin.

      config.extraPlugins = (config.extraPlugins ? ',' : '') + 'image';

  
      // Add plugin to toolbar.

      config.toolbar.push({

        name: "image",

        items: ['image']

      });

  
      // Add our special tag

      tags.push('image');

    };

  });

})(H5P.jQuery);

 

6. Next, I tried to follow the instructions that said "in order for this file to load inside the H5P editor's iframe it has to be registered like this: H5PEditor.assets.js.push('/wp-content/plugins/mymods/extraplugins.js'); But I had no idea where to put this script! I noted that phaqlancs had the same question here and thomasmars advice here was to find and add an alter scripts code to load a separate javascript file. So I tried adding this to my h5pmods.php file: 

function h5pmods_alter_scripts(&$scripts, $libraries, $embed_type) {

  $scripts[] = (object) array(

    // Path can be relative to wp-content/uploads/h5p or absolute.

    'path' => '/wp-content/plugins/h5pmods/extraplugins.js',

    'version' => '?ver=1.0' // Cache buster    

  );

 }

add_action('h5p_alter_library_scripts', 'h5pmods_alter_scripts', 10, 3);

 

7. After this didn't work, I searched around for any other articles which might explain where to insert the script: H5PEditor.assets.js.push('/wp-content/plugins/mymods/extraplugins.js'. The only help I could find was this thread here by FJRonH5P who had the same question (but in relation to the sourcearea plugin not the image plugin). Since there was actually some advice on this post, I decided to download the sourcearea plugin, upload it to my website and follow the advice in this thread to see if it would work for the datasource plugin. I thought, "At least if this works, I can just insert an image directly through HTML code instead!" So I followed the advice from osa19 here and updated the content of the extraplugins.js file to refer to 'Source'. This is the code that was in my extraplugins.js file: 

(function ($) {
  $(document).ready(function () {
    if (!window.CKEDITOR) {
      return;
    }
 
    // Register our plugin
    CKEDITOR.plugins.addExternal('sourcearea', '/wp-content/plugins/h5pmods/sourcearea/plugin.js');
    H5PEditor.HtmlAddons = H5PEditor.HtmlAddons || {};
    H5PEditor.HtmlAddons.image = H5PEditor.HtmlAddons.text || {};
    H5PEditor.HtmlAddons.image.sourcearea = function (config, tags) {
      // Add the plugin.
      config.extraPlugins = (config.extraPlugins ? ',' : '') + 'sourcearea';
 
      // Add plugin to toolbar.
      config.toolbar.push({
        name: "sourcearea",
        items: ['Source']
      });
 
      // Add our special tag
      tags.push('sourcearea');
    };
  });
})(H5P.jQuery);

 

And I followed icc's advice here to insert the script straight into the h5pmods.php file (wrapped in the footer) and updated the h5pmods.php file to include the tag for the sourcearea plugin. So my h5pmods.php file looked like this: 

/*Add extra buttons
*/

function h5pmods_h5p_semantics_alter(&$semantics) {
    
  foreach ($semantics as $field) {
    // Go through list fields
    while ($field->type === 'list') {
      $field = $field->field;
    }
   
    // Go through group fields
    if ($field->type === 'group') {
      h5pmods_h5p_semantics_alter($field->fields); // Check function name!
      continue;
    }
   
    // Check to see if we have the correct type and widget
    if ($field->type === 'text' && isset($field->widget) && $field->widget === 'html') {
      // Found a wysiwyg/CKEditor field. Add image button.
      if (!isset($field->tags)) {
        $field->tags = array();
      }
      $field->tags = array_merge($field->tags, array(
        'table',
        'thead',
        'tfoot',
        'tbody',
        'tr',
        'th',
        'td',
        'div',
        'span',
        'p',
        'sourcearea'
      ));
      }
    }
  }
add_action('h5p_alter_library_semantics', 'h5pmods_h5p_semantics_alter');


/*Add it to the toolbar*/

function h5pmods_admin_footer() {
  wp_add_inline_script('h5p-editor', 
"H5PIntegration.editor.assets.js.push('https://lingobango.com/wp-content/plugins/h5pmods/extraplugins.js');");
}
add_action('admin_footer', 'h5pmods_admin_footer');

 

I then tried replacing the URLs in the PHP and Javascript file with absolute URLs instead of relative and this still did not work. 

So unfortunately, I could not even get the sourcearea plugin working following the exact same steps that worked  in this post. I still have no 'Source' button showing in the footer of the editor. 

 I know this is a community of volunteers and I have really tried to research this myself so that I don't waste anyone's time. But I am completely at a loss now! As I said, if someone can help me with this, I will happily make the instructions much clearer with a video tutorial so that you will not be asked further questions about this. 

Summary: 
Image in CKEditor

I'm not sure if anyone has had a chance to look at this request, but after investing far too much time into trying to get this simple function to work. I ended up giving up and implementing a workaround instead. The workaround is to not include a task description at all in any of the H5P activity modules and instead write the task instructions in a Wordpress 'columns' block which sits above the embedded H5P content. That way, I can easily insert an image into my Wordpress block next to the task instructions.

For anyone else who wants to implement this solution and has found that some of the modules (like 'Dictation') have the task description as a mandatory field, you can hide the contents of this field using CSS as shown below:   

.h5p-content .h5p-question-introduction {
display: none;
}
 I'll post it as a feature request that the image button be added to the WYSIWYG editor, just to hopefully prevent anyone else from ending up in the same loop of frustration that I was in. I'm really curious as to the reason why the standard editor buttons that we usually see in other applications (like image, table, subscript, superscript etc) are not included by default in the H5P editor in all modules, and why all of that complex code is required in order for people to get them added to the editor. Is the reason simply to reduce the file size of the H5P application or is there another reason why they are not included?