Search code examples
javascriptmathjax

How can I use MathJax on popovers created with driver.js?


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?


Solution

  • 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).