Search code examples
mathjaxmathml

Retrieving input from MathML rendered using MathJax


I want to make a practice sheet using HTML (MathML) and MathJax. The practice sheet will be filled with numbers and the inputted numbers can be retrieved and checked with an answer key. My problem is that my code can't retrieve the input when I use MathJax (It works fine without MathJax). Is there a workaround?

This is my code.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Math Quiz</title>
    <script type="text/javascript" async src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
    <script type="text/javascript" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
    <script>
      window.MathJax = {
        tex: { inlineMath: [['$', '$'], ['\\(', '\\)']] }
      };
    </script>
    <style>
    .input {
      width: 20px;
      text-align: center;
      font-family: Arial, sans-serif;
    }

    .red {
      background-color: darkred;
    }
    </style>
</head>
<body>


<math display="block" class="tml-display" style="display:block math;">
  <mrow>
    <msubsup>
      <mo movablelimits="false">∫</mo>
      <mn>2</mn>
      <mn>3</mn>
    </msubsup>
    <msup>
      <mi>x</mi>
      <mn>2</mn>
    </msup>
    <mo>=</mo>
    <mfrac>
      <mn><semantics>
        <annotation-xml encoding="application/xhtml+xml">
          <input xmlns="http://www.w3.org/1999/xhtml" type="text" maxlength="2" class="input" size="1" data-answer="19" value="" autocomplete="off" />
        </annotation-xml></semantics></mn>
      <mn><semantics>
        <annotation-xml encoding="application/xhtml+xml">
          <input xmlns="http://www.w3.org/1999/xhtml" type="text" maxlength="1" class="input" size="1" data-answer="3" value="" autocomplete="off" />
        </annotation-xml></semantics></mn>
    </mfrac>
  </mrow>
</math>

<br>
<button id="checkButton" style="margin-top: 10px;">Check Answers</button>
<div id="resultMessage" style="margin-top: 10px;"></div>

<script>
  document.addEventListener('DOMContentLoaded', function () {
    function checkAnswer(element) {
      const inputValue = element.value.replace(/[^0-9-]/g, ''); 
      const correctAnswer = element.dataset.answer;

      console.log('Input Value:', inputValue);
      console.log('Correct Answer:', correctAnswer);

      const isCorrect = inputValue === correctAnswer;

      
      element.style.backgroundColor = ''; 
      if (!isCorrect) {
        element.style.backgroundColor = 'red'; 
      }

      return isCorrect;
    }

    function checkAllAnswers() {
      const inputFields = document.querySelectorAll('input[data-answer]');
      let allCorrect = true;

      inputFields.forEach(function (element) {
        if (!checkAnswer(element)) {
          allCorrect = false; 
        }
      });

      const resultMessage = document.getElementById('resultMessage');
      resultMessage.textContent = allCorrect
        ? 'All answers are correct!'
        : 'Some answers are incorrect. Please try again.';
    }

  
    document.getElementById('checkButton').addEventListener('click', function () {
      checkAllAnswers();

      }
    )});

</script>

</body>
</html>

When I input the correct answers and click the 'Check Answers' button, it is supposed to return "All answers are correct!", but it did not.

Note: I am a complete beginner in programming and I am just starting to learn about things.


Solution

  • The problem is that v3.2.2 of MathJax inserts hidden MathML that is for assistive technology like screen readers. That means that you have one copy of the input fields in the visible typeset math, and another copy in the hidden assisitve-MathML. The student can only enter answers in the first of these, so the second set will be marked by your code as incorrect, so not all answers are correct.

    One solution would be to turn off the assistive-MathML using a configuration that includes

    MathJax = {
      options: {
        enableAssistiveMml: false
      }
    };
    

    although your read could turn it on again in the MathJax contextual menu.

    Alternatively, you could have your code ignore the copies that are in the assistive MathML (by checking the parent elements to check if they are in a n <annotation-xml> node, for example). That is probably safer.