H5p content, How to use mathjax.js for equation?

I want to create some interactive math courseware, but I find mathjax.js does not work in h5p content.

How to use equation in h5p content?

Attachments: 
falcon's picture

If you're adding mathjax to your page the normal way it won't work since many of the H5P content types are displayed in an iframe. The iframe is used to avoid css conflicts.

To fix this you need to add the mathjax script inside the iframe. Are you using Wordpress or Drupal?

We use Mathjax on a customer site with wiris as editor

I am using Drupal.

wiris ?

falcon's picture

Example code for adding your own scripts: (hook_node_view)

// If not teaser and has library.
if (!$a3 && isset($node->main_library)) {
  // Add generic CSS (will not work on iframed content).
  $module_path = drupal_get_path('module', 'my_module');
  if (H5PCore::determineEmbedType($node->embed_type, $node->main_library['embedTypes']) === 'div') {
    // Div
    drupal_set_html_head('');
  }
  else {
    // Iframe
    $content_id = h5p_get_content_id($node);
    $settings['h5p']['cid-' . $content_id]['scripts'][] = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
    $settings['h5p']['cid-' . $content_id]['styles'][] = $module_path . '/css/styles.css';
    drupal_add_js($settings, 'setting');
  }
}

Wiris web site:

http://www.wiris.com/

 

Thank you! I will try.....

I am not good at code.

$a3 what is meaning?

In drupal7  drupal_set_html_head  change to drupal_add_js ?

1. I delete "!$a3 &&" , I don't know $a3 what is it.

2. "drupal_set_html_head" instead of "drupal_add_html_head".

I test 3 content types, on "Course Presentation" page 1 and 2 that is ok, but page 3,4,5.... that does not work.

"Summary" and "Multichoice question" not work.

falcon's picture

The code was copied from a drupal 6 module. Sorry about that.

Multichoice and summary uses div so it mush be something wrong with the div section of the code. Can you see the math jax code getting loaded in your browser console?

The coursepresentation preloads the first two pages. I guess that's why it works on the two first pages and not on the rest of them. You'll need to make mathjax run again everytime the user visits a new page:

http://stackoverflow.com/questions/5200545/how-to-recall-or-restart-mathjax

We'll be adding xAPI in our next release. Then you'll be able to listen in to the stream of xAPI events and trigger mathJax whenever the users goes to a new page.

Now, new xAPI include ?

falcon's picture

Not yet, but soon I hope :)

Thanks, look forward next release ......

Hi, this thread is a bit old but I am also trying to use mathjax within h5p. Are there any plans of integrating mathjax into h5p so you can simply type e.g. $v=u+at$ in a text box and it shows up formatted? Or should I try to follow the instructions above to call mathjax?

falcon's picture

We're planning to add a mathjax library in the future, but we're not there quite yet. The comment above is a bit outdated.

 

Try this in a module:

<?php

/**
 * @file
 *  h5pmathjax.module php file
 *  Drupal module h5pmathjax. 
 */

/**
 * Implementation of hook_h5p_semantics_alter().
 *
 * Adds mathml tags to wysiwyg fields.
 */
function h5pmathjax_h5p_semantics_alter(&$semantics) {
  foreach ($semantics as $field) {
    // Lists specify the field inside the list.
    while ($field->type === 'list') {
      $field = $field->field;
    }

    if ($field->type === 'group') {
      h5pmathjax_h5p_semantics_alter($field->fields);
    }
    else if ($field->type === 'text' && isset($field->widget) && $field->widget === 'html') {
      if (!isset($field->tags)) {
        $field->tags = array();
      }

      // Add MathML tags
      $field->tags = array_merge($field->tags, array(
        'span',
        'math',
        'maction',
        'maligngroup',
        'malignmark',
        'menclose',
        'merror',
        'mfenced',
        'mfrac',
        'mglyph',
        'mi',
        'mlabeledtr',
        'mlongdiv',
        'mmultiscripts',
        'mn',
        'mo',
        'mover',
        'mpadded',
        'mphantom',
        'mroot',
        'mrow',
        'ms',
        'mscarries',
        'mscarry',
        'msgroup',
        'msline',
        'mspace',
        'msqrt',
        'msrow',
        'mstack',
        'mstyle',
        'msub',
        'msup',
        'msubsup',
        'mtable',
        'mtd',
        'mtext',
        'mtr',
        'munder',
        'munderover',
        'semantics',
        'annotation',
        'annotation-xml',
      ));
    }
  }
}

/**
 * Implements hook_h5p_scripts_alter().
 *
 * Adds MathJax support.
 */
function h5pmathjax_h5p_scripts_alter(&$scripts, &$libraries, &$embed_type) {
  $scripts[] = (object) array(
    'path' => 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML',
    'version' => ''
  );
  $scripts[] = (object) array(
    'path' => drupal_get_path('module', 'h5pmathjax') . '/mathjax.js',
    'version' => '?ver=0.0.1'
  );
}

And mathjax.js:

(function ($) {
  if (MathJax === undefined) {
    return; // Missing MathJax
  }

  // Hide annoying processing messages
  MathJax.Hub.Config({messageStyle: 'none'});

  $(document).ready(function () {
    // Find H5P content
    $('.h5p-content').each(function (i, e) {
      var doJax = function (node) {
        MathJax.Hub.Queue(['Typeset', MathJax.Hub, node]);
      };
      var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
      if (!MutationObserver) {
        var check = function () {
          $('math', e).each(function (j, m) {
            doJax(m.parentNode);
          });
          checkInterval = setTimeout(check, 2000);
        };
        var checkInterval = setTimeout(check, 2000);
      }
      else {
        var running = false;
          var limitedResize = function () {
            if (!running) {
              running = setTimeout(function () {
                $('math', e).each(function (j, m) {
                  doJax(m.parentNode);
                });
                running = null;
              }, 500); // 2 fps cap
            }
          };

        var observer = new MutationObserver(function (mutations) {
          for (var i = 0; i < mutations.length; i++) {
            if (mutations[i].addedNodes.length) {
              limitedResize();
              return;
            }
          }
        });
        observer.observe(e, {
          childList: true,
          subtree: true
        });
      }
    });
  });
})(H5P.jQuery);

Thanks for the quick reply. Where do I paste the code? I am using Wordpress, not Drupal if that matters.

falcon's picture

Oh, sorry, I don't know why I assumed it was Drupal. I don't think this is easy to do with Wordpress. I'll ask icc to comment on this.
icc's picture

It should be possible to do in WordPress as well, but it might be difficult for a novice user.
You need two components to get this working. You'll have to have a CKEditor plugin where you can enter the symbols, and then you need mathjax to display them.

You should be able to use the code falcon posted, but first you have to create a simple plugin to use it in, or do it in a custom theme that you have. I would recommend creating a simple plugin. Secondly you'll have to add the function as a trigger, i.e. 
add_action('h5p_alter_library_semantics', 'h5pmathjax_h5p_semantics_alter');
in your plugin.

There might be some issues and debugging, so if you're not into coding I think I'd wait until someone created a plugin that does this. Or if you have the money, pay someone to create it. 

Thank you. That does sound a bit too advanced for now so I'll work around it by saving the equations as pictures until someone else makes a plugin...

I'm on a low budget I'm afraid, making my website as a non-profit. It's amazing that H5P is free even though it's a fantastic plugin :) I'm so glad I finally found a plugin to make great-looking courses without any coding so I can focus on the content.

Hi, I have made a custom plugin and I am wondering if you could help me on the next steps on how to make mathjax work through it? Thanks

icc's picture

Great!

If you share the code I'm sure someone is willing to have a look.

Here is the custom plugin but I do not know what's the next step.The plugin allows custom javascript to be injected inside a WYSIWYG iframe. I hope someone can continue and may find the plugin helpful.

Attachments: 
icc's picture

Thanks!

falcon's picture

:)

hi falcon,

I would love to use this module do I just create it under sites/modules or in sites/modules/h5p/modules

falcon's picture

Great, yes, you create it under sites/all/modules :)

I have tried to install this mathjax support for h5p, but with no success.

I have created a module by placing a folder in \sites\all\modules\h5pmathjax\h5pmathjax.module as listed in the code section above. I added h5pmathjax.info and mathjax.js (as listed in the code section above) to this folder.

I enabled the module, successfully I believe as I added a function h5pmathjax_help which is being recognised). When I try to use a mathjax string it remains as a string. By looking in developer tools in CHrome, I can see that the mathjax.js file for the mathjax module has been loaded, but this one does not appear. What am I missing?

Experience level: php/js reasonable; Drupal/Opigno very new. Thanks for your consideration. 

falcon's picture

Have you tried to debug the javascript? Is the limited resize function being run? Does it find the math tag?

Thanks. I put a 3 alerts in the new mathjax.js to see if it was being loaded and run. One at line 2, one at line 10, one at line 28 (i.e. in the linitedREsize function. The first two were triggered. The third was not. I got a couple of console messages looking for files in \extensions folder  MathZoom.js, MathMenu.js (but not finding them - as they are not there!)

falcon's picture

Might be that the code above is for an older version of mathjax then. Do you get something if you add an alert message or console.log after "$('.h5p-content').each(function (i, e) {" ?

I will do that and respond. I would try and debug this in developer tools but cannot see the source (which made me think it was not being loaded - proved incorrect by sticking in the messages). I can see the source of the mathjax.js that is in the non hp5 folder but not the one that I copied from this page. Do you know where I would find that? 

falcon's picture

Yeah, you will have to select the correct window. The H5P runs in an iframe so you have to select that window.

Did as you suggested and  add an alert message or console.log after "$('.h5p-content').each(function (i, e) {" .

It was not invoked.

falcon's picture

Sounds like the code runs too early then - not sure how to fix it without digging into the code, hopefully someone else will jump in here.

Hi Falcon,

I'm happy to have a look round and see what is going on and make suggestions. The only problem is that I am not sure what the mathjax.js is trying to do. If it is just the case that, because the hp5 is running in an iframe and so cannot see the mathjax.js on the mnain site, why do we just not load the identical files inside the iframe, rather than writing a new script? If you can point me somewhere that I could find out what it is trying to do I can spend sometime: looks like it would be useful.

icc's picture

First we need to figure out if our script tries to trigger MathJax. Put a console.log('Running MathJax', node); inside the doJax function and watch for output. 

You can also try to step through the code by inserting debugger; on a separate line, that should add a break point for the Developer Tools in the browser(Ctrl+Shift+J in Chrome).

I inserted this code

<code>

  $(document).ready(function () {

    // Find H5P content

console.log('Find H5P content');

debugger;

    $('.h5p-content').each(function (i, e) {

console.log('Found one',i,e);

debugger;

      var doJax = function (node) {

console.log('Running MathJax', node);

debugger;

        MathJax.Hub.Queue(['Typeset', MathJax.Hub, node]);

      };

</code>

The first 2 were triggered, the one inside the MathJax was not. (can't seem to get code to be formatted)

icc's picture

Good! Are you sure you have any math tags in the H5P? Try adding console.log('Math tags: ' + $('math').length); after the console.log('Found one',i,e); to make sure they are present.

icc's picture

You can also try to remove the MutationObserver part and reducing the code to:

(function ($) {
  if (MathJax === undefined) {
    return; // Missing MathJax
  }
 
  // Hide annoying processing messages
  MathJax.Hub.Config({messageStyle: 'none'});
 
  $(document).ready(function () {
    // Find H5P content
    $('.h5p-content').each(function (i, e) {
      var doJax = function (node) {
        MathJax.Hub.Queue(['Typeset', MathJax.Hub, node]);
      };
      var check = function () {
        $('math', e).each(function (j, m) {
          doJax(m.parentNode);
        });
        checkInterval = setTimeout(check, 2000);
      };
      var checkInterval = setTimeout(check, 2000);
    });
  });
})(H5P.jQuery);

 

You can also try to uncomment or remove the "hide annoying processing messages" line and see if that gives your any error messages: // MathJax.Hub.Config({messageStyle: 'none'});

Thanks.

No maths tabs were found. (zero length)

Removed the annoying message bit, but no messages presented.

One of the things I noticed in setting this up was applying the filters to the text formats. Both h5p and MathJax would like to be the last in the list... Could I confirm these should be enabled and the order. Checking these I currently have (for both HTML and plainText: h5pcontent not enabled; MathJax enabled and placed last.)?

I will go ahead and try the MutationObserver suggestion...

icc's picture

Without the math tags you won't get any math symbols. 
You must make sure that you've implemented the "function h5pmathjax_h5p_semantics_alter(&$semantics) {" from the example code. If the MathML tags aren't added to the allowed tags in H5P they will be stripped away. The allowed tags is a whitelist that improves security by removing unwanted code.

Which CKEditor plugin did you use to add the math symbols?

Thanks. It does look like function h5pmathjax_h5p_semantics_alter(&$semantics) {" has run. Can I check it worked and that the tags have been added?

I used the h5p editing screen in Opigno (as per capture.jpeg screenshot attached). Is there something I should have set up here to use a particular plugin?

I really appreciate your help.

Attachments: 
icc's picture

Hm ok, you'll need a plugin like WIRIS or Mathematical Formulas to CKEditor in order to enter the formula. Plugins like these will create the MathML code that MathJax needs to create the formula.

Here's an example of how to add the latter plugin:

Add these to your h5pmathjax.module:

function h5pmathjax_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'h5p_content_node_form') {
    $form['#after_build'][] = 'h5pmathjax_node_form_process';
  }
}

function h5pmathjax_node_form_process($form, &$form_state) {
  $module_path = drupal_get_path('module', 'h5pmathjax');
  $cache_buster = '?' . variable_get('css_js_query_string', '');
  drupal_add_js(array(
    'h5peditor' => array(
      'mathjaxPluginPath' => base_path() . $module_path . '/mathjax/',
      'assets' => array(
        'js' => array(
          '/' . $module_path . '/add-mathjax-plugin.js' . $cache_buster
        )
      )
    )
  ), 'setting');
  return $form;
}


And then create add-mathjax-plugin.js and add:

var H5PEditor = H5PEditor || {};
H5PEditor.HtmlAddons = H5PEditor.HtmlAddons || {};
H5PEditor.HtmlAddons.math = H5PEditor.HtmlAddons.math || {};
H5PEditor.HtmlAddons.math.mathjax = function (config, tags) {
  config.extraPlugins = (config.extraPlugins ? ',' : '') + 'mathjax';
  config.toolbar.push({
    name: "mathjax",
    items: ['Mathematical Formulas']
  });
  tags.push('span');
  tags.push('math');
  tags.push('maction');
  tags.push('maligngroup');
  tags.push('malignmark');
  tags.push('menclose');
  tags.push('merror');
  tags.push('mfenced');
  tags.push('mfrac');
  tags.push('mglyph');
  tags.push('mi');
  tags.push('mlabeledtr');
  tags.push('mlongdiv');
  tags.push('mmultiscripts');
  tags.push('mn');
  tags.push('mo');
  tags.push('mover');
  tags.push('mpadded');
  tags.push('mphantom');
  tags.push('mroot');
  tags.push('mrow');
  tags.push('ms');
  tags.push('mscarries');
  tags.push('mscarry');
  tags.push('msgroup');
  tags.push('msline');
  tags.push('mspace');
  tags.push('msqrt');
  tags.push('msrow');
  tags.push('mstack');
  tags.push('mstyle');
  tags.push('msub');
  tags.push('msup');
  tags.push('msubsup');
  tags.push('mtable');
  tags.push('mtd');
  tags.push('mtext');
  tags.push('mtr');
  tags.push('munder');
  tags.push('munderover');
  tags.push('semantics');
  tags.push('annotation');
  tags.push('annotation-xml');
};

(function ($) {
  $(document).ready(function () {
    if (window.Drupal === undefined) {
      window.Drupal = window.top.Drupal;
    }
    if (window.CKEDITOR !== undefined) {
      // Add plugin
      CKEDITOR.plugins.addExternal('mathjax', Drupal.settings.h5peditor.mathjaxPluginPath);
    }
  });
})(H5P.jQuery);


You will, of course, have to download the CKEditor mathjax plugin and put the directory in your module's directory so that the mathjaxPluginPath exists, if not it won't be able to load the plugin. When everything is loaded correctly you should see a button in the WYSIWYG toolbar for inserting math formulas.

Thank you very much. I am currently checking and trying this...

 

Thanks again, but I get the message 'Uncaught [CKEDITOR.resourceManager.load] Resource name "widget" was not found at "/profiles/opigno_lms/modules/contrib/h5p/modules/h5peditor/h5peditor//ckeditor/plugins/widget/plugin.js?t=F7J9".'

It looks like I have not installed the plugin correctly? Is it relevant that there is a double slash between h5peditor and ckeditor?

To recap

  1. I appended the php into h5pmathjax.module
  2. I created a new file add-mathjax-plugin.js withe the above js
  3. I downloaded the CKEditor mathjax plugin from the link above and put it in \sites\all\modules\h5pmathjax\mathjax 

Do I need to another plugin called widget? and maybe others? I see the site says 'Dependencies: Requires the following plugins to work: WidgetLine Utilities,DialogClipboard.' 

In the folder \profiles\opigno_lms\libraries\ckeditor\plugins I have subfolders dialog and clipboard but none of the other two.

In the folder H:\WWW\htdocs\OpignoTest1\profiles\opigno_lms\modules\contrib\h5p\modules\h5peditor\h5peditor\ckeditor\plugins I have subfolders dialog and clipboard but none of the other two.

Do I install WidgetLine Utilities, in both of these locations. Are these foloders copies of ech other? Or should I be doing all of this through the UI somehow?

icc's picture

Oh, my bad! Yes, you do need the plugin dependencies as well. You should download them, put them in the module's folder with mathjax and add them the same way.

The \profiles\opigno_lms\libraries\ckeditor\plugins are the CKEditor used outside of H5P. The one inside the h5peditor folder is the one used by H5P, but you shouldn't change them as they will be replaced when you update Opigno or the modules.

Here's the updated code:

function h5pmathjax_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'h5p_content_node_form') {
    $form['#after_build'][] = 'h5pmathjax_node_form_process';
  }
}
 
function h5pmathjax_node_form_process($form, &$form_state) {
  $module_path = drupal_get_path('module', 'h5pmathjax');
  $cache_buster = '?' . variable_get('css_js_query_string', '');
  drupal_add_js(array(
    'h5peditor' => array(
      'mathjaxPluginPath' => base_path() . $module_path . '/',
      'assets' => array(
        'js' => array(
          '/' . $module_path . '/add-mathjax-plugin.js' . $cache_buster
        )
      )
    )
  ), 'setting');
  return $form;
}
var H5PEditor = H5PEditor || {};
H5PEditor.HtmlAddons = H5PEditor.HtmlAddons || {};
H5PEditor.HtmlAddons.math = H5PEditor.HtmlAddons.math || {};
H5PEditor.HtmlAddons.math.mathjax = function (config, tags) {
  config.extraPlugins = (config.extraPlugins ? ',' : '') + 'widget,lineutils,mathjax';
  config.toolbar.push({
    name: "mathjax",
    items: ['Mathematical Formulas']
  });
  tags.push('span');
  tags.push('math');
  tags.push('maction');
  tags.push('maligngroup');
  tags.push('malignmark');
  tags.push('menclose');
  tags.push('merror');
  tags.push('mfenced');
  tags.push('mfrac');
  tags.push('mglyph');
  tags.push('mi');
  tags.push('mlabeledtr');
  tags.push('mlongdiv');
  tags.push('mmultiscripts');
  tags.push('mn');
  tags.push('mo');
  tags.push('mover');
  tags.push('mpadded');
  tags.push('mphantom');
  tags.push('mroot');
  tags.push('mrow');
  tags.push('ms');
  tags.push('mscarries');
  tags.push('mscarry');
  tags.push('msgroup');
  tags.push('msline');
  tags.push('mspace');
  tags.push('msqrt');
  tags.push('msrow');
  tags.push('mstack');
  tags.push('mstyle');
  tags.push('msub');
  tags.push('msup');
  tags.push('msubsup');
  tags.push('mtable');
  tags.push('mtd');
  tags.push('mtext');
  tags.push('mtr');
  tags.push('munder');
  tags.push('munderover');
  tags.push('semantics');
  tags.push('annotation');
  tags.push('annotation-xml');
};
 
(function ($) {
  $(document).ready(function () {
    if (window.Drupal === undefined) {
      window.Drupal = window.top.Drupal;
    }
    if (window.CKEDITOR !== undefined) {
      // Add plugin
      ['widget', 'lineutils', 'mathjax'].forEach(function (p) {
        CKEDITOR.plugins.addExternal(p, Drupal.settings.h5peditor.mathjaxPluginPath + p + '/');
      });
    }
  });
})(H5P.jQuery);

 

I haven't tested it so I'm not sure if the order is correct, you can try to re-order them if you get the same message.

Thanks. Sorry for the delay. still not quite there. Will post details as reply to main topic as I am running out of screen space with the replies indenting.

Just to say that all the alerts get triggered in IE 11 (the resize gets triggered 3 times)

I am getting an error in the /sites/all/modules/h5pmathjax/mathjax/plugin.js around line 18

<code>

init: function( editor ) {

var cls = editor.config.mathJaxClass || 'math-tex';

 

if ( !editor.config.mathJaxLib ) {

CKEDITOR.error( 'mathjax-no-config' );

}

</code>

The delay was me researching to see if I could work it out - no luck!

 

icc's picture

It appears that the plugin requires the MathJax lib to work. You can set the path to it by adding a config line next to the other config lines in the JavaScript we created:

config.mathJaxLib = '//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML';

Correction (Ihad some debugging code in). The lines 

Its looking for (and not finding):

  • /jax/input/Tex/config.js
  • /jax/output/HTML-CSS/config.js
  • /extensions/tex2jax.js
  • /extensions/MathZoom.js
  • /extensions/MathMenu.js

are incorrect. IT is only looking for:

  • /extensions/MathZoom.js
  • /extensions/MathMenu.js

Sorry. No other error messages are being produced. So it looks like a case for some more debugging statements!

 

Hi icc, thanks for your advice. I tried exactly that (well at least I am learning!) last night to no avail.

Its looking for (and not finding):

  • /jax/input/Tex/config.js
  • /jax/output/HTML-CSS/config.js
  • /extensions/tex2jax.js
  • /extensions/MathZoom.js
  • /extensions/MathMenu.js

These are all being called from the http://cdn.mathjax.org/mathjax/latest/MathJax.js that has been injected into our \sites\all\modules\h5pmathjax\mathjax.js

It seems that there are a few things we are trying to achieve:

  1. get LaTex or similar to interpret a string such as  $$....$$ and convert it to MathML
  2. get MathJax to process the MathML
  3. add a nice user friendly button to the h5peditor (and ckeditor as well) to help with the above
  4. provide all the above in a way that the rest of the world can do this rather more easily

I am doing a bit of 'reading the manual(s)' at the moment to ensure I am not doing something stupid too.

Your help is greatly appreciated. 

icc's picture

Hm, let's try to focus on the editor first. We need to get the formulas in before we worry about the view.
Try to uncomment the h5pmathjax_h5p_scripts_alter function and see if anything changes. There might be some trouble since the plugin is trying to load MathJax as well.

Pages