Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
asciimathml/ASCIIMathML.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1201 lines (1137 sloc)
56.5 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
ASCIIMathML.js | |
============== | |
This file contains JavaScript functions to convert ASCII math notation | |
and (some) LaTeX to Presentation MathML. The conversion is done while the | |
HTML page loads, and should work with Firefox and other browsers that can | |
render MathML. | |
Just add the next line to your HTML page with this file in the same folder: | |
<script type="text/javascript" src="ASCIIMathML.js"></script> | |
Version 2.2 Mar 3, 2014. | |
Latest version at https://github.com/mathjax/asciimathml | |
If you use it on a webpage, please send the URL to jipsen@chapman.edu | |
Copyright (c) 2014 Peter Jipsen and other ASCIIMathML.js contributors | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. | |
*/ | |
var asciimath = {}; | |
(function(){ | |
var mathcolor = "blue"; // change it to "" (to inherit) or another color | |
var mathfontsize = "1em"; // change to e.g. 1.2em for larger math | |
var mathfontfamily = "serif"; // change to "" to inherit (works in IE) | |
// or another family (e.g. "arial") | |
var automathrecognize = false; // writing "amath" on page makes this true | |
var checkForMathML = true; // check if browser can display MathML | |
var notifyIfNoMathML = true; // display note at top if no MathML capability | |
var alertIfNoMathML = false; // show alert box if no MathML capability | |
var translateOnLoad = true; // set to false to do call translators from js | |
var translateASCIIMath = true; // false to preserve `..` | |
var displaystyle = true; // puts limits above and below large operators | |
var showasciiformulaonhover = true; // helps students learn ASCIIMath | |
var decimalsign = "."; // if "," then when writing lists or matrices put | |
//a space after the "," like `(1, 2)` not `(1,2)` | |
var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters | |
var AMdocumentId = "wikitext" // PmWiki element containing math (default=body) | |
var fixphi = true; //false to return to legacy phi/varphi mapping | |
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ | |
var isIE = (navigator.appName.slice(0,9)=="Microsoft"); | |
var noMathML = false, translated = false; | |
if (isIE) { // add MathPlayer info to IE webpages | |
document.write("<object id=\"mathplayer\"\ | |
classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>"); | |
document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>"); | |
} | |
// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW) | |
function setStylesheet(s) { | |
var id = "AMMLcustomStyleSheet"; | |
var n = document.getElementById(id); | |
if(document.createStyleSheet) { | |
// Test for IE's non-standard createStyleSheet method | |
if(n) | |
n.parentNode.removeChild(n); | |
// This failed without the | |
document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd"," <style id='" + id + "'>" + s + "</style>"); | |
} else { | |
if(n) { | |
n.replaceChild(document.createTextNode(s),n.firstChild); | |
} else { | |
n = document.createElement("style"); | |
n.type = "text/css"; | |
n.id = id; | |
n.appendChild(document.createTextNode(s)); | |
document.getElementsByTagName("head")[0].appendChild(n); | |
} | |
} | |
} | |
setStylesheet("#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}"); | |
function init(){ | |
var msg, warnings = new Array(); | |
if (document.getElementById==null){ | |
alert("This webpage requires a recent browser such as Mozilla Firefox"); | |
return null; | |
} | |
if (checkForMathML && (msg = checkMathML())) warnings.push(msg); | |
if (warnings.length>0) displayWarnings(warnings); | |
if (!noMathML) initSymbols(); | |
return true; | |
} | |
function checkMathML(){ | |
if (navigator.appName.slice(0,8)=="Netscape") | |
if (navigator.appVersion.slice(0,1)>="5") noMathML = null; | |
else noMathML = true; | |
else if (navigator.appName.slice(0,9)=="Microsoft") | |
try { | |
var ActiveX = new ActiveXObject("MathPlayer.Factory.1"); | |
noMathML = null; | |
} catch (e) { | |
noMathML = true; | |
} | |
else if (navigator.appName.slice(0,5)=="Opera") | |
if (navigator.appVersion.slice(0,3)>="9.5") noMathML = null; | |
else noMathML = true; | |
//noMathML = true; //uncomment to check | |
if (noMathML && notifyIfNoMathML) { | |
var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later."; | |
if (alertIfNoMathML) | |
alert(msg); | |
else return msg; | |
} | |
} | |
function hideWarning(){ | |
var body = document.getElementsByTagName("body")[0]; | |
body.removeChild(document.getElementById('AMMLwarningBox')); | |
body.onclick = null; | |
} | |
function displayWarnings(warnings) { | |
var i, frag, nd = createElementXHTML("div"); | |
var body = document.getElementsByTagName("body")[0]; | |
body.onclick=hideWarning; | |
nd.id = 'AMMLwarningBox'; | |
for (i=0; i<warnings.length; i++) { | |
frag = createElementXHTML("div"); | |
frag.appendChild(document.createTextNode(warnings[i])); | |
frag.style.paddingBottom = "1.0em"; | |
nd.appendChild(frag); | |
} | |
nd.appendChild(createElementXHTML("p")); | |
nd.appendChild(document.createTextNode("For instructions see the ")); | |
var an = createElementXHTML("a"); | |
an.appendChild(document.createTextNode("ASCIIMathML")); | |
an.setAttribute("href","http://asciimath.org"); | |
nd.appendChild(an); | |
nd.appendChild(document.createTextNode(" homepage")); | |
an = createElementXHTML("div"); | |
an.id = 'AMMLcloseDiv'; | |
an.appendChild(document.createTextNode('(click anywhere to close this warning)')); | |
nd.appendChild(an); | |
var body = document.getElementsByTagName("body")[0]; | |
body.insertBefore(nd,body.childNodes[0]); | |
} | |
function translate(spanclassAM) { | |
if (!translated) { // run this only once | |
translated = true; | |
var body = document.getElementsByTagName("body")[0]; | |
var processN = document.getElementById(AMdocumentId); | |
if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM); | |
} | |
} | |
function createElementXHTML(t) { | |
if (isIE) return document.createElement(t); | |
else return document.createElementNS("http://www.w3.org/1999/xhtml",t); | |
} | |
var AMmathml = "http://www.w3.org/1998/Math/MathML"; | |
function AMcreateElementMathML(t) { | |
if (isIE) return document.createElement("m:"+t); | |
else return document.createElementNS(AMmathml,t); | |
} | |
function createMmlNode(t,frag) { | |
var node; | |
if (isIE) node = document.createElement("m:"+t); | |
else node = document.createElementNS(AMmathml,t); | |
if (frag) node.appendChild(frag); | |
return node; | |
} | |
function newcommand(oldstr,newstr) { | |
AMsymbols.push({input:oldstr, tag:"mo", output:newstr, tex:null, ttype:DEFINITION}); | |
refreshSymbols(); | |
} | |
function newsymbol(symbolobj) { | |
AMsymbols.push(symbolobj); | |
refreshSymbols(); | |
} | |
// character lists for Mozilla/Netscape fonts | |
var AMcal = ["\uD835\uDC9C","\u212C","\uD835\uDC9E","\uD835\uDC9F","\u2130","\u2131","\uD835\uDCA2","\u210B","\u2110","\uD835\uDCA5","\uD835\uDCA6","\u2112","\u2133","\uD835\uDCA9","\uD835\uDCAA","\uD835\uDCAB","\uD835\uDCAC","\u211B","\uD835\uDCAE","\uD835\uDCAF","\uD835\uDCB0","\uD835\uDCB1","\uD835\uDCB2","\uD835\uDCB3","\uD835\uDCB4","\uD835\uDCB5","\uD835\uDCB6","\uD835\uDCB7","\uD835\uDCB8","\uD835\uDCB9","\u212F","\uD835\uDCBB","\u210A","\uD835\uDCBD","\uD835\uDCBE","\uD835\uDCBF","\uD835\uDCC0","\uD835\uDCC1","\uD835\uDCC2","\uD835\uDCC3","\u2134","\uD835\uDCC5","\uD835\uDCC6","\uD835\uDCC7","\uD835\uDCC8","\uD835\uDCC9","\uD835\uDCCA","\uD835\uDCCB","\uD835\uDCCC","\uD835\uDCCD","\uD835\uDCCE","\uD835\uDCCF"]; | |
var AMfrk = ["\uD835\uDD04","\uD835\uDD05","\u212D","\uD835\uDD07","\uD835\uDD08","\uD835\uDD09","\uD835\uDD0A","\u210C","\u2111","\uD835\uDD0D","\uD835\uDD0E","\uD835\uDD0F","\uD835\uDD10","\uD835\uDD11","\uD835\uDD12","\uD835\uDD13","\uD835\uDD14","\u211C","\uD835\uDD16","\uD835\uDD17","\uD835\uDD18","\uD835\uDD19","\uD835\uDD1A","\uD835\uDD1B","\uD835\uDD1C","\u2128","\uD835\uDD1E","\uD835\uDD1F","\uD835\uDD20","\uD835\uDD21","\uD835\uDD22","\uD835\uDD23","\uD835\uDD24","\uD835\uDD25","\uD835\uDD26","\uD835\uDD27","\uD835\uDD28","\uD835\uDD29","\uD835\uDD2A","\uD835\uDD2B","\uD835\uDD2C","\uD835\uDD2D","\uD835\uDD2E","\uD835\uDD2F","\uD835\uDD30","\uD835\uDD31","\uD835\uDD32","\uD835\uDD33","\uD835\uDD34","\uD835\uDD35","\uD835\uDD36","\uD835\uDD37"]; | |
var AMbbb = ["\uD835\uDD38","\uD835\uDD39","\u2102","\uD835\uDD3B","\uD835\uDD3C","\uD835\uDD3D","\uD835\uDD3E","\u210D","\uD835\uDD40","\uD835\uDD41","\uD835\uDD42","\uD835\uDD43","\uD835\uDD44","\u2115","\uD835\uDD46","\u2119","\u211A","\u211D","\uD835\uDD4A","\uD835\uDD4B","\uD835\uDD4C","\uD835\uDD4D","\uD835\uDD4E","\uD835\uDD4F","\uD835\uDD50","\u2124","\uD835\uDD52","\uD835\uDD53","\uD835\uDD54","\uD835\uDD55","\uD835\uDD56","\uD835\uDD57","\uD835\uDD58","\uD835\uDD59","\uD835\uDD5A","\uD835\uDD5B","\uD835\uDD5C","\uD835\uDD5D","\uD835\uDD5E","\uD835\uDD5F","\uD835\uDD60","\uD835\uDD61","\uD835\uDD62","\uD835\uDD63","\uD835\uDD64","\uD835\uDD65","\uD835\uDD66","\uD835\uDD67","\uD835\uDD68","\uD835\uDD69","\uD835\uDD6A","\uD835\uDD6B"]; | |
/*var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46]; | |
var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128]; | |
var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];*/ | |
var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4, | |
RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8, | |
LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13, | |
MATRIX = 14, UNARYUNDEROVER = 15; // token types | |
var AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT}; | |
var AMsymbols = [ | |
//some greek symbols | |
{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST}, | |
{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST}, | |
{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST}, | |
{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST}, | |
{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST}, | |
{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST}, | |
{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST}, | |
{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST}, | |
{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST}, | |
{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST}, | |
{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST}, | |
{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST}, | |
{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST}, | |
{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST}, | |
{input:"lamda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST}, | |
{input:"Lamda", tag:"mo", output:"\u039B", tex:null, ttype:CONST}, | |
{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST}, | |
{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST}, | |
{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST}, | |
{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST}, | |
{input:"phi", tag:"mi", output:fixphi?"\u03D5":"\u03C6", tex:null, ttype:CONST}, | |
{input:"varphi", tag:"mi", output:fixphi?"\u03C6":"\u03D5", tex:null, ttype:CONST}, | |
{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST}, | |
{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST}, | |
{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST}, | |
{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST}, | |
{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST}, | |
{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST}, | |
{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST}, | |
{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST}, | |
{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST}, | |
{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST}, | |
{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST}, | |
{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST}, | |
{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST}, | |
{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST}, | |
{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST}, | |
{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST}, | |
//binary operation symbols | |
//{input:"-", tag:"mo", output:"\u0096", tex:null, ttype:CONST}, | |
{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST}, | |
{input:"**", tag:"mo", output:"\u2217", tex:"ast", ttype:CONST}, | |
{input:"***", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST}, | |
{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST}, | |
{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST}, | |
{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST}, | |
{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST}, | |
{input:"|><", tag:"mo", output:"\u22C9", tex:"ltimes", ttype:CONST}, | |
{input:"><|", tag:"mo", output:"\u22CA", tex:"rtimes", ttype:CONST}, | |
{input:"|><|", tag:"mo", output:"\u22C8", tex:"bowtie", ttype:CONST}, | |
{input:"-:", tag:"mo", output:"\u00F7", tex:"div", ttype:CONST}, | |
{input:"divide", tag:"mo", output:"-:", tex:null, ttype:DEFINITION}, | |
{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST}, | |
{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST}, | |
{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST}, | |
{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST}, | |
{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER}, | |
{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER}, | |
{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST}, | |
{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER}, | |
{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST}, | |
{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER}, | |
{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST}, | |
{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER}, | |
{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST}, | |
{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER}, | |
//binary relation symbols | |
{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST}, | |
{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST}, | |
{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST}, | |
{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST}, | |
{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST}, | |
{input:"gt", tag:"mo", output:">", tex:null, ttype:CONST}, | |
{input:"mlt", tag:"mo", output:"\u226A", tex:"ll", ttype:CONST}, | |
{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST}, | |
{input:"gt=", tag:"mo", output:"\u2265", tex:"geq", ttype:CONST}, | |
{input:"mgt", tag:"mo", output:"\u226B", tex:"gg", ttype:CONST}, | |
{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST}, | |
{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST}, | |
{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST}, | |
{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST}, | |
{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST}, | |
{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST}, | |
{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST}, | |
{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST}, | |
{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST}, | |
{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST}, | |
{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST}, | |
{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST}, | |
{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST}, | |
{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST}, | |
{input:"~", tag:"mo", output:"\u223C", tex:"sim", ttype:CONST}, | |
{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST}, | |
//logical symbols | |
{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE}, | |
{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE}, | |
{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST}, | |
{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST}, | |
{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE}, | |
{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST}, | |
{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST}, | |
{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST}, | |
{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST}, | |
{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST}, | |
{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST}, | |
{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST}, | |
//grouping brackets | |
{input:"(", tag:"mo", output:"(", tex:"left(", ttype:LEFTBRACKET}, | |
{input:")", tag:"mo", output:")", tex:"right)", ttype:RIGHTBRACKET}, | |
{input:"[", tag:"mo", output:"[", tex:"left[", ttype:LEFTBRACKET}, | |
{input:"]", tag:"mo", output:"]", tex:"right]", ttype:RIGHTBRACKET}, | |
{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET}, | |
{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET}, | |
{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT}, | |
{input:":|:", tag:"mo", output:"|", tex:null, ttype:CONST}, | |
{input:"|:", tag:"mo", output:"|", tex:null, ttype:LEFTBRACKET}, | |
{input:":|", tag:"mo", output:"|", tex:null, ttype:RIGHTBRACKET}, | |
//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT}, | |
{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET}, | |
{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET}, | |
{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET}, | |
{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET}, | |
{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true}, | |
{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true}, | |
//miscellaneous symbols | |
{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST}, | |
{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION}, | |
{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION}, | |
{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION}, | |
{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION}, | |
{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST}, | |
{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST}, | |
{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST}, | |
{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST}, | |
{input:"-+", tag:"mo", output:"\u2213", tex:"mp", ttype:CONST}, | |
{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST}, | |
{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST}, | |
{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST}, | |
{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST}, | |
{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST}, | |
{input:":'", tag:"mo", output:"\u2235", tex:"because", ttype:CONST}, | |
{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST}, | |
{input:"/_\\", tag:"mo", output:"\u25B3", tex:"triangle", ttype:CONST}, | |
{input:"'", tag:"mo", output:"\u2032", tex:"prime", ttype:CONST}, | |
{input:"tilde", tag:"mover", output:"~", tex:null, ttype:UNARY, acc:true}, | |
{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST}, | |
{input:"frown", tag:"mo", output:"\u2322", tex:null, ttype:CONST}, | |
{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST}, | |
{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST}, | |
{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST}, | |
{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST}, | |
{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST}, | |
{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST}, | |
{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST}, | |
{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST}, | |
{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST}, | |
{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST}, | |
{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST}, | |
{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST}, | |
{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST}, | |
{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST}, | |
{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST}, | |
{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST}, | |
{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true}, | |
{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true}, | |
//standard functions | |
{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER}, | |
{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER}, | |
{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true}, | |
{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true}, | |
{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true}, | |
{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true}, | |
{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true}, | |
{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true}, | |
{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true}, | |
{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true}, | |
{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true}, | |
{input:"arcsin", tag:"mo", output:"arcsin", tex:null, ttype:UNARY, func:true}, | |
{input:"arccos", tag:"mo", output:"arccos", tex:null, ttype:UNARY, func:true}, | |
{input:"arctan", tag:"mo", output:"arctan", tex:null, ttype:UNARY, func:true}, | |
{input:"coth", tag:"mo", output:"coth", tex:null, ttype:UNARY, func:true}, | |
{input:"sech", tag:"mo", output:"sech", tex:null, ttype:UNARY, func:true}, | |
{input:"csch", tag:"mo", output:"csch", tex:null, ttype:UNARY, func:true}, | |
{input:"exp", tag:"mo", output:"exp", tex:null, ttype:UNARY, func:true}, | |
{input:"abs", tag:"mo", output:"abs", tex:null, ttype:UNARY, rewriteleftright:["|","|"]}, | |
{input:"norm", tag:"mo", output:"norm", tex:null, ttype:UNARY, rewriteleftright:["\u2225","\u2225"]}, | |
{input:"floor", tag:"mo", output:"floor", tex:null, ttype:UNARY, rewriteleftright:["\u230A","\u230B"]}, | |
{input:"ceil", tag:"mo", output:"ceil", tex:null, ttype:UNARY, rewriteleftright:["\u2308","\u2309"]}, | |
{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true}, | |
{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true}, | |
{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true}, | |
{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST}, | |
{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST}, | |
{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true}, | |
{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true}, | |
{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST}, | |
{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST}, | |
{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER}, | |
{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER}, | |
{input:"Sin", tag:"mo", output:"Sin", tex:null, ttype:UNARY, func:true}, | |
{input:"Cos", tag:"mo", output:"Cos", tex:null, ttype:UNARY, func:true}, | |
{input:"Tan", tag:"mo", output:"Tan", tex:null, ttype:UNARY, func:true}, | |
{input:"Arcsin", tag:"mo", output:"Arcsin", tex:null, ttype:UNARY, func:true}, | |
{input:"Arccos", tag:"mo", output:"Arccos", tex:null, ttype:UNARY, func:true}, | |
{input:"Arctan", tag:"mo", output:"Arctan", tex:null, ttype:UNARY, func:true}, | |
{input:"Sinh", tag:"mo", output:"Sinh", tex:null, ttype:UNARY, func:true}, | |
{input:"Cosh", tag:"mo", output:"Cosh", tex:null, ttype:UNARY, func:true}, | |
{input:"Tanh", tag:"mo", output:"Tanh", tex:null, ttype:UNARY, func:true}, | |
{input:"Cot", tag:"mo", output:"Cot", tex:null, ttype:UNARY, func:true}, | |
{input:"Sec", tag:"mo", output:"Sec", tex:null, ttype:UNARY, func:true}, | |
{input:"Csc", tag:"mo", output:"Csc", tex:null, ttype:UNARY, func:true}, | |
{input:"Log", tag:"mo", output:"Log", tex:null, ttype:UNARY, func:true}, | |
{input:"Ln", tag:"mo", output:"Ln", tex:null, ttype:UNARY, func:true}, | |
{input:"Abs", tag:"mo", output:"abs", tex:null, ttype:UNARY, notexcopy:true, rewriteleftright:["|","|"]}, | |
//arrows | |
{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST}, | |
{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST}, | |
{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST}, | |
{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST}, | |
{input:">->", tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST}, | |
{input:"->>", tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST}, | |
{input:">->>", tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST}, | |
{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST}, | |
{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST}, | |
{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST}, | |
{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST}, | |
{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST}, | |
{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST}, | |
//commands with argument | |
{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY}, | |
{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY}, | |
{input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY}, | |
{input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX}, | |
{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY}, | |
{input:"overset", tag:"mover", output:"stackrel", tex:null, ttype:BINARY}, | |
{input:"underset", tag:"munder", output:"stackrel", tex:null, ttype:BINARY}, | |
{input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX}, | |
{input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX}, | |
{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true}, | |
{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true}, | |
{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true}, | |
{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true}, | |
{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true}, | |
{input:"overarc", tag:"mover", output:"\u23DC", tex:"overparen", ttype:UNARY, acc:true}, | |
{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true}, | |
{input:"ubrace", tag:"munder", output:"\u23DF", tex:"underbrace", ttype:UNARYUNDEROVER, acc:true}, | |
{input:"obrace", tag:"mover", output:"\u23DE", tex:"overbrace", ttype:UNARYUNDEROVER, acc:true}, | |
{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT}, | |
{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT}, | |
{input:"color", tag:"mstyle", ttype:BINARY}, | |
{input:"id", tag:"mrow", ttype:BINARY}, | |
{input:"class", tag:"mrow", ttype:BINARY}, | |
{input:"cancel", tag:"menclose", output:"cancel", tex:null, ttype:UNARY}, | |
AMquote, | |
{input:"bb", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"bb", tex:null, ttype:UNARY}, | |
{input:"mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"mathbf", tex:null, ttype:UNARY}, | |
{input:"sf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY}, | |
{input:"mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY}, | |
{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb}, | |
{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb}, | |
{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal}, | |
{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal}, | |
{input:"tt", tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"tt", tex:null, ttype:UNARY}, | |
{input:"mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY}, | |
{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk}, | |
{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk} | |
]; | |
function compareNames(s1,s2) { | |
if (s1.input > s2.input) return 1 | |
else return -1; | |
} | |
var AMnames = []; //list of input symbols | |
function initSymbols() { | |
var i; | |
var symlen = AMsymbols.length; | |
for (i=0; i<symlen; i++) { | |
if (AMsymbols[i].tex) { | |
AMsymbols.push({input:AMsymbols[i].tex, | |
tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype, | |
acc:(AMsymbols[i].acc||false)}); | |
} | |
} | |
refreshSymbols(); | |
} | |
function refreshSymbols(){ | |
var i; | |
AMsymbols.sort(compareNames); | |
for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input; | |
} | |
function define(oldstr,newstr) { | |
AMsymbols.push({input:oldstr, tag:"mo", output:newstr, tex:null, ttype:DEFINITION}); | |
refreshSymbols(); // this may be a problem if many symbols are defined! | |
} | |
function AMremoveCharsAndBlanks(str,n) { | |
//remove n characters and any following blanks | |
var st; | |
if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ") | |
st = str.slice(n+1); | |
else st = str.slice(n); | |
for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1); | |
return st.slice(i); | |
} | |
function position(arr, str, n) { | |
// return position >=n where str appears or would be inserted | |
// assumes arr is sorted | |
if (n==0) { | |
var h,m; | |
n = -1; | |
h = arr.length; | |
while (n+1<h) { | |
m = (n+h) >> 1; | |
if (arr[m]<str) n = m; else h = m; | |
} | |
return h; | |
} else | |
for (var i=n; i<arr.length && arr[i]<str; i++); | |
return i; // i=arr.length || arr[i]>=str | |
} | |
function AMgetSymbol(str) { | |
//return maximal initial substring of str that appears in names | |
//return null if there is none | |
var k = 0; //new pos | |
var j = 0; //old pos | |
var mk; //match pos | |
var st; | |
var tagst; | |
var match = ""; | |
var more = true; | |
for (var i=1; i<=str.length && more; i++) { | |
st = str.slice(0,i); //initial substring of length i | |
j = k; | |
k = position(AMnames, st, j); | |
if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){ | |
match = AMnames[k]; | |
mk = k; | |
i = match.length; | |
} | |
more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k]; | |
} | |
AMpreviousSymbol=AMcurrentSymbol; | |
if (match!=""){ | |
AMcurrentSymbol=AMsymbols[mk].ttype; | |
return AMsymbols[mk]; | |
} | |
// if str[0] is a digit or - return maxsubstring of digits.digits | |
AMcurrentSymbol=CONST; | |
k = 1; | |
st = str.slice(0,1); | |
var integ = true; | |
while ("0"<=st && st<="9" && k<=str.length) { | |
st = str.slice(k,k+1); | |
k++; | |
} | |
if (st == decimalsign) { | |
st = str.slice(k,k+1); | |
if ("0"<=st && st<="9") { | |
integ = false; | |
k++; | |
while ("0"<=st && st<="9" && k<=str.length) { | |
st = str.slice(k,k+1); | |
k++; | |
} | |
} | |
} | |
if ((integ && k>1) || k>2) { | |
st = str.slice(0,k-1); | |
tagst = "mn"; | |
} else { | |
k = 2; | |
st = str.slice(0,1); //take 1 character | |
tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi"); | |
} | |
if (st=="-" && str.charAt(1)!==' ' && AMpreviousSymbol==INFIX) { | |
AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse | |
return {input:st, tag:tagst, output:st, ttype:UNARY, func:true}; | |
} | |
return {input:st, tag:tagst, output:st, ttype:CONST}; | |
} | |
function AMremoveBrackets(node) { | |
var st; | |
if (!node.hasChildNodes()) { return; } | |
if (node.firstChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) { | |
if (node.firstChild.nextSibling && node.firstChild.nextSibling.nodeName=="mtable") { return; } | |
st = node.firstChild.firstChild.nodeValue; | |
if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild); | |
} | |
if (node.lastChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) { | |
st = node.lastChild.firstChild.nodeValue; | |
if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild); | |
} | |
} | |
/*Parsing ASCII math expressions with the following grammar | |
v ::= [A-Za-z] | greek letters | numbers | other constant symbols | |
u ::= sqrt | text | bb | other unary symbols for font commands | |
b ::= frac | root | stackrel binary symbols | |
l ::= ( | [ | { | (: | {: left brackets | |
r ::= ) | ] | } | :) | :} right brackets | |
S ::= v | lEr | uS | bSS Simple expression | |
I ::= S_S | S^S | S_S^S | S Intermediate expression | |
E ::= IE | I/I Expression | |
Each terminal symbol is translated into a corresponding mathml node.*/ | |
var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol; | |
function AMparseSexpr(str) { //parses str and returns [node,tailstr] | |
var symbol, node, result, i, st,// rightvert = false, | |
newFrag = document.createDocumentFragment(); | |
str = AMremoveCharsAndBlanks(str,0); | |
symbol = AMgetSymbol(str); //either a token or a bracket or empty | |
if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) { | |
return [null,str]; | |
} | |
if (symbol.ttype == DEFINITION) { | |
str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); | |
symbol = AMgetSymbol(str); | |
} | |
switch (symbol.ttype) { case UNDEROVER: | |
case CONST: | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
return [createMmlNode(symbol.tag, //its a constant | |
document.createTextNode(symbol.output)),str]; | |
case LEFTBRACKET: //read (expr+) | |
AMnestingDepth++; | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
result = AMparseExpr(str,true); | |
AMnestingDepth--; | |
if (typeof symbol.invisible == "boolean" && symbol.invisible) | |
node = createMmlNode("mrow",result[0]); | |
else { | |
node = createMmlNode("mo",document.createTextNode(symbol.output)); | |
node = createMmlNode("mrow",node); | |
node.appendChild(result[0]); | |
} | |
return [node,result[1]]; | |
case TEXT: | |
if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
if (str.charAt(0)=="{") i=str.indexOf("}"); | |
else if (str.charAt(0)=="(") i=str.indexOf(")"); | |
else if (str.charAt(0)=="[") i=str.indexOf("]"); | |
else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1; | |
else i = 0; | |
if (i==-1) i = str.length; | |
st = str.slice(1,i); | |
if (st.charAt(0) == " ") { | |
node = createMmlNode("mspace"); | |
node.setAttribute("width","1ex"); | |
newFrag.appendChild(node); | |
} | |
newFrag.appendChild( | |
createMmlNode(symbol.tag,document.createTextNode(st))); | |
if (st.charAt(st.length-1) == " ") { | |
node = createMmlNode("mspace"); | |
node.setAttribute("width","1ex"); | |
newFrag.appendChild(node); | |
} | |
str = AMremoveCharsAndBlanks(str,i+1); | |
return [createMmlNode("mrow",newFrag),str]; | |
case UNARYUNDEROVER: | |
case UNARY: | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
result = AMparseSexpr(str); | |
if (result[0]==null) { | |
if (symbol.tag=="mi" || symbol.tag=="mo") { | |
return [createMmlNode(symbol.tag, | |
document.createTextNode(symbol.output)),str]; | |
} else { | |
result[0] = createMmlNode("mi", ""); | |
} | |
} | |
if (typeof symbol.func == "boolean" && symbol.func) { // functions hack | |
st = str.charAt(0); | |
if (st=="^" || st=="_" || st=="/" || st=="|" || st=="," || | |
(symbol.input.length==1 && symbol.input.match(/\w/) && st!="(")) { | |
return [createMmlNode(symbol.tag, | |
document.createTextNode(symbol.output)),str]; | |
} else { | |
node = createMmlNode("mrow", | |
createMmlNode(symbol.tag,document.createTextNode(symbol.output))); | |
node.appendChild(result[0]); | |
return [node,result[1]]; | |
} | |
} | |
AMremoveBrackets(result[0]); | |
if (symbol.input == "sqrt") { // sqrt | |
return [createMmlNode(symbol.tag,result[0]),result[1]]; | |
} else if (typeof symbol.rewriteleftright != "undefined") { // abs, floor, ceil | |
node = createMmlNode("mrow", createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[0]))); | |
node.appendChild(result[0]); | |
node.appendChild(createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[1]))); | |
return [node,result[1]]; | |
} else if (symbol.input == "cancel") { // cancel | |
node = createMmlNode(symbol.tag,result[0]); | |
node.setAttribute("notation","updiagonalstrike"); | |
return [node,result[1]]; | |
} else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent | |
node = createMmlNode(symbol.tag,result[0]); | |
var accnode = createMmlNode("mo",document.createTextNode(symbol.output)); | |
if (symbol.input=="vec" && ( | |
(result[0].nodeName=="mrow" && result[0].childNodes.length==1 | |
&& result[0].firstChild.firstChild.nodeValue !== null | |
&& result[0].firstChild.firstChild.nodeValue.length==1) || | |
(result[0].firstChild && result[0].firstChild.nodeValue !== null | |
&& result[0].firstChild.nodeValue.length==1) )) { | |
accnode.setAttribute("stretchy",false); | |
} | |
node.appendChild(accnode); | |
return [node,result[1]]; | |
} else { // font change command | |
if (!isIE && typeof symbol.codes != "undefined") { | |
for (i=0; i<result[0].childNodes.length; i++) | |
if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") { | |
st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue: | |
result[0].childNodes[i].firstChild.nodeValue); | |
var newst = []; | |
for (var j=0; j<st.length; j++) | |
if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) | |
newst = newst + symbol.codes[st.charCodeAt(j)-65]; | |
else if (st.charCodeAt(j)>96 && st.charCodeAt(j)<123) | |
newst = newst + symbol.codes[st.charCodeAt(j)-71]; | |
else newst = newst + st.charAt(j); | |
if (result[0].nodeName=="mi") | |
result[0]=createMmlNode("mo"). | |
appendChild(document.createTextNode(newst)); | |
else result[0].replaceChild(createMmlNode("mo"). | |
appendChild(document.createTextNode(newst)), | |
result[0].childNodes[i]); | |
} | |
} | |
node = createMmlNode(symbol.tag,result[0]); | |
node.setAttribute(symbol.atname,symbol.atval); | |
return [node,result[1]]; | |
} | |
case BINARY: | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
result = AMparseSexpr(str); | |
if (result[0]==null) return [createMmlNode("mo", | |
document.createTextNode(symbol.input)),str]; | |
AMremoveBrackets(result[0]); | |
var result2 = AMparseSexpr(result[1]); | |
if (result2[0]==null) return [createMmlNode("mo", | |
document.createTextNode(symbol.input)),str]; | |
AMremoveBrackets(result2[0]); | |
if (['color', 'class', 'id'].indexOf(symbol.input) >= 0) { | |
// Get the second argument | |
if (str.charAt(0)=="{") i=str.indexOf("}"); | |
else if (str.charAt(0)=="(") i=str.indexOf(")"); | |
else if (str.charAt(0)=="[") i=str.indexOf("]"); | |
st = str.slice(1,i); | |
// Make a mathml node | |
node = createMmlNode(symbol.tag,result2[0]); | |
// Set the correct attribute | |
if (symbol.input === "color") node.setAttribute("mathcolor", st) | |
else if (symbol.input === "class") node.setAttribute("class", st) | |
else if (symbol.input === "id") node.setAttribute("id", st) | |
return [node,result2[1]]; | |
} | |
if (symbol.input=="root" || symbol.output=="stackrel") | |
newFrag.appendChild(result2[0]); | |
newFrag.appendChild(result[0]); | |
if (symbol.input=="frac") newFrag.appendChild(result2[0]); | |
return [createMmlNode(symbol.tag,newFrag),result2[1]]; | |
case INFIX: | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
return [createMmlNode("mo",document.createTextNode(symbol.output)),str]; | |
case SPACE: | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
node = createMmlNode("mspace"); | |
node.setAttribute("width","1ex"); | |
newFrag.appendChild(node); | |
newFrag.appendChild( | |
createMmlNode(symbol.tag,document.createTextNode(symbol.output))); | |
node = createMmlNode("mspace"); | |
node.setAttribute("width","1ex"); | |
newFrag.appendChild(node); | |
return [createMmlNode("mrow",newFrag),str]; | |
case LEFTRIGHT: | |
// if (rightvert) return [null,str]; else rightvert = true; | |
AMnestingDepth++; | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
result = AMparseExpr(str,false); | |
AMnestingDepth--; | |
st = ""; | |
if (result[0].lastChild!=null) | |
st = result[0].lastChild.firstChild.nodeValue; | |
if (st == "|" && str.charAt(0)!==",") { // its an absolute value subterm | |
node = createMmlNode("mo",document.createTextNode(symbol.output)); | |
node = createMmlNode("mrow",node); | |
node.appendChild(result[0]); | |
return [node,result[1]]; | |
} else { // the "|" is a \mid so use unicode 2223 (divides) for spacing | |
node = createMmlNode("mo",document.createTextNode("\u2223")); | |
node = createMmlNode("mrow",node); | |
return [node,str]; | |
} | |
default: | |
//alert("default"); | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
return [createMmlNode(symbol.tag, //its a constant | |
document.createTextNode(symbol.output)),str]; | |
} | |
} | |
function AMparseIexpr(str) { | |
var symbol, sym1, sym2, node, result, underover; | |
str = AMremoveCharsAndBlanks(str,0); | |
sym1 = AMgetSymbol(str); | |
result = AMparseSexpr(str); | |
node = result[0]; | |
str = result[1]; | |
symbol = AMgetSymbol(str); | |
if (symbol.ttype == INFIX && symbol.input != "/") { | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
// if (symbol.input == "/") result = AMparseIexpr(str); else ... | |
result = AMparseSexpr(str); | |
if (result[0] == null) // show box in place of missing argument | |
result[0] = createMmlNode("mo",document.createTextNode("\u25A1")); | |
else AMremoveBrackets(result[0]); | |
str = result[1]; | |
// if (symbol.input == "/") AMremoveBrackets(node); | |
underover = (sym1.ttype == UNDEROVER || sym1.ttype == UNARYUNDEROVER); | |
if (symbol.input == "_") { | |
sym2 = AMgetSymbol(str); | |
if (sym2.input == "^") { | |
str = AMremoveCharsAndBlanks(str,sym2.input.length); | |
var res2 = AMparseSexpr(str); | |
AMremoveBrackets(res2[0]); | |
str = res2[1]; | |
node = createMmlNode((underover?"munderover":"msubsup"),node); | |
node.appendChild(result[0]); | |
node.appendChild(res2[0]); | |
node = createMmlNode("mrow",node); // so sum does not stretch | |
} else { | |
node = createMmlNode((underover?"munder":"msub"),node); | |
node.appendChild(result[0]); | |
} | |
} else if (symbol.input == "^" && underover) { | |
node = createMmlNode("mover",node); | |
node.appendChild(result[0]); | |
} else { | |
node = createMmlNode(symbol.tag,node); | |
node.appendChild(result[0]); | |
} | |
if (typeof sym1.func != 'undefined' && sym1.func) { | |
sym2 = AMgetSymbol(str); | |
if (sym2.ttype != INFIX && sym2.ttype != RIGHTBRACKET && | |
(sym1.input.length>1 || sym2.ttype == LEFTBRACKET)) { | |
result = AMparseIexpr(str); | |
node = createMmlNode("mrow",node); | |
node.appendChild(result[0]); | |
str = result[1]; | |
} | |
} | |
} | |
return [node,str]; | |
} | |
function AMparseExpr(str,rightbracket) { | |
var symbol, node, result, i, | |
newFrag = document.createDocumentFragment(); | |
do { | |
str = AMremoveCharsAndBlanks(str,0); | |
result = AMparseIexpr(str); | |
node = result[0]; | |
str = result[1]; | |
symbol = AMgetSymbol(str); | |
if (symbol.ttype == INFIX && symbol.input == "/") { | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
result = AMparseIexpr(str); | |
if (result[0] == null) // show box in place of missing argument | |
result[0] = createMmlNode("mo",document.createTextNode("\u25A1")); | |
else AMremoveBrackets(result[0]); | |
str = result[1]; | |
AMremoveBrackets(node); | |
node = createMmlNode(symbol.tag,node); | |
node.appendChild(result[0]); | |
newFrag.appendChild(node); | |
symbol = AMgetSymbol(str); | |
} | |
else if (node!=undefined) newFrag.appendChild(node); | |
} while ((symbol.ttype != RIGHTBRACKET && | |
(symbol.ttype != LEFTRIGHT || rightbracket) | |
|| AMnestingDepth == 0) && symbol!=null && symbol.output!=""); | |
if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) { | |
// if (AMnestingDepth > 0) AMnestingDepth--; | |
var len = newFrag.childNodes.length; | |
if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" | |
&& newFrag.childNodes[len-1].lastChild | |
&& newFrag.childNodes[len-1].lastChild.firstChild ) { //matrix | |
//removed to allow row vectors: //&& len>1 && | |
//newFrag.childNodes[len-2].nodeName == "mo" && | |
//newFrag.childNodes[len-2].firstChild.nodeValue == "," | |
var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue; | |
if (right==")" || right=="]") { | |
var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue; | |
if (left=="(" && right==")" && symbol.output != "}" || | |
left=="[" && right=="]") { | |
var pos = []; // positions of commas | |
var matrix = true; | |
var m = newFrag.childNodes.length; | |
for (i=0; matrix && i<m; i=i+2) { | |
pos[i] = []; | |
node = newFrag.childNodes[i]; | |
if (matrix) matrix = node.nodeName=="mrow" && | |
(i==m-1 || node.nextSibling.nodeName=="mo" && | |
node.nextSibling.firstChild.nodeValue==",")&& | |
node.firstChild.firstChild && | |
node.firstChild.firstChild.nodeValue==left && | |
node.lastChild.firstChild && | |
node.lastChild.firstChild.nodeValue==right; | |
if (matrix) | |
for (var j=0; j<node.childNodes.length; j++) | |
if (node.childNodes[j].firstChild.nodeValue==",") | |
pos[i][pos[i].length]=j; | |
if (matrix && i>1) matrix = pos[i].length == pos[i-2].length; | |
} | |
matrix = matrix && (pos.length>1 || pos[0].length>0); | |
var columnlines = []; | |
if (matrix) { | |
var row, frag, n, k, table = document.createDocumentFragment(); | |
for (i=0; i<m; i=i+2) { | |
row = document.createDocumentFragment(); | |
frag = document.createDocumentFragment(); | |
node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow> | |
n = node.childNodes.length; | |
k = 0; | |
node.removeChild(node.firstChild); //remove ( | |
for (j=1; j<n-1; j++) { | |
if (typeof pos[i][k] != "undefined" && j==pos[i][k]){ | |
node.removeChild(node.firstChild); //remove , | |
if (node.firstChild.nodeName=="mrow" && node.firstChild.childNodes.length==1 && | |
node.firstChild.firstChild.firstChild.nodeValue=="\u2223") { | |
//is columnline marker - skip it | |
if (i==0) { columnlines.push("solid"); } | |
node.removeChild(node.firstChild); //remove mrow | |
node.removeChild(node.firstChild); //remove , | |
j+=2; | |
k++; | |
} else if (i==0) { columnlines.push("none"); } | |
row.appendChild(createMmlNode("mtd",frag)); | |
k++; | |
} else frag.appendChild(node.firstChild); | |
} | |
row.appendChild(createMmlNode("mtd",frag)); | |
if (i==0) { columnlines.push("none"); } | |
if (newFrag.childNodes.length>2) { | |
newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow> | |
newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo> | |
} | |
table.appendChild(createMmlNode("mtr",row)); | |
} | |
node = createMmlNode("mtable",table); | |
node.setAttribute("columnlines", columnlines.join(" ")); | |
if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left"); | |
newFrag.replaceChild(node,newFrag.firstChild); | |
} | |
} | |
} | |
} | |
str = AMremoveCharsAndBlanks(str,symbol.input.length); | |
if (typeof symbol.invisible != "boolean" || !symbol.invisible) { | |
node = createMmlNode("mo",document.createTextNode(symbol.output)); | |
newFrag.appendChild(node); | |
} | |
} | |
return [newFrag,str]; | |
} | |
function parseMath(str,latex) { | |
var frag, node; | |
AMnestingDepth = 0; | |
//some basic cleanup for dealing with stuff editors like TinyMCE adds | |
str = str.replace(/ /g,""); | |
str = str.replace(/>/g,">"); | |
str = str.replace(/</g,"<"); | |
frag = AMparseExpr(str.replace(/^\s+/g,""),false)[0]; | |
node = createMmlNode("mstyle",frag); | |
if (mathcolor != "") node.setAttribute("mathcolor",mathcolor); | |
if (mathfontsize != "") { | |
node.setAttribute("fontsize", mathfontsize); | |
node.setAttribute("mathsize", mathfontsize); | |
} | |
if (mathfontfamily != "") { | |
node.setAttribute("fontfamily", mathfontfamily); | |
node.setAttribute("mathvariant", mathfontfamily); | |
} | |
if (displaystyle) node.setAttribute("displaystyle","true"); | |
node = createMmlNode("math",node); | |
if (showasciiformulaonhover) //fixed by djhsu so newline | |
node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko | |
return node; | |
} | |
function strarr2docFrag(arr, linebreaks, latex) { | |
var newFrag=document.createDocumentFragment(); | |
var expr = false; | |
for (var i=0; i<arr.length; i++) { | |
if (expr) newFrag.appendChild(parseMath(arr[i],latex)); | |
else { | |
var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]); | |
newFrag.appendChild(createElementXHTML("span"). | |
appendChild(document.createTextNode(arri[0]))); | |
for (var j=1; j<arri.length; j++) { | |
newFrag.appendChild(createElementXHTML("p")); | |
newFrag.appendChild(createElementXHTML("span"). | |
appendChild(document.createTextNode(arri[j]))); | |
} | |
} | |
expr = !expr; | |
} | |
return newFrag; | |
} | |
function AMautomathrec(str) { | |
//formula is a space (or start of str) followed by a maximal sequence of *two* or more tokens, possibly separated by runs of digits and/or space. | |
//tokens are single letters (except a, A, I) and ASCIIMathML tokens | |
var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|"; | |
var ambigAMtoken = "\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|"; | |
var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|"; | |
var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out | |
var simpleAMtoken = "NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta"; // uuu nnn? | |
var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|"; | |
var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken; | |
var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g"); | |
str = str.replace(re," `$2`$7"); | |
var arr = str.split(AMdelimiter1); | |
var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g"); | |
var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now | |
for (i=0; i<arr.length; i++) //single nonenglish tokens | |
if (i%2==0) { | |
arr[i] = arr[i].replace(re1," `$2`$3"); | |
arr[i] = arr[i].replace(re2," `$2`$3"); | |
arr[i] = arr[i].replace(/([{}[\]])/,"`$1`"); | |
} | |
str = arr.join(AMdelimiter1); | |
str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)"); //fix parentheses | |
str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3"); //fix parentheses | |
str = str.replace(/\sin`/g,"` in"); | |
str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`"); | |
str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2"); | |
str = str.replace(/`([0-9.]+:)`/g,"$1"); | |
return str; | |
} | |
function processNodeR(n, linebreaks,latex) { | |
var mtch, str, arr, frg, i; | |
if (n.childNodes.length == 0) { | |
if ((n.nodeType!=8 || linebreaks) && | |
n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" && | |
n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /*&& | |
n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"*/) { | |
str = n.nodeValue; | |
if (!(str == null)) { | |
str = str.replace(/\r\n\r\n/g,"\n\n"); | |
str = str.replace(/\x20+/g," "); | |
str = str.replace(/\s*\r\n/g," "); | |
if(latex) { | |
// DELIMITERS: | |
mtch = (str.indexOf("\$")==-1 ? false : true); | |
str = str.replace(/([^\\])\$/g,"$1 \$"); | |
str = str.replace(/^\$/," \$"); // in case \$ at start of string | |
arr = str.split(" \$"); | |
for (i=0; i<arr.length; i++) | |
arr[i]=arr[i].replace(/\\\$/g,"\$"); | |
} else { | |
mtch = false; | |
str = str.replace(new RegExp(AMescape1, "g"), | |
function(){mtch = true; return "AMescape1"}); | |
str = str.replace(/\\?end{?a?math}?/i, | |
function(){automathrecognize = false; mtch = true; return ""}); | |
str = str.replace(/amath\b|\\begin{a?math}/i, | |
function(){automathrecognize = true; mtch = true; return ""}); | |
arr = str.split(AMdelimiter1); | |
if (automathrecognize) | |
for (i=0; i<arr.length; i++) | |
if (i%2==0) arr[i] = AMautomathrec(arr[i]); | |
str = arr.join(AMdelimiter1); | |
arr = str.split(AMdelimiter1); | |
for (i=0; i<arr.length; i++) // this is a problem ************ | |
arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1); | |
} | |
if (arr.length>1 || mtch) { | |
if (!noMathML) { | |
frg = strarr2docFrag(arr,n.nodeType==8,latex); | |
var len = frg.childNodes.length; | |
n.parentNode.replaceChild(frg,n); | |
return len-1; | |
} else return 0; | |
} | |
} | |
} else return 0; | |
} else if (n.nodeName!="math") { | |
for (i=0; i<n.childNodes.length; i++) | |
i += processNodeR(n.childNodes[i], linebreaks,latex); | |
} | |
return 0; | |
} | |
function AMprocessNode(n, linebreaks, spanclassAM) { | |
var frag,st; | |
if (spanclassAM!=null) { | |
frag = document.getElementsByTagName("span") | |
for (var i=0;i<frag.length;i++) | |
if (frag[i].className == "AM") | |
processNodeR(frag[i],linebreaks,false); | |
} else { | |
try { | |
st = n.innerHTML; // look for AMdelimiter on page | |
} catch(err) {} | |
//alert(st) | |
if (st==null || /amath\b|\\begin{a?math}/i.test(st) || | |
st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 || | |
st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) { | |
processNodeR(n,linebreaks,false); | |
} | |
} | |
} | |
function generic(){ | |
if(!init()) return; | |
if (translateOnLoad) { | |
translate(); | |
} | |
}; | |
//setup onload function | |
if(typeof window.addEventListener != 'undefined'){ | |
//.. gecko, safari, konqueror and standard | |
window.addEventListener('load', generic, false); | |
} | |
else if(typeof document.addEventListener != 'undefined'){ | |
//.. opera 7 | |
document.addEventListener('load', generic, false); | |
} | |
else if(typeof window.attachEvent != 'undefined'){ | |
//.. win/ie | |
window.attachEvent('onload', generic); | |
}else{ | |
//.. mac/ie5 and anything else that gets this far | |
//if there's an existing onload function | |
if(typeof window.onload == 'function'){ | |
//store it | |
var existing = onload; | |
//add new onload handler | |
window.onload = function(){ | |
//call existing onload function | |
existing(); | |
//call generic onload function | |
generic(); | |
}; | |
}else{ | |
window.onload = generic; | |
} | |
} | |
//expose some functions to outside | |
asciimath.newcommand = newcommand; | |
asciimath.newsymbol = newsymbol; | |
asciimath.AMprocesssNode = AMprocessNode; | |
asciimath.parseMath = parseMath; | |
asciimath.translate = translate; | |
})(); |