MathJax duplicates my equations - why and how can I fix it?

I have the following page (css useless - omitted):

HTML:

<!DOCTYPE html> <html lang=en> <head> <meta charset="UTF-8"> <title>Command Line</title> <script type="text/x-mathjax-config"> MathJax.Hub.Config({ extensions: ["http://cs.jsu.edu/mathjax-ext/contrib/forminput/forminput.js"], tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}, TeX: {extensions: ["AMSmath.js","AMSsymbols.js"]} }); </script> <script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script src="http://code.jquery.com/jquery-1.10.2.js"></script> <script src="!!IMPORTANT_JS!!.js"></script> <script src="theta.js"></script> <script src="cmd.js"></script> <link rel="STYLESHEET" type="text/css" href="styles.css"> </head> <header> <h1 id="title">COMMAND LINE v.2.0</h1><span id="copy">&copy; 2015 ~ Conor O'Brien</span> </header> <body> <div id="subtitle">Now with $\LaTeX$!</div> <div id="out"></div> <h3 id="sQ"></h3> </body> <footer> <input type="text" id="cmd"> <input type="color" id="col"> <div id="left">&gt;&gt;</div> </footer> </html> 

JavaScript:

 $( document ).ready(function(){ window.t = false; $("#col").on("change",function(){ var d = $q(this).value; $q("#out").innerHTML+="<p>Color: <span style=\"color: "+d+";\">"+d.toUpperCase()+", "+Color.hexToRgb(d).v+" - "+linkC("/color "+d,"Use")+"</span>.</p>"; }); $("#cmd")[0].addEventListener("keypress",function(e){ if(e.key=="Enter"){ submit(); } }); $("#out").html("Initializing..."); window.init = function(){ var d = [br(3)+ "********* INITIALIZED *********", "* Welcome to the experimental *", "* JavaScript command line! It *", "* will execute exactly like a *", "* handheld calculator, having *", "* the capacity to execute the *", "* user inputs. *", "* *", "* ~-~-~-~-~-~-~-~-~-~-~-~-~-~ *", "* *", "* Type 'help' for environment *", "* commands. *", "*******************************"+br(), "<hr>"],i=0; function x(d,i){ $q("#out").innerHTML += (d[i++])||""; $q("#out").innerHTML += br(); if(i<d.length){ setTimeout(x,20,d,i); } else { window.t = true; } } setTimeout(x,500,d,i); } init(); }); function br(x){ var o = "",x=x||1; for(i=0;i<x;i++){ o+="<br>"; } return o; } function $q(i){ return $(i)[0]; } function submit(){ if(t){ var $out = getOutput(); if($out){ var d = "<p id='a"+(el++)+"'>"+$out+"</p>"; $q("#out").innerHTML += d; lines.push(d); marker = lines.length; location = "file:///C:/Users/Conor%20O%27Brien/Documents/Programming/command%20line%20v.2.0/main.html#sQ"; $q("#cmd").focus(); console.log(el); MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]); } } } var pi = Math.PI; var e = Math.E; function Reval(str){ with(Math){var tstr = str.replace(/(.+)\^(.+)/g,"Math.pow($1,$2)");return eval(tstr);} } function Dval(str){ return "$"+str.replace(/(.+)\^(.+)/g,"{$1}^{$2}")+"$"; } var el = 0; function getOutput(){ var val = $q("#cmd").value; if(val=="help"){ $q("#out").innerHTML = ""; return "<h1>HELP</h1><h2>Commands</h2>"+ [ "= help", " - displays help document.", "= open {target}", " - displays {target} contents.", " - {target} values:", " * options: adjust options with subpoints (ie options.{prop} = {1/0} [1=True,0=False])" ].join(br())+"<hr>"; } else if(val=="cls"||val=="clear"){ $q("#out").innerHTML = ""; return "Cleared."; } else if(val.substr(0,5)=="open "){ var target = val.substr(5,val.length); console.log(target); switch(target){ case "options": break; default: return new Error(target+" is not a valid target!"); break; } } else { try { console.log(val,Reval(val)); return Dval(val)+br()+"<span class='ans'>"+Reval(val)+"</span>"; } catch(e) { return e; } } } 


After doing this (ideally) it will be possible to evaluate the user input (i.e. sin(3) or 3 + 5^3 / 99.3 ). This code does this successfully, although displaying it is more complicated. I use MathJax to display math correctly and using MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]); to target the element a{number} and repeat it with MathJax. This somehow refreshes the entire page and, in addition, after several entries in the input, it starts duplicating the previous equations.

I narrowed it down to what I think would be the solution: MathJax has two observable phases.

  • It formats the equations, then
  • He uses fonts.

The MathJax function seems to perform these two steps in my code twice: once, at the beginning, and once when the function is first executed.

My question is, how can I fix this? I tried to fix it, but to no avail.

+1
javascript html5 mathjax
source share
1 answer

There are several problems with your approach. The reason MathJax processes the entire document is due to how you increase el in the submit() function. You are using post-increment, el++ , so after the line

 var d = "<p id='a"+(el++)+"'>"+$out+"</p>"; 

el is one more than the paragraph ID you are adding. So when you do

 MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]); 

the identifier you are passing does not apply to the newly added <p> , and in fact there is no such identifier. When the identifier is not found, MathJax processes the entire page.

As for math duplication, this is because you use innerHTML to update the output area. This destroys the existing DOM and replaces it with a new one (very inefficient approach). In doing so, you break the connection between MathJax and the existing math in the DOM, so MathJax does not know that the math has been processed. Therefore, when he refines the page, he tries to type in the math again (although in this case he gets to create a preview, but this is the math that you see as a duplicate).

It is better not to use innerHTML to replace the contents of the element containing the MathJax output. In addition to disconnecting the output from MathJax, you also lose the event handlers that MathJax uses for things like its context menu and zoom functions. It would be better to use explicit DOM manipulation commands such as document.createElement() and appendChild() . They take a little more work, but will be much more efficient, especially for longer documents, and will not cause MathJax problems.

MathJax actually provides some support for creating elements this way, so you can use them instead of doing it all manually.

+1
source share

All Articles