Add a processing state variable and use that to allow pre- and post-Translate methods that can be used to get scaling factors, etc.

This commit is contained in:
Davide P. Cervone 2011-08-28 13:14:20 -04:00
parent c23c21443e
commit 805c78df67
2 changed files with 150 additions and 79 deletions

File diff suppressed because one or more lines are too long

View File

@ -1137,7 +1137,7 @@ MathJax.Message = {
this.status = true; this.status = true;
} }
} }
if (clearDelay) {setTimeout(MathJax.Callback(["Clear",this,n]),clearDelay)} if (clearDelay) {setTimeout(MathJax.Callback(["Clear",this,n,0]),clearDelay)}
return n; return n;
}, },
@ -1149,8 +1149,9 @@ MathJax.Message = {
if (this.text) { if (this.text) {
if (this.div.parentNode == null) {this.Init()} // see ASCIIMathML comments above if (this.div.parentNode == null) {this.Init()} // see ASCIIMathML comments above
if (this.current == null) { if (this.current == null) {
if (this.timer) {clearTimeout(this.timer)} if (this.timer) {clearTimeout(this.timer); delete this.timer}
this.timer = setTimeout(MathJax.Callback(["Remove",this]),(delay||600)); if (delay === 0) {this.Remove()}
else {this.timer = setTimeout(MathJax.Callback(["Remove",this]),(delay||600))}
} else if (this.textNodeBug) {this.div.innerHTML = this.log[this.current].text} } else if (this.textNodeBug) {this.div.innerHTML = this.log[this.current].text}
else {this.text.nodeValue = this.log[this.current].text} else {this.text.nodeValue = this.log[this.current].text}
if (this.status) {window.status = ""; delete this.status} if (this.status) {window.status = ""; delete this.status}
@ -1343,18 +1344,25 @@ MathJax.Hub = {
var queue = MathJax.Callback.Queue(["Clear",this.signal]); var queue = MathJax.Callback.Queue(["Clear",this.signal]);
for (var i = 0, m = ec.elements.length; i < m; i++) { for (var i = 0, m = ec.elements.length; i < m; i++) {
if (ec.elements[i]) { if (ec.elements[i]) {
var scripts = []; // filled in by prepareScripts var state = {
scripts: [], // filled in by prepareScripts
start: new Date().getTime(), // timer for processing messages
i: 0, // current script
jax: {} // scripts grouped by output jax
};
queue.Push( queue.Push(
["Post",this.signal,["Begin "+action,ec.elements[i]]], ["Post",this.signal,["Begin "+action,ec.elements[i]]],
["Post",this.signal,["Begin Math",ec.elements[i]]], ["Post",this.signal,["Begin Math",ec.elements[i],action]],
["prepareScripts",this,action,ec.elements[i],scripts], ["prepareScripts",this,action,ec.elements[i],state],
["Post",this.signal,["Begin Math Input",ec.elements[i]]], ["Post",this.signal,["Begin Math Input",ec.elements[i],action]],
["processInput",this,scripts], ["processInput",this,state],
["Post",this.signal,["End Math Input",ec.elements[i]]], ["Post",this.signal,["End Math Input",ec.elements[i],action]],
["Post",this.signal,["Begin Math Output",ec.elements[i]]], ["prepareOutput",this,state,"preTranslate"],
["processOutput",this,scripts], ["Post",this.signal,["Begin Math Output",ec.elements[i],action]],
["Post",this.signal,["End Math Output",ec.elements[i]]], ["processOutput",this,state],
["Post",this.signal,["End Math",ec.elements[i]]], ["Post",this.signal,["End Math Output",ec.elements[i],action]],
["prepareOutput",this,state,"postTranslate"],
["Post",this.signal,["End Math",ec.elements[i],action]],
["Post",this.signal,["End "+action,ec.elements[i]]] ["Post",this.signal,["End "+action,ec.elements[i]]]
); );
} }
@ -1375,7 +1383,7 @@ MathJax.Hub = {
} }
}, },
prepareScripts: function (action,element,math) { prepareScripts: function (action,element,state) {
if (arguments.callee.disabled) return; if (arguments.callee.disabled) return;
var scripts = this.elementScripts(element); var scripts = this.elementScripts(element);
var STATE = MathJax.ElementJax.STATE; var STATE = MathJax.ElementJax.STATE;
@ -1385,19 +1393,17 @@ MathJax.Hub = {
if (script.MathJax && script.MathJax.state !== STATE.PENDING) if (script.MathJax && script.MathJax.state !== STATE.PENDING)
{this.scriptAction[action](script)} {this.scriptAction[action](script)}
if (!script.MathJax) {script.MathJax = {state: STATE.PENDING}} if (!script.MathJax) {script.MathJax = {state: STATE.PENDING}}
if (script.MathJax.state !== STATE.PROCESSED) {math.push(script)} if (script.MathJax.state !== STATE.PROCESSED) {state.scripts.push(script)}
} }
} }
}, },
checkScriptSiblings: function (script) { checkScriptSiblings: function (script) {
if (script.MathJax && script.MathJax.checked) return; if (script.MathJax.checked) return;
var config = this.config; var config = this.config, pre = script.previousSibling;
var pre = script.previousSibling; if (pre && pre.nodeName === "#text") {
if (pre && pre.nodeName == "#text") { var preJax,postJax, post = script.nextSibling;
var preJax,postJax; if (post && post.nodeName !== "#text") {post = null}
var post = script.nextSibling;
if (post && post.nodeName != "#text") {post = null}
if (config.preJax) { if (config.preJax) {
if (typeof(config.preJax) === "string") {config.preJax = new RegExp(config.preJax+"$")} if (typeof(config.preJax) === "string") {config.preJax = new RegExp(config.preJax+"$")}
preJax = pre.nodeValue.match(config.preJax); preJax = pre.nodeValue.match(config.preJax);
@ -1417,87 +1423,152 @@ MathJax.Hub = {
} }
if (pre && !pre.nodeValue.match(/\S/)) {pre = pre.previousSibling} if (pre && !pre.nodeValue.match(/\S/)) {pre = pre.previousSibling}
} }
if (config.preRemoveClass && pre && pre.className == config.preRemoveClass) { if (config.preRemoveClass && pre && pre.className === config.preRemoveClass)
try {pre.innerHTML = ""} catch (err) {} {script.MathJax.preview = pre}
pre.style.display = "none"; script.MathJax.checked = 1;
}
if (script.MathJax) {script.MathJax.checked = 1}
}, },
processInput: function (scripts,start,n) { processInput: function (state) {
if (arguments.callee.disabled) {return null} var jax, STATE = MathJax.ElementJax.STATE;
if (!start) {start = new Date().getTime()} var script, prev, m = state.scripts.length;
var result, STATE = MathJax.ElementJax.STATE;
var i = 0, script, prev;
try { try {
while (i < scripts.length) { //
script = scripts[i]; if (!script) {i++; continue} // Loop through the scripts
//
while (state.i < m) {
script = state.scripts[state.i]; if (!script) {state.i++; continue}
//
// Remove previous error marker, if any
//
prev = script.previousSibling; prev = script.previousSibling;
if (prev && prev.className === "MathJax_Error") {prev.parentNode.removeChild(prev)} if (prev && prev.className === "MathJax_Error") {prev.parentNode.removeChild(prev)}
var type = script.type.replace(/ *;(.|\s)*/,""); //
if (!script.MathJax || script.MathJax.state === STATE.PROCESSED) {i++; continue}; // Check if already processed or needs processing
//
if (!script.MathJax || script.MathJax.state === STATE.PROCESSED) {state.i++; continue};
if (!script.MathJax.elementJax || script.MathJax.state === STATE.UPDATE) { if (!script.MathJax.elementJax || script.MathJax.state === STATE.UPDATE) {
this.checkScriptSiblings(script); this.checkScriptSiblings(script); // remove preJax/postJax etc.
result = this.inputJax[type].Process(script); var type = script.type.replace(/ *;(.|\s)*/,""); // the input jax type
if (typeof result === 'function') { jax = this.inputJax[type].Process(script); // run the input jax
if (result.called) continue; // go back and call Process() again if (typeof jax === 'function') { // if a callback was returned
this.RestartAfter(result); if (jax.called) continue; // go back and call Process() again
this.RestartAfter(jax); // wait for the callback
} }
result.Attach(script,this.inputJax[type].id); jax.Attach(script,this.inputJax[type].id); // register the jax on the script
script.MathJax.state = STATE.OUTPUT; script.MathJax.state = STATE.OUTPUT; // mark it as needing output
//
if (!this.outputJax[jax.mimeType]) { // check for existing output jax
script.MathJax.state = STATE.UPDATE;
throw Error("No output jax registered for "+jax.mimeType);
}
//
// Record the output jax
// and put this script in the queue for that jax
//
jax.outputJax = this.outputJax[jax.mimeType][0].id;
if (!state.jax[jax.outputJax]) {state.jax[jax.outputJax] = []}
state.jax[jax.outputJax].push(script);
}
//
// Go on to the next script, and check if we need to update the processing message
//
state.i++; var now = new Date().getTime();
if (now - state.start > this.processUpdateTime && state.i < state.scripts.length) {
state.start = now;
tihs.processMessage(state,"Input");
this.RestartAfter(MathJax.Callback.Delay(1));
} }
i++;
if (new Date().getTime() - start > this.processUpdateTime && i < scripts.length)
{start = 0; this.RestartAfter(MathJax.Callback.Delay(1))}
} }
} catch (err) {return this.processError(err,scripts,i,n,start,"Input")} } catch (err) {return this.processError(err,state,"Input")}
if ((n || scripts.length) && this.config.showProcessingMessages) //
// Put up final message, reset the state and return
//
if (state.scripts.length && this.config.showProcessingMessages)
{MathJax.Message.Set("Processing math: 100%",0)} {MathJax.Message.Set("Processing math: 100%",0)}
state.start = new Date().getTime(); state.i = 0;
return null; return null;
}, },
//
// Pre- and post-translate sscripts by jax
// (to get scaling factors, hide/show output, and so on)
//
prepareOutput: function (state,method) {
for (var id in state.jax) {if (state.jax.hasOwnProperty(id)) {
var JAX = MathJax.OutputJax[id];
if (JAX[method]) {JAX[method](state.jax[id])}
}}
},
processOutput: function (scripts,start,n) { processOutput: function (state) {
if (arguments.callee.disabled) {return null} var result, STATE = MathJax.ElementJax.STATE, script, m = state.scripts.length;
if (!start) {start = new Date().getTime()}
var result, STATE = MathJax.ElementJax.STATE;
var i = 0, script;
try { try {
while (i < scripts.length) { //
script = scripts[i]; if (!script || !script.MathJax) {i++; continue} // Loop through the scripts
var jax = script.MathJax.elementJax; if (!jax) {i++; continue} //
if (!this.outputJax[jax.mimeType]) { while (state.i < m) {
script.MathJax.state = STATE.UPDATE; //
throw Error("No output jax registered for "+jax.mimeType); // Check that there is an element jax
} //
var outputJax = this.outputJax[jax.mimeType][0]; script = state.scripts[state.i]; if (!script || !script.MathJax) {state.i++; continue}
jax.outputJax = outputJax.id; var jax = script.MathJax.elementJax; if (!jax) {state.i++; continue}
result = outputJax.Process(script); //
// Call the output Jax's Process method (which will be its Translate()
// method once loaded) and if it returns a call back, restart the processing.
//
result = MathJax.OutputJax[jax.outputJax].Process(script);
if (typeof result === 'function') { if (typeof result === 'function') {
if (result.called) continue; // go back and call Process() again if (result.called) continue; // go back and call Process() again
this.RestartAfter(result); this.RestartAfter(result);
} }
script.MathJax.state = STATE.PROCESSED; i++; //
// Mark it as complete and remove the preview
//
script.MathJax.state = STATE.PROCESSED; state.i++;
if (script.MathJax.preview) {script.MathJax.preview.style.display = "none"}
//
// Signal that new math is available
//
this.signal.Post(["New Math",jax.inputID]); // FIXME: wait for this? (i.e., restart if returns uncalled callback) this.signal.Post(["New Math",jax.inputID]); // FIXME: wait for this? (i.e., restart if returns uncalled callback)
if (new Date().getTime() - start > this.processUpdateTime && i < scripts.length) //
{start = 0; this.RestartAfter(MathJax.Callback.Delay(1))} // Update the processing message, if needed
//
var now = new Date().getTime();
if (now - state.start > this.processUpdateTime && state.i < state.scripts.length) {
state.start = now;
this.processMessage(state,"Output");
this.RestartAfter(MathJax.Callback.Delay(1));
}
} }
} catch (err) {return this.processError(err,scripts,i,n,start,"Output")} } catch (err) {return this.processError(err,state,"Output")}
if ((n || scripts.length) && this.config.showProcessingMessages) { //
MathJax.Message.Set("Typesetting math: 100%",0); // Put up the typesetting-complete message
MathJax.Message.Clear(0); //
} if (state.scripts.length && this.config.showProcessingMessages)
{MathJax.Message.Set("Typesetting math: 100%",0,600)}
return null; return null;
}, },
postOutput: function (state) {
for (var id in state.jax) {if (state.jax.hasOwnProperty(id)) {
var JAX = MathJax.OutputJax[id];
if (JAX.postTranslate) {JAX.preTranslate(state.jax[id])}
}}
},
processError: function (err,scripts,i,n,start,type) { processMessage: function (state,type) {
if (!err.restart) { var m = Math.floor(state.i/(state.scripts.length)*100);
if (!this.config.errorSettings.message) {throw err}
this.formatError(scripts[i],err); i++;
}
if (!n) {n = 0}; var m = Math.floor((n+i)/(n+scripts.length)*100); n += i;
var message = (type === "Output" ? "Typesetting" : "Processing"); var message = (type === "Output" ? "Typesetting" : "Processing");
if (this.config.showProcessingMessages) {MathJax.Message.Set(message+" math: "+m+"%",0)} if (this.config.showProcessingMessages) {MathJax.Message.Set(message+" math: "+m+"%",0)}
return MathJax.Callback.After(["process"+type,this,scripts.slice(i),start,n],err.restart); },
processError: function (err,state,type) {
if (!err.restart) {
if (!this.config.errorSettings.message) {throw err}
this.formatError(state.scripts[state.i],err); state.i++;
}
this.processMessage(state,type);
return MathJax.Callback.After(["process"+type,this,state],err.restart);
}, },
formatError: function (script,err) { formatError: function (script,err) {