MathJax 正在复制我的方程式——为什么以及如何解决这个问题?
MathJax is duplicating my equations -- why and how can I fix this?
我有如下页面(css没用--省略):
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">© 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">>></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's 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(,)");return eval(tstr);}
}
function Dval(str){
return "$"+str.replace(/(.+)\^(.+)/g,"{}^{}")+"$";
}
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}'s contents.",
" - {target} values:",
" * options: adjust options with subpoints (i.e. 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;
}
}
}
在执行时,这(理想情况下)将能够评估用户的输入(即 sin(3)
或 3 + 5^3 / 99.3
)。这段代码成功地做到了这一点,尽管显示它比较棘手。我正在使用 MathJax 正确显示数学,并使用 MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]);
定位元素 a{number}
并重做其 MathJax。这不知何故刷新了整个页面,而且,在输入一些条目后,将开始复制以前的方程式。
我已经将范围缩小到我认为的解决方案:MathJax 有两个可观察的阶段。
- 格式化方程式,然后
- 它应用字体。
MathJax 函数似乎只在我的代码中执行这两个步骤两次:一次,在开始时,一次,当函数首次执行时。
我的问题是,我该如何解决这个问题?我一直在尝试解决这个问题,但无济于事。
您的方法存在几个问题。 MathJax 重新处理整个文档的原因是因为您如何在 submit()
函数中增加 el
。您使用 post 增量,el++
,以便在行
之后
var d = "<p id='a"+(el++)+"'>"+$out+"</p>";
el
比您要添加的段落的 ID 大 1。所以稍后当你做
MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]);
您传递的 ID 不是指新添加的 <p>
标签,事实上,没有这样的 ID。当找不到ID时,MathJax处理整个页面。
至于重复的数学,那是因为你正在使用innerHTML
来更新输出区域。这样做会破坏现有的 DOM 并将其替换为新的(一种非常低效的方法)。这样做时,您切断了 MathJax 与 DOM 中现有数学之间的连接,因此 MathJax 不知道数学已被处理。因此,当它重新处理页面时,它会尝试再次排版数学(尽管在这种情况下它只能创建预览,但这是您看到的重复数学)。
最好不要使用innerHTML
来替换包含MathJax输出的元素的内容。除了断开 MathJax 的输出之外,您还会丢失 MathJax 用于上下文菜单和缩放功能等事件的事件处理程序。最好使用明确的 DOM 操作命令,如 document.createElement()
和 appendChild()
。这些需要更多的工作,但会更有效率,特别是对于较长的文档,并且不会导致 MathJax 问题。
MathJax 实际上为以这种方式创建元素提供了一些支持,因此您可以利用这些,而不是全部手动完成。
我有如下页面(css没用--省略):
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">© 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">>></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's 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(,)");return eval(tstr);}
}
function Dval(str){
return "$"+str.replace(/(.+)\^(.+)/g,"{}^{}")+"$";
}
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}'s contents.",
" - {target} values:",
" * options: adjust options with subpoints (i.e. 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;
}
}
}
在执行时,这(理想情况下)将能够评估用户的输入(即
sin(3)
或 3 + 5^3 / 99.3
)。这段代码成功地做到了这一点,尽管显示它比较棘手。我正在使用 MathJax 正确显示数学,并使用 MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]);
定位元素 a{number}
并重做其 MathJax。这不知何故刷新了整个页面,而且,在输入一些条目后,将开始复制以前的方程式。
我已经将范围缩小到我认为的解决方案:MathJax 有两个可观察的阶段。
- 格式化方程式,然后
- 它应用字体。
MathJax 函数似乎只在我的代码中执行这两个步骤两次:一次,在开始时,一次,当函数首次执行时。
我的问题是,我该如何解决这个问题?我一直在尝试解决这个问题,但无济于事。
您的方法存在几个问题。 MathJax 重新处理整个文档的原因是因为您如何在 submit()
函数中增加 el
。您使用 post 增量,el++
,以便在行
var d = "<p id='a"+(el++)+"'>"+$out+"</p>";
el
比您要添加的段落的 ID 大 1。所以稍后当你做
MathJax.Hub.Queue(["Typeset",MathJax.Hub,"a"+el+""]);
您传递的 ID 不是指新添加的 <p>
标签,事实上,没有这样的 ID。当找不到ID时,MathJax处理整个页面。
至于重复的数学,那是因为你正在使用innerHTML
来更新输出区域。这样做会破坏现有的 DOM 并将其替换为新的(一种非常低效的方法)。这样做时,您切断了 MathJax 与 DOM 中现有数学之间的连接,因此 MathJax 不知道数学已被处理。因此,当它重新处理页面时,它会尝试再次排版数学(尽管在这种情况下它只能创建预览,但这是您看到的重复数学)。
最好不要使用innerHTML
来替换包含MathJax输出的元素的内容。除了断开 MathJax 的输出之外,您还会丢失 MathJax 用于上下文菜单和缩放功能等事件的事件处理程序。最好使用明确的 DOM 操作命令,如 document.createElement()
和 appendChild()
。这些需要更多的工作,但会更有效率,特别是对于较长的文档,并且不会导致 MathJax 问题。
MathJax 实际上为以这种方式创建元素提供了一些支持,因此您可以利用这些,而不是全部手动完成。