1

I use driver.js to generate popovers to present a page. Though MathJax is working for basic elements, I can't figure out how to use it on the popovers. I followed this answer and try to rerun MathJax when the popover is generated, but I can't make it work.

Here's a small example describing the problem:

<!DOCTYPE html>
<html lang="en">
  <head>
      <!-- Files for MathJax -->
      <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
      <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
      
      <!-- Files for driver.js --> 
      <script src="https://unpkg.com/driver.js/dist/driver.min.js"></script>
      <link rel="stylesheet" href="https://unpkg.com/driver.js/dist/driver.min.css">
  </head>

  <body>
      <p>
      When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are \[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]
      </p>
      <button id="btn">Click to show popover</button>

      <script>
          // Define the popover
          const driver = new Driver();
          driver.defineSteps([
          {
            element: '#btn',
            popover: {
              title: 'Test MathJax',
              description: 'When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are \[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]',
              position: 'bottom'
            }
           }
         ]);
           
         let btn = document.querySelector('#btn');
          
         // When button is clicked, popover should appear and MathJax should re-run so that the math in the popover is correctly displayed
         btn.addEventListener('click', function(){
           driver.start();  
           MathJax.Hub.Queue(["Typeset", MathJax.Hub, "driver-popover-item"]);
         });
      </script>
      
  </body>
</html>

It is possible that this is due to the way driver.js was built but I don't have enough knowledge in JavaScript to check this by myself, and the GitHub repo seems quite inactive for now.

Does somebody have an idea?

bretauv
  • 7,756
  • 2
  • 20
  • 57

2 Answers2

1

Some observations:

Backslashes (\) need to be escaped so they appear inside strings in javascript. No need for that inside HTML tags.

The command to rerun MathJax in the recent version is MathJax.typeset(). I delayed it so that the driver has the chance to make the box appear.

<!DOCTYPE html>
<html lang="en">
  <head>
      <!-- Files for MathJax -->
      <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
      <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
      
      <!-- Files for driver.js --> 
      <script src="https://unpkg.com/driver.js/dist/driver.min.js"></script>
      <link rel="stylesheet" href="https://unpkg.com/driver.js/dist/driver.min.css">
  </head>

  <body>
      <p>
      When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are \[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]
      </p>
      <button id="btn">Click to show popover</button>

      <script>
          // Define the popover
          const driver = new Driver();
          driver.defineSteps([
          {
            element: '#btn',
            popover: {
              title: 'Test MathJax',
              description: 'When \\(a \\ne 0\\), there are two solutions to \\(ax^2 + bx + c = 0\\) and they are \\[x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\\]',
              position: 'bottom'
            }
           }
         ]);
           
         let btn = document.querySelector('#btn');
          
         // When button is clicked, popover should appear and MathJax should re-run so that the math in the popover is correctly displayed
         btn.addEventListener('click', function(){
           driver.start();  
           // MathJax.Hub.Typeset(document.querySelector(".driver-popover-description"));
           setTimeout(function() {
            MathJax.typeset();
           }, 1000);
         });
      </script>
      
  </body>
</html>
Eduardo Poço
  • 2,819
  • 1
  • 19
  • 27
  • I copied your code but it just doesn't work (MathJax not applied), does it work for you? – bretauv Dec 26 '20 at 08:43
  • I've never used driver.js, but ran into the same problem with dynamic math content. Is there a public link to this page, so I can test with devTools? – Eduardo Poço Dec 26 '20 at 14:18
  • No I just built this example but it's not on a public page. I'm still a novice in web development, can't you use devTools with the code I provided? – bretauv Dec 26 '20 at 17:17
  • Thanks! I just have a minor observation: when I remove the `setTimeout` function, mathjax is not applied. However, when I set the time to 0 (i.e when there's no delay), the maths are well displayed as soon as the popover appears. Do you have an idea of why this is the case? – bretauv Dec 26 '20 at 18:00
  • I think setTimeout gives the DOM a chance to recalculate layouts, so a timeout of 0 may be helping. If driver.js has some type of promise/callback to say when it is finished, you can put the MathJax rerun code inside it, so it is more guaranteed to work as soon as possible. – Eduardo Poço Dec 26 '20 at 18:08
0

Though Eduardo Poco's answer works for a single popover, it doesn't apply MathJax on popovers coming after in the tour. Also, when doing "Next" and "Prev" (hence coming back to the first popover where MathJax was applied), MathJax is not applied anymore.

To apply MathJax to all driver.js popovers (and I guess other tour libraries have something equivalent), you can use onHighlighted to apply MathJax on each highlighted popover.

Hence, the example in my post becomes:

<!DOCTYPE html>
<html lang="en">
  <head>
      <!-- Files for MathJax -->
      <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
      <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
      
      <!-- Files for driver.js --> 
      <script src="https://unpkg.com/driver.js/dist/driver.min.js"></script>
      <link rel="stylesheet" href="https://unpkg.com/driver.js/dist/driver.min.css">
  </head>

  <body>
      <p>
      When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are \[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]
      </p>
      <button id="btn">Click to show popover</button>
      <p id = "test2">Some text</p>

      <script>
          const driver = new Driver({
              onHighlighted: () => {
                 setTimeout(function() {
                    MathJax.typeset();
                   }, 400);
              }
          });
          driver.defineSteps([
          {
            element: '#btn',
            popover: {
              title: 'Test MathJax',
              description: '\\(a \\ne 0\\), there are two solutions to \\(ax^2 + bx + c = 0\\) and they are \\[x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\\]',
              position: 'bottom'
            }
           },
            {
            element: '#test2',
            popover: {
              title: 'Test MathJax',
              description: '\\(a \\ne 0\\)',
              position: 'bottom'
            }
           }
         ]);
           
         let btn = document.querySelector('#btn');
         btn.addEventListener('click', function(){
           driver.start(); 
         });
      </script>
      
  </body>
</html>

Note: I set the delay to 400 ms because if I put a lower value, MathJax is is applied too quickly (before the content of the popover appears) and therefore the content is not modified. This value might change for you (I made several tries to find it).

bretauv
  • 7,756
  • 2
  • 20
  • 57