4This file contains JavaScript functions to convert ASCII math notation
5and LaTeX to Presentation MathML. Simple graphics commands are also
6translated to SVG images. The conversion is done while the (X)HTML
7page loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet
8Explorer 6/7 + MathPlayer (http://www.dessci.com/en/products/mathplayer/) +
9Adobe SVGview 3.03 (http://www.adobe.com/svg/viewer/install/).
11Just add the next line to your (X)HTML page with this file in the same folder:
13<script type="text/javascript" src="ASCIIMathML.js"></script>
15(using the graphics in IE also requires the file "d.svg" in the same folder).
16This is a convenient and inexpensive solution for authoring MathML and SVG.
18Version 2.0.9 Nov 3, 2007, (c) Peter Jipsen http://www.chapman.edu/~jipsen
19This version extends ASCIIMathML.js with LaTeXMathML.js and ASCIIsvg.js.
20Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js
21If you use it on a webpage, please send the URL to jipsen@chapman.edu
23The LaTeXMathML modifications were made by Douglas Woodall, June 2006.
24(for details see header on the LaTeXMathML part in middle of file)
25Extensive clean-up and improvements by Paulo Soares, Oct 2007.
27This program is free software; you can redistribute it and/or modify
28it under the terms of the GNU Lesser General Public License as published by
29the Free Software Foundation; either version 2.1 of the License, or (at
30your option) any later version.
32This program is distributed in the hope that it will be useful, but WITHOUT
33ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
35(at http://www.gnu.org/licences/lgpl.html) for more details.
38var mathcolor = ""; // change it to "" (to inherit) or another color
39var mathfontsize = "1em"; // change to e.g. 1.2em for larger math
40var mathfontfamily = "serif"; // change to "" to inherit (works in IE)
41 // or another family (e.g. "arial")
42var automathrecognize = false; // writing "amath" on page makes this true
43var checkForMathML = true; // check if browser can display MathML
44var notifyIfNoMathML = true; // display note at top if no MathML capability
45var alertIfNoMathML = false; // show alert box if no MathML capability
46var translateOnLoad = true; // set to false to do call translators from js
47var translateLaTeX = true; // false to preserve $..$, $$..$$
48var translateLaTeXformatting = true; // false to preserve \emph,\begin{},\end{}
49var translateASCIIMath = true; // false to preserve `..`
50var translateASCIIsvg = true; // false to preserve agraph.., \begin{graph}..
51var avoidinnerHTML = false; // set true if assigning to innerHTML gives error
52var displaystyle = true; // puts limits above and below large operators
53var showasciiformulaonhover = true; // helps students learn ASCIIMath
54var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!
55var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
56var AMdocumentId = "wikitext" // PmWiki element containing math (default=body)
57var checkforprocessasciimathinmoodle = false; // true for systems like Moodle
58var dsvglocation = ""; // path to d.svg (blank if same as ASCIIMathML.js loc)
60/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
62var isIE = document.createElementNS==null;
63var noMathML = false, translated = false;
65if (isIE) { // avoid adding MathPlayer info explicitly to each webpage
66 document.write("<object id=\"mathplayer\"\
67 classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
68 document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
71// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)
72function setStylesheet(s) {
73 var id = "AMMLcustomStyleSheet";
74 var n = document.getElementById(id);
75 if(document.createStyleSheet) {
76 // Test for IE's non-standard createStyleSheet method
78 n.parentNode.removeChild(n);
79 // This failed without the
80 document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd"," <style id='" + id + "'>" + s + "</style>");
83 n.replaceChild(document.createTextNode(s),n.firstChild);
85 n = document.createElement("style");
88 n.appendChild(document.createTextNode(s));
89 document.getElementsByTagName("head")[0].appendChild(n);
94setStylesheet("#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\}");
97 var msg, warnings = new Array();
98 if (document.getElementById==null){
99 alert("This webpage requires a recent browser such as Mozilla Firefox/Netscape 7+ or Internet Explorer 6+ with MathPlayer and Adobe SVGviewer");
102 if (checkForMathML && (msg = checkMathML())) warnings.push(msg);
103 if (checkIfSVGavailable && (msg = checkSVG())) warnings.push(msg);
104 if (warnings.length>0) displayWarnings(warnings);
105 if (!noMathML) initSymbols();
109function checkMathML(){
110 if (navigator.appName.slice(0,8)=="Netscape")
111 if (navigator.appVersion.slice(0,1)>="5") noMathML = null;
112 else noMathML = true;
113 else if (navigator.appName.slice(0,9)=="Microsoft")
115 var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
120 else noMathML = true;
121//noMathML = true; //uncomment to check
122 if (noMathML && notifyIfNoMathML) {
123 var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.";
130function hideWarning(){
131 var body = document.getElementsByTagName("body")[0];
132 body.removeChild(document.getElementById('AMMLwarningBox'));
136function displayWarnings(warnings) {
137 var i, frag, nd = createElementXHTML("div");
138 var body = document.getElementsByTagName("body")[0];
139 body.onclick=hideWarning;
140 nd.id = 'AMMLwarningBox';
141 for (i=0; i<warnings.length; i++) {
142 frag = createElementXHTML("div");
143 frag.appendChild(document.createTextNode(warnings[i]));
144 frag.style.paddingBottom = "1.0em";
145 nd.appendChild(frag);
147 nd.appendChild(createElementXHTML("p"));
148 nd.appendChild(document.createTextNode("For instructions see the "));
149 var an = createElementXHTML("a");
150 an.appendChild(document.createTextNode("ASCIIMathML"));
151 an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");
153 nd.appendChild(document.createTextNode(" homepage"));
154 an = createElementXHTML("div");
155 an.id = 'AMMLcloseDiv';
156 an.appendChild(document.createTextNode('(click anywhere to close this warning)'));
158 var body = document.getElementsByTagName("body")[0];
159 body.insertBefore(nd,body.childNodes[0]);
162function translate(spanclassAM) {
163 if (!translated) { // run this only once
165 var body = document.getElementsByTagName("body")[0];
166 var processN = document.getElementById(AMdocumentId);
167 if (translateLaTeX) LMprocessNode((processN!=null?processN:body));
168 if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);
172function createElementXHTML(t) {
173 if (isIE) return document.createElement(t);
174 else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
177function createMmlNode(t,frag) {
178 if (isIE) var node = document.createElement("m:"+t);
179 else var node = document.createElementNS("http://www.w3.org/1998/Math/MathML",t);
180 if (frag) node.appendChild(frag);
184// character lists for Mozilla/Netscape fonts
185var 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];
186var 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];
187var 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];
189var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
190 RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
191 LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13,
192 MATRIX = 14;; // token types
194var AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};
198{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},
199{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},
200{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},
201{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},
202{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},
203{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},
204{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},
205{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},
206{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},
207{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},
208{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},
209{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},
210{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
211{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
212{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},
213{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},
214{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},
215{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},
216{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},
217{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},
218{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},
219{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},
220{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},
221{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},
222{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},
223{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},
224{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},
225{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},
226{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},
227{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},
228{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},
229{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},
230{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},
231{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},
232{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},
233{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},
235//binary operation symbols
236//{input:"-", tag:"mo", output:"\u0096", tex:null, ttype:CONST},
237{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},
238{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},
239{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},
240{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},
241{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},
242{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},
243{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},
244{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},
245{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},
246{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},
247{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},
248{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},
249{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},
250{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},
251{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},
252{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},
253{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},
254{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},
255{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},
256{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},
257{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},
259//binary relation symbols
260{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},
261{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},
262{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},
263{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},
264{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},
265{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},
266{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},
267{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},
268{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},
269{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},
270{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},
271{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},
272{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},
273{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},
274{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},
275{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},
276{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},
277{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},
278{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},
279{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},
280{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},
281{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},
284{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},
285{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},
286{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},
287{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},
288{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},
289{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},
290{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},
291{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},
292{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},
293{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},
294{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},
295{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},
298{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},
299{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},
300{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},
301{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},
302{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},
303{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},
304{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},
305//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
306{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},
307{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},
308{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},
309{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},
310{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},
311{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},
313//miscellaneous symbols
314{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},
315{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},
316{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},
317{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},
318{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},
319{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},
320{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},
321{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},
322{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},
323{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},
324{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},
325{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},
326{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},
327{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},
328{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},
329{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},
330{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},
331{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},
332{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},
333{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},
334{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},
335{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},
336{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},
337{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},
338{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},
339{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},
340{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},
341{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},
342{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},
343{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},
344{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},
345{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},
346{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},
347{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},
350{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},
351{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},
352{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},
353{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},
354{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},
355{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},
356{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},
357{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},
358{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},
359{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},
360{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},
361{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},
362{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},
363{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},
364{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},
365{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},
366{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},
367{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},
368{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},
369{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},
370{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},
371{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},
374{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},
375{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},
376{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},
377{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},
378{input:">->", tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST},
379{input:"->>", tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST},
380{input:">->>", tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST},
381{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},
382{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},
383{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},
384{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},
385{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},
386{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},
387//commands with argument
388{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},
389{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},
390{input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},
391{input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},
392{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
393{input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},
394{input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},
395{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},
396{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},
397{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},
398{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},
399{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},
400{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},
401{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},
402{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},
404{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},
405{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},
406{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},
407{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},
408{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},
409{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},
410{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},
411{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},
412{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},
413{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},
414{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},
415{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}
418function compareNames(s1,s2) {
419 if (s1.input > s2.input) return 1
423var AMnames = []; //list of input symbols
425function initSymbols() {
426 var texsymbols = [], i;
427 for (i=0; i<AMsymbols.length; i++)
428 if (AMsymbols[i].tex)
429 texsymbols[texsymbols.length] = {input:AMsymbols[i].tex,
430 tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};
431 AMsymbols = AMsymbols.concat(texsymbols);
435function refreshSymbols(){
437 AMsymbols.sort(compareNames);
438 for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
439 LMsymbols.sort(compareNames);
440 for (i=0; i<LMsymbols.length; i++) LMnames[i] = LMsymbols[i].input;
443function define(oldstr,newstr) {
444 if(oldstr.substr(0,1)=="\\")
445 LMsymbols = LMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,
448 AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,
449 tex:null, ttype:DEFINITION}]);
450 refreshSymbols(); // this may be a problem if many symbols are defined!
453function AMremoveCharsAndBlanks(str,n) {
454//remove n characters and any following blanks
456 if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ")
458 else st = str.slice(n);
459 for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
463function position(arr, str, n) {
464// return position >=n where str appears or would be inserted
465// assumes arr is sorted
472 if (arr[m]<str) n = m; else h = m;
476 for (var i=n; i<arr.length && arr[i]<str; i++);
477 return i; // i=arr.length || arr[i]>=str
480function AMgetSymbol(str) {
481//return maximal initial substring of str that appears in names
482//return null if there is none
490 for (var i=1; i<=str.length && more; i++) {
491 st = str.slice(0,i); //initial substring of length i
493 k = position(AMnames, st, j);
494 if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
499 more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
501 AMpreviousSymbol=AMcurrentSymbol;
503 AMcurrentSymbol=AMsymbols[mk].ttype;
504 return AMsymbols[mk];
506// if str[0] is a digit or - return maxsubstring of digits.digits
507 AMcurrentSymbol=CONST;
511 while ("0"<=st && st<="9" && k<=str.length) {
512 st = str.slice(k,k+1);
515 if (st == decimalsign) {
516 st = str.slice(k,k+1);
517 if ("0"<=st && st<="9") {
520 while ("0"<=st && st<="9" && k<=str.length) {
521 st = str.slice(k,k+1);
526 if ((integ && k>1) || k>2) {
527 st = str.slice(0,k-1);
531 st = str.slice(0,1); //take 1 character
532 tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
534 if (st=="-" && AMpreviousSymbol==INFIX) {
535 AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse
536 return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
538 return {input:st, tag:tagst, output:st, ttype:CONST};
541function AMremoveBrackets(node) {
543 if (node.nodeName=="mrow") {
544 st = node.firstChild.firstChild.nodeValue;
545 if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);
547 if (node.nodeName=="mrow") {
548 st = node.lastChild.firstChild.nodeValue;
549 if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);
553/*Parsing ASCII math expressions with the following grammar
554v ::= [A-Za-z] | greek letters | numbers | other constant symbols
555u ::= sqrt | text | bb | other unary symbols for font commands
556b ::= frac | root | stackrel binary symbols
557l ::= ( | [ | { | (: | {: left brackets
558r ::= ) | ] | } | :) | :} right brackets
559S ::= v | lEr | uS | bSS Simple expression
560I ::= S_S | S^S | S_S^S | S Intermediate expression
561E ::= IE | I/I Expression
562Each terminal symbol is translated into a corresponding mathml node.*/
564var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;
566function AMparseSexpr(str) { //parses str and returns [node,tailstr]
567 var symbol, node, result, i, st,// rightvert = false,
568 newFrag = document.createDocumentFragment();
569 str = AMremoveCharsAndBlanks(str,0);
570 symbol = AMgetSymbol(str); //either a token or a bracket or empty
571 if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {
574 if (symbol.ttype == DEFINITION) {
575 str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);
576 symbol = AMgetSymbol(str);
578 switch (symbol.ttype) { case UNDEROVER:
580 str = AMremoveCharsAndBlanks(str,symbol.input.length);
581 return [createMmlNode(symbol.tag, //its a constant
582 document.createTextNode(symbol.output)),str];
583 case LEFTBRACKET: //read (expr+)
585 str = AMremoveCharsAndBlanks(str,symbol.input.length);
586 result = AMparseExpr(str,true);
588 if (typeof symbol.invisible == "boolean" && symbol.invisible)
589 node = createMmlNode("mrow",result[0]);
591 node = createMmlNode("mo",document.createTextNode(symbol.output));
592 node = createMmlNode("mrow",node);
593 node.appendChild(result[0]);
595 return [node,result[1]];
597 if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);
598 if (str.charAt(0)=="{") i=str.indexOf("}");
599 else if (str.charAt(0)=="(") i=str.indexOf(")");
600 else if (str.charAt(0)=="[") i=str.indexOf("]");
601 else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;
603 if (i==-1) i = str.length;
605 if (st.charAt(0) == " ") {
606 node = createMmlNode("mspace");
607 node.setAttribute("width","1ex");
608 newFrag.appendChild(node);
611 createMmlNode(symbol.tag,document.createTextNode(st)));
612 if (st.charAt(st.length-1) == " ") {
613 node = createMmlNode("mspace");
614 node.setAttribute("width","1ex");
615 newFrag.appendChild(node);
617 str = AMremoveCharsAndBlanks(str,i+1);
618 return [createMmlNode("mrow",newFrag),str];
620 str = AMremoveCharsAndBlanks(str,symbol.input.length);
621 result = AMparseSexpr(str);
622 if (result[0]==null) return [createMmlNode(symbol.tag,
623 document.createTextNode(symbol.output)),str];
624 if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
626 if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {
627 return [createMmlNode(symbol.tag,
628 document.createTextNode(symbol.output)),str];
630 node = createMmlNode("mrow",
631 createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
632 node.appendChild(result[0]);
633 return [node,result[1]];
636 AMremoveBrackets(result[0]);
637 if (symbol.input == "sqrt") { // sqrt
638 return [createMmlNode(symbol.tag,result[0]),result[1]];
639 } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent
640 node = createMmlNode(symbol.tag,result[0]);
641 node.appendChild(createMmlNode("mo",document.createTextNode(symbol.output)));
642 return [node,result[1]];
643 } else { // font change command
644 if (!isIE && typeof symbol.codes != "undefined") {
645 for (i=0; i<result[0].childNodes.length; i++)
646 if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
647 st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
648 result[0].childNodes[i].firstChild.nodeValue);
650 for (var j=0; j<st.length; j++)
651 if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +
652 String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);
653 else newst = newst + st.charAt(j);
654 if (result[0].nodeName=="mi")
655 result[0]=createMmlNode("mo").
656 appendChild(document.createTextNode(newst));
657 else result[0].replaceChild(createMmlNode("mo").
658 appendChild(document.createTextNode(newst)),
659 result[0].childNodes[i]);
662 node = createMmlNode(symbol.tag,result[0]);
663 node.setAttribute(symbol.atname,symbol.atval);
664 return [node,result[1]];
667 str = AMremoveCharsAndBlanks(str,symbol.input.length);
668 result = AMparseSexpr(str);
669 if (result[0]==null) return [createMmlNode("mo",
670 document.createTextNode(symbol.input)),str];
671 AMremoveBrackets(result[0]);
672 var result2 = AMparseSexpr(result[1]);
673 if (result2[0]==null) return [createMmlNode("mo",
674 document.createTextNode(symbol.input)),str];
675 AMremoveBrackets(result2[0]);
676 if (symbol.input=="root" || symbol.input=="stackrel")
677 newFrag.appendChild(result2[0]);
678 newFrag.appendChild(result[0]);
679 if (symbol.input=="frac") newFrag.appendChild(result2[0]);
680 return [createMmlNode(symbol.tag,newFrag),result2[1]];
682 str = AMremoveCharsAndBlanks(str,symbol.input.length);
683 return [createMmlNode("mo",document.createTextNode(symbol.output)),str];
685 str = AMremoveCharsAndBlanks(str,symbol.input.length);
686 node = createMmlNode("mspace");
687 node.setAttribute("width","1ex");
688 newFrag.appendChild(node);
690 createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
691 node = createMmlNode("mspace");
692 node.setAttribute("width","1ex");
693 newFrag.appendChild(node);
694 return [createMmlNode("mrow",newFrag),str];
696// if (rightvert) return [null,str]; else rightvert = true;
698 str = AMremoveCharsAndBlanks(str,symbol.input.length);
699 result = AMparseExpr(str,false);
702 if (result[0].lastChild!=null)
703 st = result[0].lastChild.firstChild.nodeValue;
704 if (st == "|") { // its an absolute value subterm
705 node = createMmlNode("mo",document.createTextNode(symbol.output));
706 node = createMmlNode("mrow",node);
707 node.appendChild(result[0]);
708 return [node,result[1]];
709 } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing
710 node = createMmlNode("mo",document.createTextNode("\u2223"));
711 node = createMmlNode("mrow",node);
716 str = AMremoveCharsAndBlanks(str,symbol.input.length);
717 return [createMmlNode(symbol.tag, //its a constant
718 document.createTextNode(symbol.output)),str];
722function AMparseIexpr(str) {
723 var symbol, sym1, sym2, node, result, underover;
724 str = AMremoveCharsAndBlanks(str,0);
725 sym1 = AMgetSymbol(str);
726 result = AMparseSexpr(str);
729 symbol = AMgetSymbol(str);
730 if (symbol.ttype == INFIX && symbol.input != "/") {
731 str = AMremoveCharsAndBlanks(str,symbol.input.length);
732// if (symbol.input == "/") result = AMparseIexpr(str); else ...
733 result = AMparseSexpr(str);
734 if (result[0] == null) // show box in place of missing argument
735 result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
736 else AMremoveBrackets(result[0]);
738// if (symbol.input == "/") AMremoveBrackets(node);
739 if (symbol.input == "_") {
740 sym2 = AMgetSymbol(str);
741 underover = (sym1.ttype == UNDEROVER);
742 if (sym2.input == "^") {
743 str = AMremoveCharsAndBlanks(str,sym2.input.length);
744 var res2 = AMparseSexpr(str);
745 AMremoveBrackets(res2[0]);
747 node = createMmlNode((underover?"munderover":"msubsup"),node);
748 node.appendChild(result[0]);
749 node.appendChild(res2[0]);
750 node = createMmlNode("mrow",node); // so sum does not stretch
752 node = createMmlNode((underover?"munder":"msub"),node);
753 node.appendChild(result[0]);
756 node = createMmlNode(symbol.tag,node);
757 node.appendChild(result[0]);
763function AMparseExpr(str,rightbracket) {
764 var symbol, node, result, i, nodeList = [],
765 newFrag = document.createDocumentFragment();
767 str = AMremoveCharsAndBlanks(str,0);
768 result = AMparseIexpr(str);
771 symbol = AMgetSymbol(str);
772 if (symbol.ttype == INFIX && symbol.input == "/") {
773 str = AMremoveCharsAndBlanks(str,symbol.input.length);
774 result = AMparseIexpr(str);
775 if (result[0] == null) // show box in place of missing argument
776 result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
777 else AMremoveBrackets(result[0]);
779 AMremoveBrackets(node);
780 node = createMmlNode(symbol.tag,node);
781 node.appendChild(result[0]);
782 newFrag.appendChild(node);
783 symbol = AMgetSymbol(str);
785 else if (node!=undefined) newFrag.appendChild(node);
786 } while ((symbol.ttype != RIGHTBRACKET &&
787 (symbol.ttype != LEFTRIGHT || rightbracket)
788 || AMnestingDepth == 0) && symbol!=null && symbol.output!="");
789 if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {
790// if (AMnestingDepth > 0) AMnestingDepth--;
791 var len = newFrag.childNodes.length;
792 if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&
793 newFrag.childNodes[len-2].nodeName == "mo" &&
794 newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix
795 var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;
796 if (right==")" || right=="]") {
797 var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;
798 if (left=="(" && right==")" && symbol.output != "}" ||
799 left=="[" && right=="]") {
800 var pos = []; // positions of commas
802 var m = newFrag.childNodes.length;
803 for (i=0; matrix && i<m; i=i+2) {
805 node = newFrag.childNodes[i];
806 if (matrix) matrix = node.nodeName=="mrow" &&
807 (i==m-1 || node.nextSibling.nodeName=="mo" &&
808 node.nextSibling.firstChild.nodeValue==",")&&
809 node.firstChild.firstChild.nodeValue==left &&
810 node.lastChild.firstChild.nodeValue==right;
812 for (var j=0; j<node.childNodes.length; j++)
813 if (node.childNodes[j].firstChild.nodeValue==",")
814 pos[i][pos[i].length]=j;
815 if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;
818 var row, frag, n, k, table = document.createDocumentFragment();
819 for (i=0; i<m; i=i+2) {
820 row = document.createDocumentFragment();
821 frag = document.createDocumentFragment();
822 node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
823 n = node.childNodes.length;
825 node.removeChild(node.firstChild); //remove (
826 for (j=1; j<n-1; j++) {
827 if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
828 node.removeChild(node.firstChild); //remove ,
829 row.appendChild(createMmlNode("mtd",frag));
831 } else frag.appendChild(node.firstChild);
833 row.appendChild(createMmlNode("mtd",frag));
834 if (newFrag.childNodes.length>2) {
835 newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>
836 newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>
838 table.appendChild(createMmlNode("mtr",row));
840 node = createMmlNode("mtable",table);
841 if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");
842 newFrag.replaceChild(node,newFrag.firstChild);
847 str = AMremoveCharsAndBlanks(str,symbol.input.length);
848 if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
849 node = createMmlNode("mo",document.createTextNode(symbol.output));
850 newFrag.appendChild(node);
853 return [newFrag,str];
856function parseMath(str,latex) {
859 frag = latex ? LMparseExpr(str.replace(/^\s+/g,""),false,false)[0] : AMparseExpr(str.replace(/^\s+/g,""),false)[0];
860 node = createMmlNode("mstyle",frag);
861 node.setAttribute("mathcolor",mathcolor);
862 node.setAttribute("fontfamily",mathfontfamily);
863 node.setAttribute("mathsize",mathfontsize);
864 if (displaystyle) node.setAttribute("displaystyle","true");
865 node = createMmlNode("math",node);
866 if (showasciiformulaonhover) //fixed by djhsu so newline
867 node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
871function strarr2docFrag(arr, linebreaks, latex) {
872 var newFrag=document.createDocumentFragment();
874 for (var i=0; i<arr.length; i++) {
875 if (expr) newFrag.appendChild(parseMath(arr[i],latex));
877 var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
878 newFrag.appendChild(createElementXHTML("span").
879 appendChild(document.createTextNode(arri[0])));
880 for (var j=1; j<arri.length; j++) {
881 newFrag.appendChild(createElementXHTML("p"));
882 newFrag.appendChild(createElementXHTML("span").
883 appendChild(document.createTextNode(arri[j])));
891function AMautomathrec(str) {
892//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.
893//tokens are single letters (except a, A, I) and ASCIIMathML tokens
894 var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|";
895 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])|";
896 var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|";
897 var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out
898 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?
899 var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|";
900 var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken;
901 var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g");
902 str = str.replace(re," `$2`$7");
903 var arr = str.split(AMdelimiter1);
904 var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g");
905 var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now
906 for (i=0; i<arr.length; i++) //single nonenglish tokens
908 arr[i] = arr[i].replace(re1," `$2`$3");
909 arr[i] = arr[i].replace(re2," `$2`$3");
910 arr[i] = arr[i].replace(/([{}[\]])/,"`$1`");
912 str = arr.join(AMdelimiter1);
913 str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)"); //fix parentheses
914 str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3"); //fix parentheses
915 str = str.replace(/\sin`/g,"` in");
916 str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`");
917 str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2");
918 str = str.replace(/`([0-9.]+:)`/g,"$1");
922function processNodeR(n, linebreaks,latex) {
923 var mtch, str, arr, frg, i;
924 if (n.childNodes.length == 0) {
925 if ((n.nodeType!=8 || linebreaks) &&
926 n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
927 n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /*&&
928 n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"*/) {
930 if (!(str == null)) {
931 str = str.replace(/\r\n\r\n/g,"\n\n");
932 str = str.replace(/\x20+/g," ");
933 str = str.replace(/\s*\r\n/g," ");
936 mtch = (str.indexOf("\$")==-1 ? false : true);
937 str = str.replace(/([^\\])\$/g,"$1 \$");
938 str = str.replace(/^\$/," \$"); // in case \$ at start of string
939 arr = str.split(" \$");
940 for (i=0; i<arr.length; i++)
941 arr[i]=arr[i].replace(/\\\$/g,"\$");
944 str = str.replace(new RegExp(AMescape1, "g"),
945 function(){mtch = true; return "AMescape1"});
946 str = str.replace(/\\?end{?a?math}?/i,
947 function(){automathrecognize = false; mtch = true; return ""});
948 str = str.replace(/amath\b|\\begin{a?math}/i,
949 function(){automathrecognize = true; mtch = true; return ""});
950 arr = str.split(AMdelimiter1);
951 if (automathrecognize)
952 for (i=0; i<arr.length; i++)
953 if (i%2==0) arr[i] = AMautomathrec(arr[i]);
954 str = arr.join(AMdelimiter1);
955 arr = str.split(AMdelimiter1);
956 for (i=0; i<arr.length; i++) // this is a problem ************
957 arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);
959 if (arr.length>1 || mtch) {
961 frg = strarr2docFrag(arr,n.nodeType==8,latex);
962 var len = frg.childNodes.length;
963 n.parentNode.replaceChild(frg,n);
969 } else if (n.nodeName!="math") {
970 for (i=0; i<n.childNodes.length; i++)
971 i += processNodeR(n.childNodes[i], linebreaks,latex);
976function AMprocessNode(n, linebreaks, spanclassAM) {
978 if (spanclassAM!=null) {
979 frag = document.getElementsByTagName("span")
980 for (var i=0;i<frag.length;i++)
981 if (frag[i].className == "AM")
982 processNodeR(frag[i],linebreaks,false);
985 st = n.innerHTML; // look for AMdelimiter on page
988 if (st==null || /amath\b|\\begin{a?math}/i.test(st) ||
989 st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 ||
990 st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) {
991 processNodeR(n,linebreaks,false);
994/* if (isIE) { //needed to match size and font of formula to surrounding text
995 frag = document.getElementsByTagName('math');
996 for (var i=0;i<frag.length;i++) frag[i].update() //What is this?
1004Version 1.1, July 20, 2007 (c) modifications by Peter Jipsen
1006(changes: renamed global variables from AM... to LM... so that
1007LaTeXMathML and ASCIIMathML can be used simultaneously)
1009Previous header notice:
1010This file (Version 1.0), is due to Douglas Woodall, June 2006.
1011It contains JavaScript functions to convert (most simple) LaTeX
1012math notation to Presentation MathML. It was obtained by
1013downloading the file ASCIIMathML.js from
1014 http://www1.chapman.edu/~jipsen/mathml/asciimathdownload/
1015and modifying it so that it carries out ONLY those conversions
1016that would be carried out in LaTeX. A description of the original
1017file, with examples, can be found at
1018 www1.chapman.edu/~jipsen/mathml/asciimath.html
1019 ASCIIMathML: Math on the web for everyone
1021Here is the header notice from the original file:
1025This file contains JavaScript functions to convert ASCII math notation
1026to Presentation MathML. The conversion is done while the (X)HTML page
1027loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet
1028Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/).
1029Just add the next line to your (X)HTML page with this file in the same folder:
1030<script type="text/javascript" src="ASCIIMathML.js"></script>
1031This is a convenient and inexpensive solution for authoring MathML.
1033Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen
1034Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js
1035For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt
1036If you use it on a webpage, please send the URL to jipsen@chapman.edu
1038This program is free software; you can redistribute it and/or modify
1039it under the terms of the GNU Lesser General Public License as published by
1040the Free Software Foundation; either version 2.1 of the License, or (at
1041your option) any later version.
1043This program is distributed in the hope that it will be useful,
1044but WITHOUT ANY WARRANTY; without even the implied warranty of
1045MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
1046General Public License (at http://www.gnu.org/license/lgpl.html)
1052Content between $...$ and $$...$$ is converted by this part of the file
1055// all further global variables start with "LM"
1057// Commented out by DRW to prevent 1/2 turning into a 2-line fraction
1058// LMdiv = {input:"/", tag:"mfrac", output:"/", ttype:INFIX},
1059// Commented out by DRW so that " prints literally in equations
1060// LMquote = {input:"\"", tag:"mtext", output:"mbox", ttype:TEXT};
1064{input:"\\alpha", tag:"mi", output:"\u03B1", ttype:CONST},
1065{input:"\\beta", tag:"mi", output:"\u03B2", ttype:CONST},
1066{input:"\\gamma", tag:"mi", output:"\u03B3", ttype:CONST},
1067{input:"\\delta", tag:"mi", output:"\u03B4", ttype:CONST},
1068{input:"\\epsilon", tag:"mi", output:"\u03B5", ttype:CONST},
1069{input:"\\varepsilon", tag:"mi", output:"\u025B", ttype:CONST},
1070{input:"\\zeta", tag:"mi", output:"\u03B6", ttype:CONST},
1071{input:"\\eta", tag:"mi", output:"\u03B7", ttype:CONST},
1072{input:"\\theta", tag:"mi", output:"\u03B8", ttype:CONST},
1073{input:"\\vartheta", tag:"mi", output:"\u03D1", ttype:CONST},
1074{input:"\\iota", tag:"mi", output:"\u03B9", ttype:CONST},
1075{input:"\\kappa", tag:"mi", output:"\u03BA", ttype:CONST},
1076{input:"\\lambda", tag:"mi", output:"\u03BB", ttype:CONST},
1077{input:"\\mu", tag:"mi", output:"\u03BC", ttype:CONST},
1078{input:"\\nu", tag:"mi", output:"\u03BD", ttype:CONST},
1079{input:"\\xi", tag:"mi", output:"\u03BE", ttype:CONST},
1080{input:"\\pi", tag:"mi", output:"\u03C0", ttype:CONST},
1081{input:"\\varpi", tag:"mi", output:"\u03D6", ttype:CONST},
1082{input:"\\rho", tag:"mi", output:"\u03C1", ttype:CONST},
1083{input:"\\varrho", tag:"mi", output:"\u03F1", ttype:CONST},
1084{input:"\\varsigma", tag:"mi", output:"\u03C2", ttype:CONST},
1085{input:"\\sigma", tag:"mi", output:"\u03C3", ttype:CONST},
1086{input:"\\tau", tag:"mi", output:"\u03C4", ttype:CONST},
1087{input:"\\upsilon", tag:"mi", output:"\u03C5", ttype:CONST},
1088{input:"\\phi", tag:"mi", output:"\u03C6", ttype:CONST},
1089{input:"\\varphi", tag:"mi", output:"\u03D5", ttype:CONST},
1090{input:"\\chi", tag:"mi", output:"\u03C7", ttype:CONST},
1091{input:"\\psi", tag:"mi", output:"\u03C8", ttype:CONST},
1092{input:"\\omega", tag:"mi", output:"\u03C9", ttype:CONST},
1093{input:"\\Gamma", tag:"mo", output:"\u0393", ttype:CONST},
1094{input:"\\Delta", tag:"mo", output:"\u0394", ttype:CONST},
1095{input:"\\Theta", tag:"mo", output:"\u0398", ttype:CONST},
1096{input:"\\Lambda", tag:"mo", output:"\u039B", ttype:CONST},
1097{input:"\\Xi", tag:"mo", output:"\u039E", ttype:CONST},
1098{input:"\\Pi", tag:"mo", output:"\u03A0", ttype:CONST},
1099{input:"\\Sigma", tag:"mo", output:"\u03A3", ttype:CONST},
1100{input:"\\Upsilon", tag:"mo", output:"\u03A5", ttype:CONST},
1101{input:"\\Phi", tag:"mo", output:"\u03A6", ttype:CONST},
1102{input:"\\Psi", tag:"mo", output:"\u03A8", ttype:CONST},
1103{input:"\\Omega", tag:"mo", output:"\u03A9", ttype:CONST},
1106{input:"\\frac12", tag:"mo", output:"\u00BD", ttype:CONST},
1107{input:"\\frac14", tag:"mo", output:"\u00BC", ttype:CONST},
1108{input:"\\frac34", tag:"mo", output:"\u00BE", ttype:CONST},
1109{input:"\\frac13", tag:"mo", output:"\u2153", ttype:CONST},
1110{input:"\\frac23", tag:"mo", output:"\u2154", ttype:CONST},
1111{input:"\\frac15", tag:"mo", output:"\u2155", ttype:CONST},
1112{input:"\\frac25", tag:"mo", output:"\u2156", ttype:CONST},
1113{input:"\\frac35", tag:"mo", output:"\u2157", ttype:CONST},
1114{input:"\\frac45", tag:"mo", output:"\u2158", ttype:CONST},
1115{input:"\\frac16", tag:"mo", output:"\u2159", ttype:CONST},
1116{input:"\\frac56", tag:"mo", output:"\u215A", ttype:CONST},
1117{input:"\\frac18", tag:"mo", output:"\u215B", ttype:CONST},
1118{input:"\\frac38", tag:"mo", output:"\u215C", ttype:CONST},
1119{input:"\\frac58", tag:"mo", output:"\u215D", ttype:CONST},
1120{input:"\\frac78", tag:"mo", output:"\u215E", ttype:CONST},
1122//binary operation symbols
1123{input:"\\pm", tag:"mo", output:"\u00B1", ttype:CONST},
1124{input:"\\mp", tag:"mo", output:"\u2213", ttype:CONST},
1125{input:"\\triangleleft",tag:"mo", output:"\u22B2", ttype:CONST},
1126{input:"\\triangleright",tag:"mo",output:"\u22B3", ttype:CONST},
1127{input:"\\cdot", tag:"mo", output:"\u22C5", ttype:CONST},
1128{input:"\\star", tag:"mo", output:"\u22C6", ttype:CONST},
1129{input:"\\ast", tag:"mo", output:"\u002A", ttype:CONST},
1130{input:"\\times", tag:"mo", output:"\u00D7", ttype:CONST},
1131{input:"\\div", tag:"mo", output:"\u00F7", ttype:CONST},
1132{input:"\\circ", tag:"mo", output:"\u2218", ttype:CONST},
1133//{input:"\\bullet", tag:"mo", output:"\u2219", ttype:CONST},
1134{input:"\\bullet", tag:"mo", output:"\u2022", ttype:CONST},
1135{input:"\\oplus", tag:"mo", output:"\u2295", ttype:CONST},
1136{input:"\\ominus", tag:"mo", output:"\u2296", ttype:CONST},
1137{input:"\\otimes", tag:"mo", output:"\u2297", ttype:CONST},
1138{input:"\\bigcirc", tag:"mo", output:"\u25CB", ttype:CONST},
1139{input:"\\oslash", tag:"mo", output:"\u2298", ttype:CONST},
1140{input:"\\odot", tag:"mo", output:"\u2299", ttype:CONST},
1141{input:"\\land", tag:"mo", output:"\u2227", ttype:CONST},
1142{input:"\\wedge", tag:"mo", output:"\u2227", ttype:CONST},
1143{input:"\\lor", tag:"mo", output:"\u2228", ttype:CONST},
1144{input:"\\vee", tag:"mo", output:"\u2228", ttype:CONST},
1145{input:"\\cap", tag:"mo", output:"\u2229", ttype:CONST},
1146{input:"\\cup", tag:"mo", output:"\u222A", ttype:CONST},
1147{input:"\\sqcap", tag:"mo", output:"\u2293", ttype:CONST},
1148{input:"\\sqcup", tag:"mo", output:"\u2294", ttype:CONST},
1149{input:"\\uplus", tag:"mo", output:"\u228E", ttype:CONST},
1150{input:"\\amalg", tag:"mo", output:"\u2210", ttype:CONST},
1151{input:"\\bigtriangleup",tag:"mo",output:"\u25B3", ttype:CONST},
1152{input:"\\bigtriangledown",tag:"mo",output:"\u25BD", ttype:CONST},
1153{input:"\\dag", tag:"mo", output:"\u2020", ttype:CONST},
1154{input:"\\dagger", tag:"mo", output:"\u2020", ttype:CONST},
1155{input:"\\ddag", tag:"mo", output:"\u2021", ttype:CONST},
1156{input:"\\ddagger", tag:"mo", output:"\u2021", ttype:CONST},
1157{input:"\\lhd", tag:"mo", output:"\u22B2", ttype:CONST},
1158{input:"\\rhd", tag:"mo", output:"\u22B3", ttype:CONST},
1159{input:"\\unlhd", tag:"mo", output:"\u22B4", ttype:CONST},
1160{input:"\\unrhd", tag:"mo", output:"\u22B5", ttype:CONST},
1164{input:"\\sum", tag:"mo", output:"\u2211", ttype:UNDEROVER},
1165{input:"\\prod", tag:"mo", output:"\u220F", ttype:UNDEROVER},
1166{input:"\\bigcap", tag:"mo", output:"\u22C2", ttype:UNDEROVER},
1167{input:"\\bigcup", tag:"mo", output:"\u22C3", ttype:UNDEROVER},
1168{input:"\\bigwedge", tag:"mo", output:"\u22C0", ttype:UNDEROVER},
1169{input:"\\bigvee", tag:"mo", output:"\u22C1", ttype:UNDEROVER},
1170{input:"\\bigsqcap", tag:"mo", output:"\u2A05", ttype:UNDEROVER},
1171{input:"\\bigsqcup", tag:"mo", output:"\u2A06", ttype:UNDEROVER},
1172{input:"\\coprod", tag:"mo", output:"\u2210", ttype:UNDEROVER},
1173{input:"\\bigoplus", tag:"mo", output:"\u2A01", ttype:UNDEROVER},
1174{input:"\\bigotimes", tag:"mo", output:"\u2A02", ttype:UNDEROVER},
1175{input:"\\bigodot", tag:"mo", output:"\u2A00", ttype:UNDEROVER},
1176{input:"\\biguplus", tag:"mo", output:"\u2A04", ttype:UNDEROVER},
1177{input:"\\int", tag:"mo", output:"\u222B", ttype:CONST},
1178{input:"\\oint", tag:"mo", output:"\u222E", ttype:CONST},
1180//binary relation symbols
1181{input:":=", tag:"mo", output:":=", ttype:CONST},
1182{input:"\\lt", tag:"mo", output:"<", ttype:CONST},
1183{input:"\\gt", tag:"mo", output:">", ttype:CONST},
1184{input:"\\ne", tag:"mo", output:"\u2260", ttype:CONST},
1185{input:"\\neq", tag:"mo", output:"\u2260", ttype:CONST},
1186{input:"\\le", tag:"mo", output:"\u2264", ttype:CONST},
1187{input:"\\leq", tag:"mo", output:"\u2264", ttype:CONST},
1188{input:"\\leqslant", tag:"mo", output:"\u2264", ttype:CONST},
1189{input:"\\ge", tag:"mo", output:"\u2265", ttype:CONST},
1190{input:"\\geq", tag:"mo", output:"\u2265", ttype:CONST},
1191{input:"\\geqslant", tag:"mo", output:"\u2265", ttype:CONST},
1192{input:"\\equiv", tag:"mo", output:"\u2261", ttype:CONST},
1193{input:"\\ll", tag:"mo", output:"\u226A", ttype:CONST},
1194{input:"\\gg", tag:"mo", output:"\u226B", ttype:CONST},
1195{input:"\\doteq", tag:"mo", output:"\u2250", ttype:CONST},
1196{input:"\\prec", tag:"mo", output:"\u227A", ttype:CONST},
1197{input:"\\succ", tag:"mo", output:"\u227B", ttype:CONST},
1198{input:"\\preceq", tag:"mo", output:"\u227C", ttype:CONST},
1199{input:"\\succeq", tag:"mo", output:"\u227D", ttype:CONST},
1200{input:"\\subset", tag:"mo", output:"\u2282", ttype:CONST},
1201{input:"\\supset", tag:"mo", output:"\u2283", ttype:CONST},
1202{input:"\\subseteq", tag:"mo", output:"\u2286", ttype:CONST},
1203{input:"\\supseteq", tag:"mo", output:"\u2287", ttype:CONST},
1204{input:"\\sqsubset", tag:"mo", output:"\u228F", ttype:CONST},
1205{input:"\\sqsupset", tag:"mo", output:"\u2290", ttype:CONST},
1206{input:"\\sqsubseteq", tag:"mo", output:"\u2291", ttype:CONST},
1207{input:"\\sqsupseteq", tag:"mo", output:"\u2292", ttype:CONST},
1208{input:"\\sim", tag:"mo", output:"\u223C", ttype:CONST},
1209{input:"\\simeq", tag:"mo", output:"\u2243", ttype:CONST},
1210{input:"\\approx", tag:"mo", output:"\u2248", ttype:CONST},
1211{input:"\\cong", tag:"mo", output:"\u2245", ttype:CONST},
1212{input:"\\Join", tag:"mo", output:"\u22C8", ttype:CONST},
1213{input:"\\bowtie", tag:"mo", output:"\u22C8", ttype:CONST},
1214{input:"\\in", tag:"mo", output:"\u2208", ttype:CONST},
1215{input:"\\ni", tag:"mo", output:"\u220B", ttype:CONST},
1216{input:"\\owns", tag:"mo", output:"\u220B", ttype:CONST},
1217{input:"\\propto", tag:"mo", output:"\u221D", ttype:CONST},
1218{input:"\\vdash", tag:"mo", output:"\u22A2", ttype:CONST},
1219{input:"\\dashv", tag:"mo", output:"\u22A3", ttype:CONST},
1220{input:"\\models", tag:"mo", output:"\u22A8", ttype:CONST},
1221{input:"\\perp", tag:"mo", output:"\u22A5", ttype:CONST},
1222{input:"\\smile", tag:"mo", output:"\u2323", ttype:CONST},
1223{input:"\\frown", tag:"mo", output:"\u2322", ttype:CONST},
1224{input:"\\asymp", tag:"mo", output:"\u224D", ttype:CONST},
1225{input:"\\notin", tag:"mo", output:"\u2209", ttype:CONST},
1228{input:"\\begin{eqnarray}", output:"X", ttype:MATRIX, invisible:true},
1229{input:"\\begin{array}", output:"X", ttype:MATRIX, invisible:true},
1230{input:"\\\\", output:"}&{", ttype:DEFINITION},
1231{input:"\\end{eqnarray}", output:"}}", ttype:DEFINITION},
1232{input:"\\end{array}", output:"}}", ttype:DEFINITION},
1234//grouping and literal brackets -- ieval is for IE
1235{input:"\\big", tag:"mo", output:"X", atval:"1.2", ieval:"2.2", ttype:BIG},
1236{input:"\\Big", tag:"mo", output:"X", atval:"1.6", ieval:"2.6", ttype:BIG},
1237{input:"\\bigg", tag:"mo", output:"X", atval:"2.2", ieval:"3.2", ttype:BIG},
1238{input:"\\Bigg", tag:"mo", output:"X", atval:"2.9", ieval:"3.9", ttype:BIG},
1239{input:"\\left", tag:"mo", output:"X", ttype:LEFTBRACKET},
1240{input:"\\right", tag:"mo", output:"X", ttype:RIGHTBRACKET},
1241{input:"{", output:"{", ttype:LEFTBRACKET, invisible:true},
1242{input:"}", output:"}", ttype:RIGHTBRACKET, invisible:true},
1244{input:"(", tag:"mo", output:"(", atval:"1", ttype:STRETCHY},
1245{input:"[", tag:"mo", output:"[", atval:"1", ttype:STRETCHY},
1246{input:"\\lbrack", tag:"mo", output:"[", atval:"1", ttype:STRETCHY},
1247{input:"\\{", tag:"mo", output:"{", atval:"1", ttype:STRETCHY},
1248{input:"\\lbrace", tag:"mo", output:"{", atval:"1", ttype:STRETCHY},
1249{input:"\\langle", tag:"mo", output:"\u2329", atval:"1", ttype:STRETCHY},
1250{input:"\\lfloor", tag:"mo", output:"\u230A", atval:"1", ttype:STRETCHY},
1251{input:"\\lceil", tag:"mo", output:"\u2308", atval:"1", ttype:STRETCHY},
1253// rtag:"mi" causes space to be inserted before a following sin, cos, etc.
1254// (see function LMparseExpr() )
1255{input:")", tag:"mo",output:")", rtag:"mi",atval:"1",ttype:STRETCHY},
1256{input:"]", tag:"mo",output:"]", rtag:"mi",atval:"1",ttype:STRETCHY},
1257{input:"\\rbrack",tag:"mo",output:"]", rtag:"mi",atval:"1",ttype:STRETCHY},
1258{input:"\\}", tag:"mo",output:"}", rtag:"mi",atval:"1",ttype:STRETCHY},
1259{input:"\\rbrace",tag:"mo",output:"}", rtag:"mi",atval:"1",ttype:STRETCHY},
1260{input:"\\rangle",tag:"mo",output:"\u232A", rtag:"mi",atval:"1",ttype:STRETCHY},
1261{input:"\\rfloor",tag:"mo",output:"\u230B", rtag:"mi",atval:"1",ttype:STRETCHY},
1262{input:"\\rceil", tag:"mo",output:"\u2309", rtag:"mi",atval:"1",ttype:STRETCHY},
1264// "|", "\\|", "\\vert" and "\\Vert" modified later: lspace = rspace = 0em
1265{input:"|", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},
1266{input:"\\|", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},
1267{input:"\\vert", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},
1268{input:"\\Vert", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},
1269{input:"\\mid", tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},
1270{input:"\\parallel", tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},
1271{input:"/", tag:"mo", output:"/", atval:"1.01", ttype:STRETCHY},
1272{input:"\\backslash", tag:"mo", output:"\u2216", atval:"1", ttype:STRETCHY},
1273{input:"\\setminus", tag:"mo", output:"\\", ttype:CONST},
1275//miscellaneous symbols
1276{input:"\\!", tag:"mspace", atname:"width", atval:"-0.167em", ttype:SPACE},
1277{input:"\\,", tag:"mspace", atname:"width", atval:"0.167em", ttype:SPACE},
1278{input:"\\>", tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},
1279{input:"\\:", tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},
1280{input:"\\;", tag:"mspace", atname:"width", atval:"0.278em", ttype:SPACE},
1281{input:"~", tag:"mspace", atname:"width", atval:"0.333em", ttype:SPACE},
1282{input:"\\quad", tag:"mspace", atname:"width", atval:"1em", ttype:SPACE},
1283{input:"\\qquad", tag:"mspace", atname:"width", atval:"2em", ttype:SPACE},
1284//{input:"{}", tag:"mo", output:"\u200B", ttype:CONST}, // zero-width
1285{input:"\\prime", tag:"mo", output:"\u2032", ttype:CONST},
1286{input:"'", tag:"mo", output:"\u02B9", ttype:CONST},
1287{input:"''", tag:"mo", output:"\u02BA", ttype:CONST},
1288{input:"'''", tag:"mo", output:"\u2034", ttype:CONST},
1289{input:"''''", tag:"mo", output:"\u2057", ttype:CONST},
1290{input:"\\ldots", tag:"mo", output:"\u2026", ttype:CONST},
1291{input:"\\cdots", tag:"mo", output:"\u22EF", ttype:CONST},
1292{input:"\\vdots", tag:"mo", output:"\u22EE", ttype:CONST},
1293{input:"\\ddots", tag:"mo", output:"\u22F1", ttype:CONST},
1294{input:"\\forall", tag:"mo", output:"\u2200", ttype:CONST},
1295{input:"\\exists", tag:"mo", output:"\u2203", ttype:CONST},
1296{input:"\\Re", tag:"mo", output:"\u211C", ttype:CONST},
1297{input:"\\Im", tag:"mo", output:"\u2111", ttype:CONST},
1298{input:"\\aleph", tag:"mo", output:"\u2135", ttype:CONST},
1299{input:"\\hbar", tag:"mo", output:"\u210F", ttype:CONST},
1300{input:"\\ell", tag:"mo", output:"\u2113", ttype:CONST},
1301{input:"\\wp", tag:"mo", output:"\u2118", ttype:CONST},
1302{input:"\\emptyset", tag:"mo", output:"\u2205", ttype:CONST},
1303{input:"\\infty", tag:"mo", output:"\u221E", ttype:CONST},
1304{input:"\\surd", tag:"mo", output:"\\sqrt{}", ttype:DEFINITION},
1305{input:"\\partial", tag:"mo", output:"\u2202", ttype:CONST},
1306{input:"\\nabla", tag:"mo", output:"\u2207", ttype:CONST},
1307{input:"\\triangle", tag:"mo", output:"\u25B3", ttype:CONST},
1308{input:"\\therefore", tag:"mo", output:"\u2234", ttype:CONST},
1309{input:"\\angle", tag:"mo", output:"\u2220", ttype:CONST},
1310//{input:"\\\\ ", tag:"mo", output:"\u00A0", ttype:CONST},
1311{input:"\\diamond", tag:"mo", output:"\u22C4", ttype:CONST},
1312//{input:"\\Diamond", tag:"mo", output:"\u25CA", ttype:CONST},
1313{input:"\\Diamond", tag:"mo", output:"\u25C7", ttype:CONST},
1314{input:"\\neg", tag:"mo", output:"\u00AC", ttype:CONST},
1315{input:"\\lnot", tag:"mo", output:"\u00AC", ttype:CONST},
1316{input:"\\bot", tag:"mo", output:"\u22A5", ttype:CONST},
1317{input:"\\top", tag:"mo", output:"\u22A4", ttype:CONST},
1318{input:"\\square", tag:"mo", output:"\u25AB", ttype:CONST},
1319{input:"\\Box", tag:"mo", output:"\u25A1", ttype:CONST},
1320{input:"\\wr", tag:"mo", output:"\u2240", ttype:CONST},
1323//Note UNDEROVER *must* have tag:"mo" to work properly
1324{input:"\\arccos", tag:"mi", output:"arccos", ttype:UNARY, func:true},
1325{input:"\\arcsin", tag:"mi", output:"arcsin", ttype:UNARY, func:true},
1326{input:"\\arctan", tag:"mi", output:"arctan", ttype:UNARY, func:true},
1327{input:"\\arg", tag:"mi", output:"arg", ttype:UNARY, func:true},
1328{input:"\\cos", tag:"mi", output:"cos", ttype:UNARY, func:true},
1329{input:"\\cosh", tag:"mi", output:"cosh", ttype:UNARY, func:true},
1330{input:"\\cot", tag:"mi", output:"cot", ttype:UNARY, func:true},
1331{input:"\\coth", tag:"mi", output:"coth", ttype:UNARY, func:true},
1332{input:"\\csc", tag:"mi", output:"csc", ttype:UNARY, func:true},
1333{input:"\\deg", tag:"mi", output:"deg", ttype:UNARY, func:true},
1334{input:"\\det", tag:"mi", output:"det", ttype:UNARY, func:true},
1335{input:"\\dim", tag:"mi", output:"dim", ttype:UNARY, func:true}, //CONST?
1336{input:"\\exp", tag:"mi", output:"exp", ttype:UNARY, func:true},
1337{input:"\\gcd", tag:"mi", output:"gcd", ttype:UNARY, func:true}, //CONST?
1338{input:"\\hom", tag:"mi", output:"hom", ttype:UNARY, func:true},
1339{input:"\\inf", tag:"mo", output:"inf", ttype:UNDEROVER},
1340{input:"\\ker", tag:"mi", output:"ker", ttype:UNARY, func:true},
1341{input:"\\lg", tag:"mi", output:"lg", ttype:UNARY, func:true},
1342{input:"\\lim", tag:"mo", output:"lim", ttype:UNDEROVER},
1343{input:"\\liminf", tag:"mo", output:"liminf", ttype:UNDEROVER},
1344{input:"\\limsup", tag:"mo", output:"limsup", ttype:UNDEROVER},
1345{input:"\\ln", tag:"mi", output:"ln", ttype:UNARY, func:true},
1346{input:"\\log", tag:"mi", output:"log", ttype:UNARY, func:true},
1347{input:"\\max", tag:"mo", output:"max", ttype:UNDEROVER},
1348{input:"\\min", tag:"mo", output:"min", ttype:UNDEROVER},
1349{input:"\\Pr", tag:"mi", output:"Pr", ttype:UNARY, func:true},
1350{input:"\\sec", tag:"mi", output:"sec", ttype:UNARY, func:true},
1351{input:"\\sin", tag:"mi", output:"sin", ttype:UNARY, func:true},
1352{input:"\\sinh", tag:"mi", output:"sinh", ttype:UNARY, func:true},
1353{input:"\\sup", tag:"mo", output:"sup", ttype:UNDEROVER},
1354{input:"\\tan", tag:"mi", output:"tan", ttype:UNARY, func:true},
1355{input:"\\tanh", tag:"mi", output:"tanh", ttype:UNARY, func:true},
1358{input:"\\gets", tag:"mo", output:"\u2190", ttype:CONST},
1359{input:"\\leftarrow", tag:"mo", output:"\u2190", ttype:CONST},
1360{input:"\\to", tag:"mo", output:"\u2192", ttype:CONST},
1361{input:"\\rightarrow", tag:"mo", output:"\u2192", ttype:CONST},
1362{input:"\\leftrightarrow", tag:"mo", output:"\u2194", ttype:CONST},
1363{input:"\\uparrow", tag:"mo", output:"\u2191", ttype:CONST},
1364{input:"\\downarrow", tag:"mo", output:"\u2193", ttype:CONST},
1365{input:"\\updownarrow", tag:"mo", output:"\u2195", ttype:CONST},
1366{input:"\\Leftarrow", tag:"mo", output:"\u21D0", ttype:CONST},
1367{input:"\\Rightarrow", tag:"mo", output:"\u21D2", ttype:CONST},
1368{input:"\\Leftrightarrow", tag:"mo", output:"\u21D4", ttype:CONST},
1369{input:"\\iff", tag:"mo", output:"~\\Longleftrightarrow~", ttype:DEFINITION},
1370{input:"\\Uparrow", tag:"mo", output:"\u21D1", ttype:CONST},
1371{input:"\\Downarrow", tag:"mo", output:"\u21D3", ttype:CONST},
1372{input:"\\Updownarrow", tag:"mo", output:"\u21D5", ttype:CONST},
1373{input:"\\mapsto", tag:"mo", output:"\u21A6", ttype:CONST},
1374{input:"\\longleftarrow", tag:"mo", output:"\u2190", ttype:LONG},
1375{input:"\\longrightarrow", tag:"mo", output:"\u2192", ttype:LONG},
1376{input:"\\longleftrightarrow", tag:"mo", output:"\u2194", ttype:LONG},
1377{input:"\\Longleftarrow", tag:"mo", output:"\u21D0", ttype:LONG},
1378{input:"\\Longrightarrow", tag:"mo", output:"\u21D2", ttype:LONG},
1379{input:"\\implies", tag:"mo", output:"\u21D2", ttype:LONG},
1380{input:"\\Longleftrightarrow", tag:"mo", output:"\u21D4", ttype:LONG},
1381{input:"\\longmapsto", tag:"mo", output:"\u21A6", ttype:CONST},
1384//commands with argument
1386{input:"\\sqrt", tag:"msqrt", output:"sqrt", ttype:UNARY},
1387{input:"\\root", tag:"mroot", output:"root", ttype:BINARY},
1388{input:"\\frac", tag:"mfrac", output:"/", ttype:BINARY},
1389{input:"\\stackrel", tag:"mover", output:"stackrel", ttype:BINARY},
1390{input:"\\atop", tag:"mfrac", output:"", ttype:INFIX},
1391{input:"\\choose", tag:"mfrac", output:"", ttype:INFIX},
1392{input:"_", tag:"msub", output:"_", ttype:INFIX},
1393{input:"^", tag:"msup", output:"^", ttype:INFIX},
1394{input:"\\mathrm", tag:"mtext", output:"text", ttype:TEXT},
1395{input:"\\mbox", tag:"mtext", output:"mbox", ttype:TEXT},
1398{input:"\\acute", tag:"mover", output:"\u00B4", ttype:UNARY, acc:true},
1399//{input:"\\acute", tag:"mover", output:"\u0317", ttype:UNARY, acc:true},
1400//{input:"\\acute", tag:"mover", output:"\u0301", ttype:UNARY, acc:true},
1401//{input:"\\grave", tag:"mover", output:"\u0300", ttype:UNARY, acc:true},
1402//{input:"\\grave", tag:"mover", output:"\u0316", ttype:UNARY, acc:true},
1403{input:"\\grave", tag:"mover", output:"\u0060", ttype:UNARY, acc:true},
1404{input:"\\breve", tag:"mover", output:"\u02D8", ttype:UNARY, acc:true},
1405{input:"\\check", tag:"mover", output:"\u02C7", ttype:UNARY, acc:true},
1406{input:"\\dot", tag:"mover", output:".", ttype:UNARY, acc:true},
1407{input:"\\ddot", tag:"mover", output:"..", ttype:UNARY, acc:true},
1408//{input:"\\ddot", tag:"mover", output:"\u00A8", ttype:UNARY, acc:true},
1409{input:"\\mathring", tag:"mover", output:"\u00B0", ttype:UNARY, acc:true},
1410{input:"\\vec", tag:"mover", output:"\u20D7", ttype:UNARY, acc:true},
1411{input:"\\overrightarrow",tag:"mover",output:"\u20D7", ttype:UNARY, acc:true},
1412{input:"\\overleftarrow",tag:"mover", output:"\u20D6", ttype:UNARY, acc:true},
1413{input:"\\hat", tag:"mover", output:"\u005E", ttype:UNARY, acc:true},
1414{input:"\\widehat", tag:"mover", output:"\u0302", ttype:UNARY, acc:true},
1415{input:"\\tilde", tag:"mover", output:"~", ttype:UNARY, acc:true},
1416//{input:"\\tilde", tag:"mover", output:"\u0303", ttype:UNARY, acc:true},
1417{input:"\\widetilde", tag:"mover", output:"\u02DC", ttype:UNARY, acc:true},
1418{input:"\\bar", tag:"mover", output:"\u203E", ttype:UNARY, acc:true},
1419{input:"\\overbrace", tag:"mover", output:"\u23B4", ttype:UNARY, acc:true},
1420{input:"\\overline", tag:"mover", output:"\u00AF", ttype:UNARY, acc:true},
1421{input:"\\underbrace", tag:"munder", output:"\u23B5", ttype:UNARY, acc:true},
1422{input:"\\underline", tag:"munder", output:"\u00AF", ttype:UNARY, acc:true},
1423//{input:"underline", tag:"munder", output:"\u0332", ttype:UNARY, acc:true},
1425//typestyles and fonts
1426{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true", ttype:UNARY},
1427{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false", ttype:UNARY},
1428{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1", ttype:UNARY},
1429{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2", ttype:UNARY},
1430{input:"\\textrm", tag:"mstyle", output:"\\mathrm", ttype: DEFINITION},
1431{input:"\\mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},
1432{input:"\\textbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},
1433{input:"\\mathit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},
1434{input:"\\textit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},
1435{input:"\\mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},
1436{input:"\\texttt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},
1437{input:"\\mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", ttype:UNARY},
1438{input:"\\mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", ttype:UNARY, codes:AMbbb},
1439{input:"\\mathcal",tag:"mstyle", atname:"mathvariant", atval:"script", ttype:UNARY, codes:AMcal},
1440{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant", atval:"fraktur",ttype:UNARY, codes:AMfrk}
1443var LMnames = []; //list of input symbols
1445function LMremoveCharsAndBlanks(str,n) {
1446//remove n characters and any following blanks
1449 for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
1453function LMgetSymbol(str) {
1454//return maximal initial substring of str that appears in names
1455//return null if there is none
1456 var k = 0; //new pos
1457 var j = 0; //old pos
1463 for (var i=1; i<=str.length && more; i++) {
1464 st = str.slice(0,i); //initial substring of length i
1466 k = position(LMnames, st, j);
1467 if (k<LMnames.length && str.slice(0,LMnames[k].length)==LMnames[k]){
1472 more = k<LMnames.length && str.slice(0,LMnames[k].length)>=LMnames[k];
1474 LMpreviousSymbol=LMcurrentSymbol;
1476 LMcurrentSymbol=LMsymbols[mk].ttype;
1477 return LMsymbols[mk];
1479 LMcurrentSymbol=CONST;
1481 st = str.slice(0,1); //take 1 character
1482 if ("0"<=st && st<="9") tagst = "mn";
1483 else tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
1485// Commented out by DRW (not fully understood, but probably to do with
1486// use of "/" as an INFIX version of "\\frac", which we don't want):
1488//if (st=="-" && LMpreviousSymbol==INFIX) {
1489// LMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse
1490// return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
1493 return {input:st, tag:tagst, output:st, ttype:CONST};
1497/*Parsing ASCII math expressions with the following grammar
1498v ::= [A-Za-z] | greek letters | numbers | other constant symbols
1499u ::= sqrt | text | bb | other unary symbols for font commands
1500b ::= frac | root | stackrel binary symbols
1501l ::= { | \left left brackets
1502r ::= } | \right right brackets
1503S ::= v | lEr | uS | bSS Simple expression
1504I ::= S_S | S^S | S_S^S | S Intermediate expression
1505E ::= IE | I/I Expression
1506Each terminal symbol is translated into a corresponding mathml node.*/
1508var LMpreviousSymbol,LMcurrentSymbol;
1510function LMparseSexpr(str) { //parses str and returns [node,tailstr,(node)tag]
1511 var symbol, node, result, result2, i, st,// rightvert = false,
1512 newFrag = document.createDocumentFragment();
1513 str = LMremoveCharsAndBlanks(str,0);
1514 symbol = LMgetSymbol(str); //either a token or a bracket or empty
1515 if (symbol == null || symbol.ttype == RIGHTBRACKET)
1516 return [null,str,null];
1517 if (symbol.ttype == DEFINITION) {
1518 str = symbol.output+LMremoveCharsAndBlanks(str,symbol.input.length);
1519 symbol = LMgetSymbol(str);
1520 if (symbol == null || symbol.ttype == RIGHTBRACKET)
1521 return [null,str,null];
1523 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1524 switch (symbol.ttype) {
1526 node = createMmlNode(symbol.tag);
1527 node.setAttribute(symbol.atname,symbol.atval);
1528 return [node,str,symbol.tag];
1531 if (symbol.input.substr(0,4) == "\\big") { // botch for missing symbols
1532 str = "\\"+symbol.input.substr(4)+str; // make \bigcup = \cup etc.
1533 symbol = LMgetSymbol(str);
1534 symbol.ttype = UNDEROVER;
1535 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1538 return [createMmlNode(symbol.tag,
1539 document.createTextNode(symbol.output)),str,symbol.tag];
1541 var output = symbol.output;
1543 if (symbol.input == "'")
1545 else if (symbol.input == "''")
1547 else if (symbol.input == "'''")
1548 output = "\u2033\u2032";
1549 else if (symbol.input == "''''")
1550 output = "\u2033\u2033";
1551 else if (symbol.input == "\\square")
1552 output = "\u25A1"; // same as \Box
1553 else if (symbol.input.substr(0,5) == "\\frac") {
1554 // botch for missing fractions
1555 var denom = symbol.input.substr(6,1);
1556 if (denom == "5" || denom == "6") {
1557 str = symbol.input.replace(/\\frac/,"\\frac ")+str;
1558 return [node,str,symbol.tag];
1562 node = createMmlNode(symbol.tag,document.createTextNode(output));
1563 return [node,str,symbol.tag];
1564 case LONG: // added by DRW
1565 node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));
1566 node.setAttribute("minsize","1.5");
1567 node.setAttribute("maxsize","1.5");
1568 node = createMmlNode("mover",node);
1569 node.appendChild(createMmlNode("mspace"));
1570 return [node,str,symbol.tag];
1571 case STRETCHY: // added by DRW
1572 if (isIE && symbol.input == "\\backslash")
1573 symbol.output = "\\"; // doesn't expand, but then nor does "\u2216"
1574 node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));
1575 if (symbol.input == "|" || symbol.input == "\\vert" ||
1576 symbol.input == "\\|" || symbol.input == "\\Vert") {
1577 node.setAttribute("lspace","0em");
1578 node.setAttribute("rspace","0em");
1580 node.setAttribute("maxsize",symbol.atval); // don't allow to stretch here
1581 if (symbol.rtag != null)
1582 return [node,str,symbol.rtag];
1584 return [node,str,symbol.tag];
1585 case BIG: // added by DRW
1586 var atval = symbol.atval;
1588 atval = symbol.ieval;
1589 symbol = LMgetSymbol(str);
1591 return [null,str,null];
1592 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1593 node = createMmlNode(symbol.tag,document.createTextNode(symbol.output));
1594 if (isIE) { // to get brackets to expand
1595 var space = createMmlNode("mspace");
1596 space.setAttribute("height",atval+"ex");
1597 node = createMmlNode("mrow",node);
1598 node.appendChild(space);
1599 } else { // ignored in IE
1600 node.setAttribute("minsize",atval);
1601 node.setAttribute("maxsize",atval);
1603 return [node,str,symbol.tag];
1604 case LEFTBRACKET: //read (expr+)
1605 if (symbol.input == "\\left") { // left what?
1606 symbol = LMgetSymbol(str);
1607 if (symbol != null) {
1608 if (symbol.input == ".")
1609 symbol.invisible = true;
1610 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1613 result = LMparseExpr(str,true,false);
1615 (typeof symbol.invisible == "boolean" && symbol.invisible))
1616 node = createMmlNode("mrow",result[0]);
1618 node = createMmlNode("mo",document.createTextNode(symbol.output));
1619 node = createMmlNode("mrow",node);
1620 node.appendChild(result[0]);
1622 return [node,result[1],result[2]];
1623 case MATRIX: //read (expr+)
1624 if (symbol.input == "\\begin{array}") {
1626 symbol = LMgetSymbol(str);
1627 str = LMremoveCharsAndBlanks(str,0);
1631 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1632 if (symbol.input != "{")
1635 symbol = LMgetSymbol(str);
1636 if (symbol != null) {
1637 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1638 if (symbol.input != "}")
1639 mask = mask+symbol.input;
1641 } while (symbol != null && symbol.input != "" && symbol.input != "}");
1643 result = LMparseExpr("{"+str,true,true);
1644// if (result[0]==null) return [createMmlNode("mo",
1645// document.createTextNode(symbol.input)),str];
1646 node = createMmlNode("mtable",result[0]);
1647 mask = mask.replace(/l/g,"left ");
1648 mask = mask.replace(/r/g,"right ");
1649 mask = mask.replace(/c/g,"center ");
1650 node.setAttribute("columnalign",mask);
1651 node.setAttribute("displaystyle","false");
1653 return [node,result[1],null];
1654// trying to get a *little* bit of space around the array
1655// (IE already includes it)
1656 var lspace = createMmlNode("mspace");
1657 lspace.setAttribute("width","0.167em");
1658 var rspace = createMmlNode("mspace");
1659 rspace.setAttribute("width","0.167em");
1660 var node1 = createMmlNode("mrow",lspace);
1661 node1.appendChild(node);
1662 node1.appendChild(rspace);
1663 return [node1,result[1],null];
1664 } else { // eqnarray
1665 result = LMparseExpr("{"+str,true,true);
1666 node = createMmlNode("mtable",result[0]);
1668 node.setAttribute("columnspacing","0.25em"); // best in practice?
1670 node.setAttribute("columnspacing","0.167em"); // correct (but ignored?)
1671 node.setAttribute("columnalign","right center left");
1672 node.setAttribute("displaystyle","true");
1673 node = createMmlNode("mrow",node);
1674 return [node,result[1],null];
1677 if (str.charAt(0)=="{") i=str.indexOf("}");
1681 st = str.slice(1,i);
1682 if (st.charAt(0) == " ") {
1683 node = createMmlNode("mspace");
1684 node.setAttribute("width","0.33em"); // was 1ex
1685 newFrag.appendChild(node);
1687 newFrag.appendChild(
1688 createMmlNode(symbol.tag,document.createTextNode(st)));
1689 if (st.charAt(st.length-1) == " ") {
1690 node = createMmlNode("mspace");
1691 node.setAttribute("width","0.33em"); // was 1ex
1692 newFrag.appendChild(node);
1694 str = LMremoveCharsAndBlanks(str,i+1);
1695 return [createMmlNode("mrow",newFrag),str,null];
1697 result = LMparseSexpr(str);
1698 if (result[0]==null) return [createMmlNode(symbol.tag,
1699 document.createTextNode(symbol.output)),str];
1700 if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
1702// if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {
1703 if (st=="^" || st=="_" || st==",") {
1704 return [createMmlNode(symbol.tag,
1705 document.createTextNode(symbol.output)),str,symbol.tag];
1707 node = createMmlNode("mrow",
1708 createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
1710 var space = createMmlNode("mspace");
1711 space.setAttribute("width","0.167em");
1712 node.appendChild(space);
1714 node.appendChild(result[0]);
1715 return [node,result[1],symbol.tag];
1718 if (symbol.input == "\\sqrt") { // sqrt
1719 if (isIE) { // set minsize, for \surd
1720 var space = createMmlNode("mspace");
1721 space.setAttribute("height","1.2ex");
1722 space.setAttribute("width","0em"); // probably no effect
1723 node = createMmlNode(symbol.tag,result[0])
1724// node.setAttribute("minsize","1"); // ignored
1725// node = createMmlNode("mrow",node); // hopefully unnecessary
1726 node.appendChild(space);
1727 return [node,result[1],symbol.tag];
1729 return [createMmlNode(symbol.tag,result[0]),result[1],symbol.tag];
1730 } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent
1731 node = createMmlNode(symbol.tag,result[0]);
1732 var output = symbol.output;
1734 if (symbol.input == "\\hat")
1736 else if (symbol.input == "\\widehat")
1738 else if (symbol.input == "\\bar")
1740 else if (symbol.input == "\\grave")
1742 else if (symbol.input == "\\tilde")
1745 var node1 = createMmlNode("mo",document.createTextNode(output));
1746 if (symbol.input == "\\vec" || symbol.input == "\\check")
1747 // don't allow to stretch
1748 node1.setAttribute("maxsize","1.2");
1749 // why doesn't "1" work? \vec nearly disappears in firefox
1750 if (isIE && symbol.input == "\\bar")
1751 node1.setAttribute("maxsize","0.5");
1752 if (symbol.input == "\\underbrace" || symbol.input == "\\underline")
1753 node1.setAttribute("accentunder","true");
1755 node1.setAttribute("accent","true");
1756 node.appendChild(node1);
1757 if (symbol.input == "\\overbrace" || symbol.input == "\\underbrace")
1758 node.ttype = UNDEROVER;
1759 return [node,result[1],symbol.tag];
1760 } else { // font change or displaystyle command
1761 if (!isIE && typeof symbol.codes != "undefined") {
1762 for (i=0; i<result[0].childNodes.length; i++)
1763 if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
1764 st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
1765 result[0].childNodes[i].firstChild.nodeValue);
1767 for (var j=0; j<st.length; j++)
1768 if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +
1769 String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);
1770 else newst = newst + st.charAt(j);
1771 if (result[0].nodeName=="mi")
1772 result[0]=createMmlNode("mo").
1773 appendChild(document.createTextNode(newst));
1774 else result[0].replaceChild(createMmlNode("mo").
1775 appendChild(document.createTextNode(newst)),result[0].childNodes[i]);
1778 node = createMmlNode(symbol.tag,result[0]);
1779 node.setAttribute(symbol.atname,symbol.atval);
1780 if (symbol.input == "\\scriptstyle" ||
1781 symbol.input == "\\scriptscriptstyle")
1782 node.setAttribute("displaystyle","false");
1783 return [node,result[1],symbol.tag];
1786 result = LMparseSexpr(str);
1787 if (result[0]==null) return [createMmlNode("mo",
1788 document.createTextNode(symbol.input)),str,null];
1789 result2 = LMparseSexpr(result[1]);
1790 if (result2[0]==null) return [createMmlNode("mo",
1791 document.createTextNode(symbol.input)),str,null];
1792 if (symbol.input=="\\root" || symbol.input=="\\stackrel")
1793 newFrag.appendChild(result2[0]);
1794 newFrag.appendChild(result[0]);
1795 if (symbol.input=="\\frac") newFrag.appendChild(result2[0]);
1796 return [createMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];
1798 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1799 return [createMmlNode("mo",document.createTextNode(symbol.output)),
1802 return [createMmlNode(symbol.tag, //its a constant
1803 document.createTextNode(symbol.output)),str,symbol.tag];
1807function LMparseIexpr(str) {
1808 var symbol, sym1, sym2, node, result, tag, underover;
1809 str = LMremoveCharsAndBlanks(str,0);
1810 sym1 = LMgetSymbol(str);
1811 result = LMparseSexpr(str);
1815 symbol = LMgetSymbol(str);
1816 if (symbol.ttype == INFIX) {
1817 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1818 result = LMparseSexpr(str);
1819 if (result[0] == null) // show box in place of missing argument
1820 result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
1823 if (symbol.input == "_" || symbol.input == "^") {
1824 sym2 = LMgetSymbol(str);
1825 tag = null; // no space between x^2 and a following sin, cos, etc.
1826// This is for \underbrace and \overbrace
1827 underover = ((sym1.ttype == UNDEROVER) || (node.ttype == UNDEROVER));
1828// underover = (sym1.ttype == UNDEROVER);
1829 if (symbol.input == "_" && sym2.input == "^") {
1830 str = LMremoveCharsAndBlanks(str,sym2.input.length);
1831 var res2 = LMparseSexpr(str);
1833 tag = res2[2]; // leave space between x_1^2 and a following sin etc.
1834 node = createMmlNode((underover?"munderover":"msubsup"),node);
1835 node.appendChild(result[0]);
1836 node.appendChild(res2[0]);
1837 } else if (symbol.input == "_") {
1838 node = createMmlNode((underover?"munder":"msub"),node);
1839 node.appendChild(result[0]);
1841 node = createMmlNode((underover?"mover":"msup"),node);
1842 node.appendChild(result[0]);
1844 node = createMmlNode("mrow",node); // so sum does not stretch
1846 node = createMmlNode(symbol.tag,node);
1847 if (symbol.input == "\\atop" || symbol.input == "\\choose")
1848 node.setAttribute("linethickness","0ex");
1849 node.appendChild(result[0]);
1850 if (symbol.input == "\\choose")
1851 node = createMmlNode("mfenced",node);
1854 return [node,str,tag];
1857function LMparseExpr(str,rightbracket,matrix) {
1858 var symbol, node, result, i, tag,
1859 newFrag = document.createDocumentFragment();
1861 str = LMremoveCharsAndBlanks(str,0);
1862 result = LMparseIexpr(str);
1866 symbol = LMgetSymbol(str);
1867 if (node!=undefined) {
1868 if ((tag == "mn" || tag == "mi") && symbol!=null &&
1869 typeof symbol.func == "boolean" && symbol.func) {
1870 // Add space before \sin in 2\sin x or x\sin x
1871 var space = createMmlNode("mspace");
1872 space.setAttribute("width","0.167em");
1873 node = createMmlNode("mrow",node);
1874 node.appendChild(space);
1876 newFrag.appendChild(node);
1878 } while ((symbol.ttype != RIGHTBRACKET)
1879 && symbol!=null && symbol.output!="");
1881 if (symbol.ttype == RIGHTBRACKET) {
1882 if (symbol.input == "\\right") { // right what?
1883 str = LMremoveCharsAndBlanks(str,symbol.input.length);
1884 symbol = LMgetSymbol(str);
1885 if (symbol != null && symbol.input == ".")
1886 symbol.invisible = true;
1891 str = LMremoveCharsAndBlanks(str,symbol.input.length); // ready to return
1892 var len = newFrag.childNodes.length;
1894 len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&
1895 newFrag.childNodes[len-2].nodeName == "mo" &&
1896 newFrag.childNodes[len-2].firstChild.nodeValue == "&") { //matrix
1897 var pos = []; // positions of ampersands
1898 var m = newFrag.childNodes.length;
1899 for (i=0; matrix && i<m; i=i+2) {
1901 node = newFrag.childNodes[i];
1902 for (var j=0; j<node.childNodes.length; j++)
1903 if (node.childNodes[j].firstChild.nodeValue=="&")
1904 pos[i][pos[i].length]=j;
1906 var row, frag, n, k, table = document.createDocumentFragment();
1907 for (i=0; i<m; i=i+2) {
1908 row = document.createDocumentFragment();
1909 frag = document.createDocumentFragment();
1910 node = newFrag.firstChild; // <mrow> -&-&...&-&- </mrow>
1911 n = node.childNodes.length;
1913 for (j=0; j<n; j++) {
1914 if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
1915 node.removeChild(node.firstChild); //remove &
1916 row.appendChild(createMmlNode("mtd",frag));
1918 } else frag.appendChild(node.firstChild);
1920 row.appendChild(createMmlNode("mtd",frag));
1921 if (newFrag.childNodes.length>2) {
1922 newFrag.removeChild(newFrag.firstChild); //remove <mrow> </mrow>
1923 newFrag.removeChild(newFrag.firstChild); //remove <mo>&</mo>
1925 table.appendChild(createMmlNode("mtr",row));
1929 if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
1930 node = createMmlNode("mo",document.createTextNode(symbol.output));
1931 newFrag.appendChild(node);
1934 return [newFrag,str,tag];
1937var tcnt = 0, dcnt = 0; //theorem and definition counters
1939function simpleLaTeXformatting(st) {
1940 st = st.replace(/\$\$((.|\n)*?)\$\$/g,"<p align=\"center\">$\\displaystyle{$1}$</p>");
1941 st = st.replace(/\\begin{(theorem|lemma|proposition|corollary)}((.|\n)*?)\\end{\1}/g,function(r,s,t){tcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+tcnt+".</b> <i>"+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+"</i>"});
1942 st = st.replace(/\\begin{(definition|example|remark|problem|exercise|conjecture|solution)}((.|\n)*?)\\end{\1}/g,function(r,s,t){dcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+dcnt+".</b> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")});
1943 st = st.replace(/\\begin{proof}((.|\n)*?)\\end{proof}/g,function(s,t){return "<i>Proof:</i> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+" □"});
1944 st = st.replace(/\\emph{(.*?)}/g,"<em>$1</em>");
1945 st = st.replace(/\\textbf{(.*?)}/g,"<b>$1</b>");
1946 st = st.replace(/\\cite{(.*?)}/g,"[$1]");
1947 st = st.replace(/\\chapter{(.*?)}/g,"<h2>$1</h2>");
1948 st = st.replace(/\\section{(.*?)}(\s*<\/?(br|p)\s?\/?>)?/g,"<h3>$1</h3>");
1949 st = st.replace(/\\subsection{((.|\n)*?)}/g,"<h4>$1</h4>");
1950 st = st.replace(/\\begin{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"<ul>");
1951 st = st.replace(/\\item\s((.|\n)*?)(?=(\\item|\\end))/g,"<li>$1</li>");
1952 st = st.replace(/\\end{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"</ul>");
1953 st = st.replace(/\\begin{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"<ol>");
1954 st = st.replace(/\\end{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"</ol>");
1955 st = st.replace(/\\item\[(.*?)]{(.*?)}/g,"<dt>$1</dt><dd>$2</dd>");
1956 st = st.replace(/\\begin{description}/g,"<dl>");
1957 st = st.replace(/\\end{description}/g,"</dl>");
1958 st = st.replace(/\\newline\b/g,"<br/>");
1959 st = st.replace(/\\newpage\b/g,"<br style=\"page-break-after:always;\">");
1960 st = st.replace(/\\par\b/g,"<p> </p>");
1961 st = st.replace(/\\bigskip/g,"<p style=\"margin-bottom:0.5in\"> </p>");
1962 st = st.replace(/\\medskip/g,"<p style=\"margin-bottom:0.3in\"> </p>");
1963 st = st.replace(/\\smallskip/g,"<p style=\"margin-bottom:0.15in\"> </p>");
1964 st = st.replace(/\\begin{center}((.|\n)*?)\\end{center}/g,"<center>$1</center>");
1968function ASCIIandgraphformatting(st) {
1969 st = st.replace(/<sup>(.*?)<\/sup>(\s|(\S))/gi,"^{$1} $3");
1970//st = st.replace(/<\/?font.*?>/gi,""); // do this only in amath...endamath
1971 st = st.replace(/(Proof:)/g,"<i>$1</i>");
1972 st = st.replace(/QED/g," □");
1973 st = st.replace(/(\\?end{?a?math}?)/ig,"<span></span>$1");
1974 st = st.replace(/(\bamath\b|\\begin{a?math})/ig,"<span></span>$1");
1975 st = st.replace(/([>\n])(Theorem|Lemma|Proposition|Corollary|Definition|Example|Remark|Problem|Exercise|Conjecture|Solution)(:|\W\W?(\w|\s|-|\.)*?\W?:)/g,"$1<b>$2$3</b>");
1976 st = st.replace(/<embed\s+class\s?=\s?"?ASCIIsvg"?/gi,"<embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\"");
1977 st = st.replace(/(?:\\begin{a?graph}|\bagraph|\(:graph\s)((.|\n)*?)(?:\\end{a?graph}|enda?graph|:\))/g,function(s,t){return "<table><tr><td><div class=\"ASCIIsvg\"><embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\" script=\'"+t.replace(/<\/?(br|p|pre)\s?\/?>/gi,"\n")+"\'/></div></td></tr></table>"});
1978 st = st.replace(/insertASCIIMathCalculator/g,"<div class=\"ASCIIMathCalculator\"></div>");
1979//alert(dsvglocation)
1983function LMprocessNode(n) {
1988 var am = /amath\b|graph/i.test(st);
1989 if ((st==null || st.indexOf("\$ ")!=-1 || st.indexOf("\$<")!=-1 ||
1990 st.indexOf("\\begin")!=-1 || am || st.slice(-1)=="$" ||
1991 st.indexOf("\$\n")!=-1)&& !/edit-content|HTMLArea|wikiedit|wpTextbox1/.test(st)){
1992 if (!avoidinnerHTML && translateLaTeXformatting)
1993 st = simpleLaTeXformatting(st);
1994 if (st!=null && am && !avoidinnerHTML) {
1995 st = ASCIIandgraphformatting(st);
1997 st = st.replace(/%7E/g,"~"); // else PmWiki has url issues
1999 if (!avoidinnerHTML) n.innerHTML = st;
2000 processNodeR(n,false,true);
2002/* if (isIE) { //needed to match size and font of formula to surrounding text
2003 frag = document.getElementsByTagName('math');
2004 for (var i=0;i<frag.length;i++) frag[i].update() //is this really needed?
2010JavaScript routines to dynamically generate Scalable Vector Graphics
2011using a mathematical xy-coordinate system (y increases upwards) and
2012very intuitive JavaScript commands (no programming experience required).
2013ASCIIsvg.js is good for learning math and illustrating online math texts.
2014Works with Internet Explorer+Adobe SVGviewer and SVG enabled Mozilla/Firefox.
2016Ver 1.2.9 July 31, 2007 (c) Peter Jipsen http://www.chapman.edu/~jipsen
2017Latest version at http://math.chapman.edu/~jipsen/math/pub/ASCIIsvg.js
2018If you use it on a webpage, please send the URL to jipsen@chapman.edu
2020This program is free software; you can redistribute it and/or modify
2021it under the terms of the GNU Lesser General Public License as published by
2022the Free Software Foundation; either version 2.1 of the License, or (at
2023your option) any later version.
2025This program is distributed in the hope that it will be useful,
2026but WITHOUT ANY WARRANTY; without even the implied warranty of
2027MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
2028General Public License (at http://www.gnu.org/license/lgpl.html)
2031// you can change these
2032var checkIfSVGavailable = true;
2033var notifyIfNoSVG = true;
2034var alertIfNoSVG = false;
2037// global defaults used if not specified by graph (you can change these)
2038var defaultwidth = 300; defaultheight = 200; // in pixels
2039var defaultxmin = -5.5; defaultxmax = 5.5; // in usercoords
2040var defaultborder = 0; border = defaultborder; // in pixel
2041var defaultstrokewidth = "1"; // default line width in pixel
2042var defaultstroke = "blue"; // default line color
2043var defaultstrokeopacity = 1; // transparent = 0, solid =1
2044var defaultstrokedasharray = null; // "10,10" gives 10px long dashes
2045var defaultfill = "none"; // default fill color
2046var defaultfillopacity = 1; // transparent = 0, solid =1
2047var defaultfontstyle = "normal"; // default text shape normal|italic|inherit
2048var defaultfontfamily = "times"; // default font times|ariel|helvetica|...
2049var defaultfontsize = "16"; // default size (scaled automatically)
2050var defaultfontweight = "normal";// normal|bold|bolder|lighter|100|...|900
2051var defaultfontstroke = "none"; // default font outline color
2052var defaultfontfill = "none"; // default font color
2053var defaultmarker = "none"; // "dot" | "arrow" | "+" | "-" | "|"
2054var defaultendpoints = ""; // "c-d" where c is <|o|* and d is >|o|*
2056// global values used for all pictures (you can change these)
2057var showcoordinates = true;
2058var markerstrokewidth = "1";
2059var markerstroke = "black";
2060var markerfill = "yellow";
2062var arrowfill = stroke;
2065var axesstroke = "black";
2066var gridstroke = "grey";
2067var backgroundstyle = "fill-opacity:0; fill:white";
2068var singlelettersitalic = true;
2070// internal variables (probably no need to change these)
2071var picturepos = null; // position of picture relative to top of HTML page
2072var xunitlength; // in pixels, used to convert to user coordinates
2073var yunitlength; // in pixels
2074var origin = [0,0]; // in pixels (default is bottom left corner)
2075var above = "above"; // shorthands (to avoid typing quotes)
2079var aboveleft = "aboveleft";
2080var aboveright = "aboveright";
2081var belowleft = "belowleft";
2082var belowright = "belowright";
2083var xmin, xmax, ymin, ymax, xscl, yscl,
2084 xgrid, ygrid, xtick, ytick, initialized;
2085var strokewidth, strokedasharray, stroke, fill, strokeopacity, fillopacity;
2086var fontstyle, fontfamily, fontsize, fontweight, fontstroke, fontfill;
2087var marker, endpoints, dynamic = {};
2088var picture, svgpicture, doc, width, height;
2089var isIE = document.createElementNS==null;
2091//this is not used! var cpi = "\u03C0", ctheta = "\u03B8"; // character for pi, theta
2092var log = function(x) { return ln(x)/ln(10) };
2093var pi = Math.PI, e = Math.E, ln = Math.log, sqrt = Math.sqrt;
2094var floor = Math.floor, ceil = Math.ceil, abs = Math.abs;
2095var sin = Math.sin, cos = Math.cos, tan = Math.tan;
2096var arcsin = Math.asin, arccos = Math.acos, arctan = Math.atan;
2097var sec = function(x) { return 1/Math.cos(x) };
2098var csc = function(x) { return 1/Math.sin(x) };
2099var cot = function(x) { return 1/Math.tan(x) };
2100var arcsec = function(x) { return arccos(1/x) };
2101var arccsc = function(x) { return arcsin(1/x) };
2102var arccot = function(x) { return arctan(1/x) };
2103var sinh = function(x) { return (Math.exp(x)-Math.exp(-x))/2 };
2104var cosh = function(x) { return (Math.exp(x)+Math.exp(-x))/2 };
2106 function(x) { return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x)) };
2107var sech = function(x) { return 1/cosh(x) };
2108var csch = function(x) { return 1/sinh(x) };
2109var coth = function(x) { return 1/tanh(x) };
2110var arcsinh = function(x) { return ln(x+Math.sqrt(x*x+1)) };
2111var arccosh = function(x) { return ln(x+Math.sqrt(x*x-1)) };
2112var arctanh = function(x) { return ln((1+x)/(1-x))/2 };
2113var sech = function(x) { return 1/cosh(x) };
2114var csch = function(x) { return 1/sinh(x) };
2115var coth = function(x) { return 1/tanh(x) };
2116var arcsech = function(x) { return arccosh(1/x) };
2117var arccsch = function(x) { return arcsinh(1/x) };
2118var arccoth = function(x) { return arctanh(1/x) };
2119var sign = function(x) { return (x==0?0:(x<0?-1:1)) };
2121function factorial(x,n) { // Factorial function
2123 if (Math.abs(x-Math.round(x*1000000)/1000000)<1e-15)
2124 x = Math.round(x*1000000)/1000000;
2125 if (x-Math.floor(x)!=0) return NaN;
2126 for (var i=x-n; i>0; i-=n) x*=i;
2127 return (x<0?NaN:(x==0?1:x));
2130function C(x,k) { // Binomial coefficient function
2132 for (var i=0; i<k; i++) res*=(x-i)/(k-i);
2136function chop(x,n) { // Truncate decimal number to n places after decimal point
2138 return Math.floor(x*Math.pow(10,n))/Math.pow(10,n);
2141function ran(a,b,n) { // Generate random number in [a,b] with n digits after .
2143 return chop((b+Math.pow(10,-n)-a)*Math.random()+a,n);
2146function myCreateElementSVG(t) {
2147 if (isIE) return doc.createElement(t);
2148 else return doc.createElementNS("http://www.w3.org/2000/svg",t);
2151function getElementsByClass(container, tagName, clsName){
2152 var list = new Array(0);
2153 var collection = container.getElementsByTagName(tagName);
2154 for(var i = 0; i < collection.length; i++)
2155 if(collection[i].className.slice(0,clsName.length)==clsName)
2156 list[list.length] = collection[i];
2160function showobj(obj) {
2163 st += (obj.getAttribute(i)==null?"":" "+i+":"+obj.getAttribute(i));
2167function findPos(obj) { // top-left corner of obj on HTML page in pixel
2168 var curleft = curtop = 0;
2169 if (obj.offsetParent) {
2170 curleft = obj.offsetLeft
2171 curtop = obj.offsetTop
2172 while (obj = obj.offsetParent) {
2173 curleft += obj.offsetLeft
2174 curtop += obj.offsetTop
2175//alert(showobj(obj)+[curleft,curtop])
2178 return [curleft,curtop];
2182 if (navigator.appName.slice(0,8)=="Netscape")
2183 if (window['SVGElement']) noSVG = null;
2185 else if (navigator.appName.slice(0,9)=="Microsoft")
2187 var oSVG=eval("new ActiveXObject('Adobe.SVGCtl.3');");
2192 else if (navigator.appName.slice(0,5)=="Opera") // works only for 9.50b1
2195//noSVG = true; //uncomment to check
2196 if (noSVG && notifyIfNoSVG) {
2197 var msg = "To view the ASCIIsvg images use Internet Explorer + Adobe SVGviewer or Mozilla Firefox 2.0 or later."
2204function setText(st,id) { // add text to an existing node with given id
2205 var node = document.getElementById(id);
2207 if (node.childNodes.length!=0) node.childNodes[0].nodeValue = st;
2208 else node.appendChild(document.createTextNode(st));
2211function getX(evt) { // return mouse x-coord in user coordinate system
2212 var svgroot = evt.target.parentNode;
2213 pos = findPos(svgroot.parentNode);
2214 return (evt.clientX+(isIE?0:window.pageXOffset)-pos[0]-svgroot.getAttribute("ox"))/parseFloat(svgroot.getAttribute("xunitlength"));
2217function getY(evt) { // return mouse y-coord in user coordinate system
2218 var svgroot = evt.target.parentNode;
2219 pos = findPos(svgroot.parentNode);
2220//alert(showobj(svgroot)+svgroot.getAttribute("mytop"))
2221 return (svgroot.getAttribute("height")-svgroot.getAttribute("oy")-(evt.clientY+(isIE?0:window.pageYOffset)-pos[1]))/parseFloat(svgroot.getAttribute("yunitlength"));
2224function translateandeval(src) { //modify user input to JavaScript syntax
2226 // replace plot(f(x),...) with plot("f(x)",...)
2227 src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+?)\,/g,"plot\(\"$1\",");
2228 src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+)\)/g,"plot(\"$1\")");
2230 // replace (expr,expr) by [expr,expr] where expr has no (,) in it
2231 src = src.replace(/([=[(,]\x20*)\(([-a-z0-9./+*]+?),([-a-z0-9./+*]+?)\)/g,"$1[$2,$3]");
2233 // insert * between digit and letter e.g. 2x --> 2*x
2234 src = src.replace(/([0-9])([a-df-zA-Z]|e^)/g,"$1*$2");
2235 src = src.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1");
2238 with (Math) eval(src); // here the svgpicture object is created
2241//alert(dsvglocation)
2242 if (typeof err=="object")
2243 errstr = err.name+" "+err.message+" "+err.number+" "+err.description;
2245 alert(errstr+"\n"+src)
2252function drawPictures() { // main routine; called after webpage has loaded
2253 var src, id, dsvg, nd, node, ht, index, cols, arr, i, node2;
2254 var ASbody = document.getElementsByTagName("body")[0];
2255 pictures = getElementsByClass(ASbody,"embed","ASCIIsvg");
2256 var len = pictures.length;
2258 for (index = lastSlot; index < len+lastSlot; index++) {
2259 width = null; height = null;
2260 xmin = null; xmax = null; ymin = null; ymax = null;
2261 xscl = null; xgrid = null; yscl = null; ygrid = null;
2262 initialized = false;
2263 picture = pictures[index-lastSlot]; // current picture object
2264 src = picture.getAttribute("script"); // get the ASCIIsvg code
2265 if (src==null) src = "";
2266 // insert "axes()" if not present ******** experimental
2267 if (!/axes\b|initPicture/.test(src)) {
2269 while (/((yscl|ymax|ymin|xscl|xmax|xmin|\bwidth|\bheight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/.test(src.slice(i))) i++;
2270 src = (i==0?"axes(); "+src: src.slice(0,i)+src.slice(i).replace(/((scl|max|min|idth|eight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/,"$1\naxes();"));
2272 ht = picture.getAttribute("height");
2274 picture.setAttribute("wmode","transparent");
2275//alert("*"+picture.getAttribute("src")+dsvglocation);
2276//adding d.svg dynamically greates problems in IE...
2277// if (picture.getAttribute("src")=="") picture.setAttribute("src",dsvglocation+"d.svg");
2279 if (document.getElementById("picture"+(index+1)+"mml")==null) {
2280 picture.parentNode.style.position = "relative";
2281 node = createElementXHTML("div");
2282 node.style.position = "absolute";
2283 node.style.top = "0px";
2284 node.style.left = "0px";
2285 node.setAttribute("id","picture"+(index+1)+"mml");
2286 picture.parentNode.insertBefore(node,picture.nextSibling);
2288 if (ht==null) ht ="";
2289// if (ht!="") defaultborder = 25;
2290 if (ht=="" || src=="")
2291 if (document.getElementById("picture"+(index+1)+"input")==null) {
2292 node = createElementXHTML("textarea");
2293 arr = src.split("\n");
2295 for (i=0;i<arr.length;i++) cols = Math.max(cols,arr[i].length);
2296 node.setAttribute("rows",Math.min(10,arr.length)+1);
2297 node.setAttribute("cols",Math.max(Math.min(60,cols),20)+5);
2298// node.setAttribute("style","display:block");
2299 if (isIE) src = src.replace(/([^\r])\n/g,"$1\r");
2300 node.appendChild(document.createTextNode(src));
2301 if (src.indexOf("showcode()")==-1) node.style.display = "none";
2302 node.setAttribute("id","picture"+(index+1)+"input");
2303 picture.parentNode.insertBefore(node,picture.nextSibling);
2304 picture.parentNode.insertBefore(createElementXHTML("br"),node);
2305 node2 = createElementXHTML("button");
2306 node2.setAttribute("id","picture"+(index+1)+"button");
2307 if (isIE) node2.onclick = function() {updatePicture(this)};
2308 else node2.setAttribute("onclick","updatePicture(this)");
2309 node2.appendChild(document.createTextNode("Update"));
2310 if (src.indexOf("showcode()")==-1) node2.style.display = "none";
2311 picture.parentNode.insertBefore(node2,node);
2312// picture.parentNode.insertBefore(document.createTextNode("ASCII"),node);
2313 picture.parentNode.insertBefore(createElementXHTML("br"),node);
2314 } else src = document.getElementById("picture"+(index+1)+"input").value;
2315 id = picture.getAttribute("id");
2316 dsvg = picture.getAttribute("src");
2317 if (id == null || id == "") {
2318 id = "picture"+(index+1);
2319 picture.setAttribute("id",id);
2321 translateandeval(src);
2326function setdefaults() { //called before each graph is evaluated
2327 strokewidth = defaultstrokewidth;
2328 stroke = defaultstroke;
2329 strokeopacity = defaultstrokeopacity;
2330 strokedasharray = defaultstrokedasharray;
2332 fillopacity = defaultfillopacity;
2333 fontstyle = defaultfontstyle;
2334 fontfamily = defaultfontfamily;
2335 fontsize = defaultfontsize;
2336 fontweight = defaultfontweight;
2337 fontstroke = defaultfontstroke;
2338 fontfill = defaultfontfill;
2339 marker = defaultmarker;
2340 endpoints = defaultendpoints;
2343function switchTo(id) { // used by dynamic code to select appropriate graph
2344 if (id==undefined) return;
2346 if (typeof name!="string") name = id.target.parentNode.getAttribute("name");
2347 picture = document.getElementById(name);
2348 width = picture.getAttribute("width")-0;
2349 height = picture.getAttribute("height")-0;
2351 if ((picture.nodeName == "EMBED" || picture.nodeName == "embed") && isIE) {
2352 svgpicture = picture.getSVGDocument().getElementById("root");
2353 doc = picture.getSVGDocument();
2355 svgpicture = picture;
2358 xunitlength = parseFloat(svgpicture.getAttribute("xunitlength"));
2359 yunitlength = parseFloat(svgpicture.getAttribute("yunitlength"));
2360 xmin = parseFloat(svgpicture.getAttribute("xmin"));
2361 xmax = parseFloat(svgpicture.getAttribute("xmax"));
2362 ymin = parseFloat(svgpicture.getAttribute("ymin"));
2363 ymax = parseFloat(svgpicture.getAttribute("ymax"));
2364 origin = [svgpicture.getAttribute("ox")-0,svgpicture.getAttribute("oy")-0];
2367function updatePicture(obj) {
2368 var node, src, id, top, left;
2369 if (typeof obj=="object") id = obj.id.slice(0,-6);
2370 else id = (typeof obj=="string"?obj:"picture"+(obj+1));
2371 src = document.getElementById(id+"input").value;
2372 xmin = null; xmax = null; ymin = null; ymax = null;
2373 xscl = null; xgrid = null; yscl = null; ygrid = null;
2374 initialized = false;
2375 picture = document.getElementById(id);
2376 translateandeval(src)
2379function changepicturesize(evt,factor) {
2380 var obj = evt.target;
2381 var name = obj.parentNode.getAttribute("name");
2382 var pic = document.getElementById(name);
2383 var src = document.getElementById(name+"input").value;
2384 if (!/height/.test(src)) src = "height=0; "+src;
2385 if (!/width/.test(src)) src = "width=0; "+src;
2386 src = src.replace(/width\s*=\s*\d+/,"width="+(factor*(pic.getAttribute("width")-0)));
2387 src = src.replace(/height\s*=\s*\d+/,"height="+(factor*(pic.getAttribute("height")-0)));
2388 document.getElementById(name+"input").value = src;
2389//alert(getKey(evt.keycode))
2390 updatePicture(name);
2393function zoom(evt,factor) {
2395 var obj = evt.target;
2396 var name = obj.parentNode.getAttribute("name");
2397 var pic = document.getElementById(name);
2398 var src = document.getElementById(name+"input").value;
2399 var xlen = (xmax-xmin)/2;
2400 var ylen = (ymax-ymin)/2;
2401 var xcen = getX(evt), ycen = getY(evt);
2402 if (!/ymax/.test(src)) src = "ymax=0; "+src;
2403 if (!/ymin/.test(src)) src = "ymin=0; "+src;
2404 if (!/xmax/.test(src)) src = "xmax=0; "+src;
2405 if (!/xmin/.test(src)) src = "xmin=0; "+src;
2406 src = src.replace(/xmin\s*=\s*[-\d.e]+/,"xmin="+(xcen-factor*xlen));
2407 src = src.replace(/xmax\s*=\s*[-\d.e]+/,"xmax="+(xcen+factor*xlen));
2408 src = src.replace(/ymin\s*=\s*[-\d.e]+/,"ymin="+(ycen-factor*ylen));
2409 src = src.replace(/ymax\s*=\s*[-\d.e]+/,"ymax="+(ycen+factor*ylen));
2410 document.getElementById(name+"input").value = src;
2411 updatePicture(name);
2414var sinceFirstClick = 0; // ondblclick simulation from
2415var dblClkTimer; // http://www.enja.org/david/?cat=13 Thanks!
2417 if(sinceFirstClick<60) {
2419 setTimeout("timer()",10);
2421 clearTimeout(dblClkTimer);
2425function mClick(evt) {
2426 if(sinceFirstClick!=0) {
2427 if(sinceFirstClick <= 40) {
2429 if (evt.altKey) changepicturesize(evt,2);
2431 } else if (evt.altKey) zoom(evt,2);//changepicturesize(evt,.5);
2432 else showHideCode(evt); // do this on dblclick
2433 clearTimeout(dblClkTimer);
2436 clearTimeout(dblClkTimer);
2437 sinceFirstClick = 0;
2438 dblClkTimer = setTimeout("timer()",10);
2441 sinceFirstClick = 0;
2442 dblClkTimer = setTimeout("timer()",10);
2446function showHideCode(evt) { // called by onclick event
2447// if (evt.getDetail()==2) {//getDetail unfortunately not in Firefox
2449 var name = obj.parentNode.getAttribute("name");
2450 var node = document.getElementById(name+"input");
2451 node.style.display = (node.style.display == "none"?"":"none");
2452 var node = document.getElementById(name+"button");
2453 node.style.display = (node.style.display == "none"?"":"none");
2457function showcode() {} // do nothing
2459function setBorder(x) { border = x } //deprecate
2461function initPicture(x_min,x_max,y_min,y_max) { // set up the graph
2462// usually called by axes() or noaxes(), but can be used directly
2466 if (x_min!=null) xmin = x_min;
2467 if (x_max!=null) xmax = x_max;
2468 if (y_min!=null) ymin = y_min;
2469 if (y_max!=null) ymax = y_max;
2470 if (xmin==null) xmin = defaultxmin;
2471 if (xmax==null) xmax = defaultxmax;
2472 if (typeof xmin != "number" || typeof xmax != "number" || xmin >= xmax)
2473 alert("Picture requires at least two numbers: xmin < xmax");
2474 else if (y_max != null && (typeof y_min != "number" ||
2475 typeof y_max != "number" || y_min >= y_max))
2476 alert("initPicture(xmin,xmax,ymin,ymax) requires numbers ymin < ymax");
2479 width = picture.getAttribute("width");
2480 if (width==null || width=="") width=defaultwidth;
2482 picture.setAttribute("width",width);
2484 height = picture.getAttribute("height");
2485 if (height==null || height=="") height=defaultheight;
2487 picture.setAttribute("height",height);
2488 xunitlength = (width-2*border)/(xmax-xmin);
2489 yunitlength = xunitlength;
2490//alert(xmin+" "+xmax+" "+ymin+" "+ymax)
2492 origin = [-xmin*xunitlength+border,height/2];
2493 ymin = -(height-2*border)/(2*yunitlength);
2496 if (ymax!=null) yunitlength = (height-2*border)/(ymax-ymin);
2497 else ymax = (height-2*border)/yunitlength + ymin;
2498 origin = [-xmin*xunitlength+border,-ymin*yunitlength+border];
2501 if (picture.FULLSCREEN==undefined) {
2502 setTimeout('drawPictures()',50);
2505 svgpicture = picture.getSVGDocument().getElementById("root");
2506 if (svgpicture==null) {
2507 setTimeout('drawPictures()',50);
2510 svgpicture = picture.getSVGDocument().getElementById("root");
2511 while (svgpicture.childNodes.length>0)
2512 svgpicture.removeChild(svgpicture.lastChild);
2513 svgpicture.setAttribute("width",width);
2514 svgpicture.setAttribute("height",height);
2515 svgpicture.setAttribute("name",picture.getAttribute("id"));
2516 doc = picture.getSVGDocument();
2518 var qnode = document.createElementNS("http://www.w3.org/2000/svg","svg");
2519 qnode.setAttribute("id",picture.getAttribute("id"));
2520 qnode.setAttribute("name",picture.getAttribute("id"));
2521// qnode.setAttribute("style","display:inline");
2522 qnode.setAttribute("width",picture.getAttribute("width"));
2523 qnode.setAttribute("height",picture.getAttribute("height"));
2524 picturepos = findPos(picture);
2525// qnode.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");
2526 if (picture.parentNode!=null) {
2527 picture.parentNode.replaceChild(qnode,picture);
2529 svgpicture.parentNode.replaceChild(qnode,svgpicture);
2534 var nd = document.getElementById(picture.getAttribute("id")+"mml");
2535 if (nd!=null) // clear out MathML layer
2536 while (nd.childNodes.length>0) nd.removeChild(nd.lastChild);
2537 svgpicture.setAttribute("xunitlength",xunitlength);
2538 svgpicture.setAttribute("yunitlength",yunitlength);
2539 svgpicture.setAttribute("xmin",xmin);
2540 svgpicture.setAttribute("xmax",xmax);
2541 svgpicture.setAttribute("ymin",ymin);
2542 svgpicture.setAttribute("ymax",ymax);
2543 svgpicture.setAttribute("ox",origin[0]);
2544 svgpicture.setAttribute("oy",origin[1]);
2545 var node = myCreateElementSVG("rect");
2546 node.setAttribute("x","0");
2547 node.setAttribute("y","0");
2548 node.setAttribute("width",width);
2549 node.setAttribute("height",height);
2550 node.setAttribute("style",backgroundstyle);
2551 svgpicture.appendChild(node);
2552 svgpicture.setAttribute("onmousemove","displayCoord(evt)");
2553 svgpicture.setAttribute("onmouseout","removeCoord(evt)");
2554 svgpicture.setAttribute("onclick","mClick(evt)");
2555 node = myCreateElementSVG("text"); // used for displayCoord
2556 node.appendChild(doc.createTextNode(" "));
2557 node.setAttribute("id","coords");
2558 svgpicture.appendChild(node);
2559 node = myCreateElementSVG("text"); // used for text display
2560 node.appendChild(doc.createTextNode(" "));
2561 node.setAttribute("id","coords");
2562 svgpicture.appendChild(node);
2563 border = defaultborder;
2568//////////////////////////user graphics commands start/////////////////////////
2570function line(p,q,id,endpts) { // segment connecting points p,q (coordinates in units)
2572 if (id!=null) node = doc.getElementById(id);
2574 node = myCreateElementSVG("path");
2575 node.setAttribute("id", id);
2576 svgpicture.appendChild(node);
2578 node.setAttribute("d","M"+(p[0]*xunitlength+origin[0])+","+
2579 (height-p[1]*yunitlength-origin[1])+" "+
2580 (q[0]*xunitlength+origin[0])+","+(height-q[1]*yunitlength-origin[1]));
2581 node.setAttribute("stroke-width", strokewidth);
2582 if (strokedasharray!=null)
2583 node.setAttribute("stroke-dasharray", strokedasharray);
2584 node.setAttribute("stroke", stroke);
2585 node.setAttribute("fill", fill);
2586 node.setAttribute("stroke-opacity", strokeopacity);
2587 node.setAttribute("fill-opacity", fillopacity);
2588 if (marker=="dot" || marker=="arrowdot") {
2589 ASdot(p,markersize,markerstroke,markerfill);
2590 if (marker=="arrowdot") arrowhead(p,q);
2591 ASdot(q,markersize,markerstroke,markerfill);
2592 } else if (marker=="arrow") arrowhead(p,q);
2593 if (endpts==null && endpoints!="") endpts = endpoints;
2595 if (endpts.indexOf("<-") != -1) arrowhead(q,p);
2596 if (endpts.indexOf("o-") != -1) dot(p, "open");
2597 if (endpts.indexOf("*-") != -1) dot(p, "closed");
2598 if (endpts.indexOf("->") != -1) arrowhead(p,q);
2599 if (endpts.indexOf("-o") != -1) dot(q, "open");
2600 if (endpts.indexOf("-*") != -1) dot(q, "closed");
2604function path(plist,id,c,endpts) {
2607 if (id!=null) node = doc.getElementById(id);
2609 node = myCreateElementSVG("path");
2610 node.setAttribute("id", id);
2611 svgpicture.appendChild(node);
2613 if (typeof plist == "string") st = plist;
2616 st += (plist[0][0]*xunitlength+origin[0])+","+
2617 (height-plist[0][1]*yunitlength-origin[1])+" "+c;
2618 for (i=1; i<plist.length; i++)
2619 st += (plist[i][0]*xunitlength+origin[0])+","+
2620 (height-plist[i][1]*yunitlength-origin[1])+" ";
2622 node.setAttribute("d", st);
2623 node.setAttribute("stroke-width", strokewidth);
2624 if (strokedasharray!=null)
2625 node.setAttribute("stroke-dasharray", strokedasharray);
2626 node.setAttribute("stroke", stroke);
2627 node.setAttribute("fill", fill);
2628 node.setAttribute("stroke-opacity", strokeopacity);
2629 node.setAttribute("fill-opacity", fillopacity);
2630 if (marker=="dot" || marker=="arrowdot")
2631 for (i=0; i<plist.length; i++)
2632 if (c!="C" && c!="T" || i!=1 && i!=2)
2633 ASdot(plist[i],markersize,markerstroke,markerfill);
2634 if (endpts==null && endpoints!="") endpts = endpoints;
2636 if (endpts.indexOf("<-") != -1) arrowhead(plist[1],plist[0]);
2637 if (endpts.indexOf("o-") != -1) dot(plist[0], "open");
2638 if (endpts.indexOf("*-") != -1) dot(plist[0], "closed");
2639 if (endpts.indexOf("->") != -1) arrowhead(plist[plist.length-2],plist[plist.length-1]);
2640 if (endpts.indexOf("-o") != -1) dot(plist[plist.length-1], "open");
2641 if (endpts.indexOf("-*") != -1) dot(plist[plist.length-1], "closed");
2645function curve(plist,id,endpts) {
2646 path(plist,id,"T",endpts);
2649function vector(p,q,id) {
2650 line(p,q,id,"","->");
2653function circle(center,radius,id) { // coordinates in units
2655 if (id!=null) node = doc.getElementById(id);
2657 node = myCreateElementSVG("circle");
2658 node.setAttribute("id", id);
2659 svgpicture.appendChild(node);
2661 node.setAttribute("cx",center[0]*xunitlength+origin[0]);
2662 node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);
2663 node.setAttribute("r",radius*xunitlength);
2664 node.setAttribute("stroke-width", strokewidth);
2665 node.setAttribute("stroke", stroke);
2666 node.setAttribute("fill", fill);
2667 node.setAttribute("stroke-opacity", strokeopacity);
2668 node.setAttribute("fill-opacity", fillopacity);
2671function loop(p,d,id) {
2672// d is a direction vector e.g. [1,0] means loop starts in that direction
2673 if (d==null) d=[1,0];
2674 path([p,[p[0]+d[0],p[1]+d[1]],[p[0]-d[1],p[1]+d[0]],p],id,"C");
2675 if (marker=="arrow" || marker=="arrowdot")
2676 arrowhead([p[0]+Math.cos(1.4)*d[0]-Math.sin(1.4)*d[1],
2677 p[1]+Math.sin(1.4)*d[0]+Math.cos(1.4)*d[1]],p);
2680function arc(start,end,radius,id,largearc) { // coordinates in units
2682//alert([fill, stroke, origin, xunitlength, yunitlength, height])
2683 if (id!=null) node = doc.getElementById(id);
2684 if (largearc==null) largearc=0;
2686 v=[end[0]-start[0],end[1]-start[1]];
2687 radius = Math.sqrt(v[0]*v[0]+v[1]*v[1]);
2690 node = myCreateElementSVG("path");
2691 node.setAttribute("id", id);
2692 svgpicture.appendChild(node);
2694 node.setAttribute("d","M"+(start[0]*xunitlength+origin[0])+","+
2695 (height-start[1]*yunitlength-origin[1])+" A"+radius*xunitlength+","+
2696 radius*yunitlength+" 0 "+largearc+",0 "+(end[0]*xunitlength+origin[0])+","+
2697 (height-end[1]*yunitlength-origin[1]));
2698 node.setAttribute("stroke-width", strokewidth);
2699 node.setAttribute("stroke", stroke);
2700 node.setAttribute("fill", fill);
2701 node.setAttribute("stroke-opacity", strokeopacity);
2702 node.setAttribute("fill-opacity", fillopacity);
2703 if (marker=="arrow" || marker=="arrowdot") {
2704 u = [(end[1]-start[1])/4,(start[0]-end[0])/4];
2705 v = [(end[0]-start[0])/2,(end[1]-start[1])/2];
2707 v = [start[0]+v[0]+u[0],start[1]+v[1]+u[1]];
2708 } else v=[start[0],start[1]];
2709 if (marker=="dot" || marker=="arrowdot") {
2710 ASdot(start,markersize,markerstroke,markerfill);
2711 if (marker=="arrowdot") arrowhead(v,end);
2712 ASdot(end,markersize,markerstroke,markerfill);
2713 } else if (marker=="arrow") arrowhead(v,end);
2716function sector(center,start,end,id) { // center,start,end should be isoceles
2717 var rx = start[0]-center[0], ry = start[1]-center[1];
2718 arc(start,end,Math.sqrt(rx*rx+ry*ry),id+"arc");
2719 path([end,center,start],id+"path");
2722function ellipse(center,rx,ry,id) { // coordinates in units
2724 if (id!=null) node = doc.getElementById(id);
2726 node = myCreateElementSVG("ellipse");
2727 node.setAttribute("id", id);
2728 svgpicture.appendChild(node);
2730 node.setAttribute("cx",center[0]*xunitlength+origin[0]);
2731 node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);
2732 node.setAttribute("rx",rx*xunitlength);
2733 node.setAttribute("ry",ry*yunitlength);
2734 node.setAttribute("stroke-width", strokewidth);
2735 node.setAttribute("stroke", stroke);
2736 node.setAttribute("fill", fill);
2737 node.setAttribute("stroke-opacity", strokeopacity);
2738 node.setAttribute("fill-opacity", fillopacity);
2741function triangle(p,q,r,id) {
2745function rect(p,q,id,rx,ry) { // opposite corners in units, rounded by radii
2747 if (id!=null) node = doc.getElementById(id);
2749 node = myCreateElementSVG("rect");
2750 node.setAttribute("id", id);
2751 svgpicture.appendChild(node);
2753 node.setAttribute("x",p[0]*xunitlength+origin[0]);
2754 node.setAttribute("y",height-q[1]*yunitlength-origin[1]);
2755 node.setAttribute("width",(q[0]-p[0])*xunitlength);
2756 node.setAttribute("height",(q[1]-p[1])*yunitlength);
2757 if (rx!=null) node.setAttribute("rx",rx*xunitlength);
2758 if (ry!=null) node.setAttribute("ry",ry*yunitlength);
2759 node.setAttribute("stroke-width", strokewidth);
2760 node.setAttribute("stroke", stroke);
2761 node.setAttribute("fill", fill);
2762 node.setAttribute("stroke-opacity", strokeopacity);
2763 node.setAttribute("fill-opacity", fillopacity);
2766function text(p,st,pos,id,fontsty) {
2767 var dnode, node, dx = 0, dy = fontsize/3, str = st.toString();
2768 if (/(`|\$)/.test(str)) { // layer for ASCIIMathML and LaTeXMathML
2769 dnode = document.getElementById(svgpicture.getAttribute("name")+"mml");
2771 if (id!=null) node = document.getElementById(id);
2773//alert(dnode.childNodes.length)
2774 node = createElementXHTML("div");
2775 node.setAttribute("id", id);
2776 node.style.position = "absolute";
2777 dnode.appendChild(node);
2779 while (node.childNodes.length>0) node.removeChild(node.lastChild);
2780 node.appendChild(document.createTextNode(str));
2781 if (/`/.test(str)) AMprocessNode(node); else LMprocessNode(node);
2782 dx = -node.offsetWidth/2;
2783 dy = -node.offsetHeight/2;
2785 if (/above/.test(pos)) dy = -node.offsetHeight;
2786 if (/below/.test(pos)) dy = 0;
2787 if (/right/.test(pos)) dx = 0;
2788 if ( /left/.test(pos)) dx = -node.offsetWidth;
2790 node.style.left = ""+(p[0]*xunitlength+origin[0]+dx)+"px";
2791 node.style.top = ""+(height-p[1]*yunitlength-origin[1]+dy)+"px";
2795 var textanchor = "middle"; // regular text goes into SVG
2797 if (/above/.test(pos)) dy = -fontsize/2;
2798 if (/below/.test(pos)) dy = fontsize-0;
2799 if (/right/.test(pos)) {textanchor = "start"; dx = fontsize/4;}
2800 if ( /left/.test(pos)) {textanchor = "end"; dx = -fontsize/4;}
2802 if (id!=null) node = doc.getElementById(id);
2804 node = myCreateElementSVG("text");
2805 node.setAttribute("id", id);
2806 svgpicture.appendChild(node);
2807 node.appendChild(doc.createTextNode(str));
2809 while (node.childNodes.length>1) node.removeChild(node.lastChild);
2810 node.lastChild.nodeValue = "\xA0"+str+"\xA0";
2811 node.setAttribute("x",p[0]*xunitlength+origin[0]+dx);
2812 node.setAttribute("y",height-p[1]*yunitlength-origin[1]+dy);
2813 node.setAttribute("font-style",(fontsty!=null?fontsty:
2814 (str.search(/^[a-zA-Z]$/)!=-1?"italic":fontstyle)));
2815 node.setAttribute("font-family",fontfamily);
2816 node.setAttribute("font-size",fontsize);
2817 node.setAttribute("font-weight",fontweight);
2818 node.setAttribute("text-anchor",textanchor);
2819 if (fontstroke!="none") node.setAttribute("stroke",fontstroke);
2820 if (fontfill!="none") node.setAttribute("fill",fontfill);
2824function mtext(p,st,pos,fontsty,fontsz) { // method for updating text on an svg
2825// "this" is the text object or the svgpicture object
2826 var textanchor = "middle";
2827 var dx = 0; var dy = fontsize/3;
2829 if (pos.slice(0,5)=="above") dy = -fontsize/2;
2830 if (pos.slice(0,5)=="below") dy = fontsize-0;
2831 if (pos.slice(0,5)=="right" || pos.slice(5,10)=="right") {
2832 textanchor = "start";
2835 if (pos.slice(0,4)=="left" || pos.slice(5,9)=="left") {
2841 if (this.nodeName=="svg") {
2842 node = myCreateElementSVG("text");
2843 this.appendChild(node);
2844 node.appendChild(doc.createTextNode(st));
2846 node.lastChild.nodeValue = st;
2847 node.setAttribute("x",p[0]+dx);
2848 node.setAttribute("y",p[1]+dy);
2849 node.setAttribute("font-style",(fontsty!=null?fontsty:fontstyle));
2850 node.setAttribute("font-family",fontfamily);
2851 node.setAttribute("font-size",(fontsz!=null?fontsz:fontsize));
2852 node.setAttribute("font-weight",fontweight);
2853 node.setAttribute("text-anchor",textanchor);
2854 if (fontstroke!="none") node.setAttribute("stroke",fontstroke);
2855 if (fontfill!="none") node.setAttribute("fill",fontfill);
2858function image(imgurl,p,w,h,id) { // not working yet
2860 if (id!=null) node = doc.getElementById(id);
2862 node = myCreateElementSVG("image");
2863 node.setAttribute("id", id);
2864 svgpicture.appendChild(node);
2866 node.setAttribute("x",p[0]*xunitlength+origin[0]);
2867 node.setAttribute("y",height-p[1]*yunitlength-origin[1]);
2868 node.setAttribute("width",w);
2869 node.setAttribute("height",h);
2870 node.setAttribute("xlink:href", imgurl);
2873function ASdot(center,radius,s,f) { // coordinates in units, radius in pixel
2874 if (s==null) s = stroke; if (f==null) f = fill;
2875 var node = myCreateElementSVG("circle");
2876 node.setAttribute("cx",center[0]*xunitlength+origin[0]);
2877 node.setAttribute("cy",height-center[1]*yunitlength-origin[1]);
2878 node.setAttribute("r",radius);
2879 node.setAttribute("stroke-width", strokewidth);
2880 node.setAttribute("stroke", s);
2881 node.setAttribute("fill", f);
2882 svgpicture.appendChild(node);
2885function dot(center, typ, label, pos, id) {
2887 var cx = center[0]*xunitlength+origin[0];
2888 var cy = height-center[1]*yunitlength-origin[1];
2889 if (id!=null) node = doc.getElementById(id);
2890 if (typ=="+" || typ=="-" || typ=="|") {
2892 node = myCreateElementSVG("path");
2893 node.setAttribute("id", id);
2894 svgpicture.appendChild(node);
2897 node.setAttribute("d",
2898 " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy+
2899 " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength));
2900 node.setAttribute("stroke-width", .5);
2901 node.setAttribute("stroke", axesstroke);
2903 if (typ=="-") node.setAttribute("d",
2904 " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy);
2905 else node.setAttribute("d",
2906 " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength));
2907 node.setAttribute("stroke-width", strokewidth);
2908 node.setAttribute("stroke", stroke);
2912 node = myCreateElementSVG("circle");
2913 node.setAttribute("id", id);
2914 svgpicture.appendChild(node);
2916 node.setAttribute("cx",cx);
2917 node.setAttribute("cy",cy);
2918 node.setAttribute("r",dotradius);
2919 node.setAttribute("stroke-width", strokewidth);
2920 node.setAttribute("stroke", stroke);
2921 node.setAttribute("fill", (typ=="open"?"white":
2922 (typ=="closed"?stroke:markerfill)));
2925 text(center,label,(pos==null?"below":pos),(id==null?id:id+"label"))
2928point = dot; //alternative name
2930function arrowhead(p,q) { // draw arrowhead at q (in units) add size param
2932 var v = [p[0]*xunitlength+origin[0],height-p[1]*yunitlength-origin[1]];
2933 var w = [q[0]*xunitlength+origin[0],height-q[1]*yunitlength-origin[1]];
2934 var u = [w[0]-v[0],w[1]-v[1]];
2935 var d = Math.sqrt(u[0]*u[0]+u[1]*u[1]);
2936 if (d > 0.00000001) {
2937 u = [u[0]/d, u[1]/d];
2939 var node = myCreateElementSVG("path");
2940 node.setAttribute("d","M "+(w[0]-15*u[0]-4*up[0])+" "+
2941 (w[1]-15*u[1]-4*up[1])+" L "+(w[0]-3*u[0])+" "+(w[1]-3*u[1])+" L "+
2942 (w[0]-15*u[0]+4*up[0])+" "+(w[1]-15*u[1]+4*up[1])+" z");
2943 node.setAttribute("stroke-width", markerstrokewidth);
2944 node.setAttribute("stroke", stroke); /*was markerstroke*/
2945 node.setAttribute("fill", stroke); /*was arrowfill*/
2946 node.setAttribute("stroke-opacity", strokeopacity);
2947 node.setAttribute("fill-opacity", fillopacity);
2948 svgpicture.appendChild(node);
2953 var k = st.indexOf(".");
2954 if (k==-1) return st;
2955 for (var i=st.length-1; i>k && st.charAt(i)=="0"; i--);
2957 return st.slice(0,i+1);
2960function grid(dx,dy) { // for backward compatibility
2961 axes(dx,dy,null,dx,dy)
2965 if (!initialized) initPicture();
2968function axes(dx,dy,labels,gdx,gdy) {
2969//xscl=x is equivalent to xtick=x; xgrid=x; labels=true;
2970 var x, y, ldx, ldy, lx, ly, lxp, lyp, pnode, st;
2971 if (!initialized) initPicture();
2972 if (typeof dx=="string") { labels = dx; dx = null; }
2973 if (typeof dy=="string") { gdx = dy; dy = null; }
2974 if (xscl!=null) {dx = xscl; gdx = xscl; labels = dx}
2975 if (yscl!=null) {dy = yscl; gdy = yscl}
2976 if (xtick!=null) {dx = xtick}
2977 if (ytick!=null) {dy = ytick}
2978 dx = (dx==null?xunitlength:dx*xunitlength);
2979 dy = (dy==null?dx:dy*yunitlength);
2980 fontsize = Math.min(dx/2,dy/2,16); //alert(fontsize)
2981 ticklength = fontsize/4;
2982 if (xgrid!=null) gdx = xgrid;
2983 if (ygrid!=null) gdy = ygrid;
2985 gdx = (typeof gdx=="string"?dx:gdx*xunitlength);
2986 gdy = (gdy==null?dy:gdy*yunitlength);
2987 pnode = myCreateElementSVG("path");
2989 for (x = origin[0]; x<width; x = x+gdx)
2990 st += " M"+x+",0"+" "+x+","+height;
2991 for (x = origin[0]-gdx; x>0; x = x-gdx)
2992 st += " M"+x+",0"+" "+x+","+height;
2993 for (y = height-origin[1]; y<height; y = y+gdy)
2994 st += " M0,"+y+" "+width+","+y;
2995 for (y = height-origin[1]-gdy; y>0; y = y-gdy)
2996 st += " M0,"+y+" "+width+","+y;
2997 pnode.setAttribute("d",st);
2998 pnode.setAttribute("stroke-width", .5);
2999 pnode.setAttribute("stroke", gridstroke);
3000 pnode.setAttribute("fill", fill);
3001 svgpicture.appendChild(pnode);
3003 pnode = myCreateElementSVG("path");
3004 st="M0,"+(height-origin[1])+" "+width+","+
3005 (height-origin[1])+" M"+origin[0]+",0 "+origin[0]+","+height;
3006 for (x = origin[0]+dx; x<width; x = x+dx)
3007 st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","+
3008 (height-origin[1]-ticklength);
3009 for (x = origin[0]-dx; x>0; x = x-dx)
3010 st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","+
3011 (height-origin[1]-ticklength);
3012 for (y = height-origin[1]+dy; y<height; y = y+dy)
3013 st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y;
3014 for (y = height-origin[1]-dy; y>0; y = y-dy)
3015 st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y;
3016 if (labels!=null) with (Math) {
3017 ldx = dx/xunitlength;
3018 ldy = dy/yunitlength;
3019 lx = (xmin>0 || xmax<0?xmin:0);
3020 ly = (ymin>0 || ymax<0?ymin:0);
3021 lxp = (ly==0?"below":"above");
3022 lyp = (lx==0?"left":"right");
3023 var ddx = floor(1.1-log(ldx)/log(10))+1;
3024 var ddy = floor(1.1-log(ldy)/log(10))+1;
3025 for (x = ldx; x<=xmax; x = x+ldx)
3026 text([x,ly],chopZ(x.toFixed(ddx)),lxp);
3027 for (x = -ldx; xmin<=x; x = x-ldx)
3028 text([x,ly],chopZ(x.toFixed(ddx)),lxp);
3029 for (y = ldy; y<=ymax; y = y+ldy)
3030 text([lx,y],chopZ(y.toFixed(ddy)),lyp);
3031 for (y = -ldy; ymin<=y; y = y-ldy)
3032 text([lx,y],chopZ(y.toFixed(ddy)),lyp);
3034 fontsize = defaultfontsize;
3035 pnode.setAttribute("d",st);
3036 pnode.setAttribute("stroke-width", .5);
3037 pnode.setAttribute("stroke", axesstroke);
3038 pnode.setAttribute("fill", fill);
3039 pnode.setAttribute("stroke-opacity", strokeopacity);
3040 pnode.setAttribute("fill-opacity", fillopacity);
3041 svgpicture.appendChild(pnode);
3044function mathjs(st) {
3045 //translate a math formula to js function notation
3048 // (...)d --> (...)*d
3049 // n! --> factorial(n)
3050 // sin^-1 --> arcsin etc.
3051 //while ^ in string, find term on left and right
3052 //slice and concat new formula string
3053 st = st.replace(/\s/g,"");
3054 if (st.indexOf("^-1")!=-1) {
3055 st = st.replace(/sin\^-1/g,"arcsin");
3056 st = st.replace(/cos\^-1/g,"arccos");
3057 st = st.replace(/tan\^-1/g,"arctan");
3058 st = st.replace(/sec\^-1/g,"arcsec");
3059 st = st.replace(/csc\^-1/g,"arccsc");
3060 st = st.replace(/cot\^-1/g,"arccot");
3061 st = st.replace(/sinh\^-1/g,"arcsinh");
3062 st = st.replace(/cosh\^-1/g,"arccosh");
3063 st = st.replace(/tanh\^-1/g,"arctanh");
3064 st = st.replace(/sech\^-1/g,"arcsech");
3065 st = st.replace(/csch\^-1/g,"arccsch");
3066 st = st.replace(/coth\^-1/g,"arccoth");
3068 st = st.replace(/^e$/g,"(Math.E)");
3069 st = st.replace(/^e([^a-zA-Z])/g,"(Math.E)$1");
3070 st = st.replace(/([^a-zA-Z])e/g,"$1(Math.E)");
3071// st = st.replace(/([^a-zA-Z])e([^a-zA-Z])/g,"$1(Math.E)$2");
3072 st = st.replace(/([0-9])([\(a-zA-Z])/g,"$1*$2");
3073 st = st.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1");
3074 var i,j,k, ch, nested;
3075 while ((i=st.indexOf("^"))!=-1) {
3076 //find left argument
3077 if (i==0) return "Error: missing argument";
3080 if (ch>="0" && ch<="9") {// look for (decimal) number
3082 while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;
3085 while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;
3087 } else if (ch==")") {// look for matching opening bracket and function name
3090 while (j>=0 && nested>0) {
3092 if (ch=="(") nested--;
3093 else if (ch==")") nested++;
3096 while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")
3098 } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable
3100 while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")
3103 return "Error: incorrect syntax in "+st+" at position "+j;
3105 //find right argument
3106 if (i==st.length-1) return "Error: missing argument";
3109 if (ch>="0" && ch<="9" || ch=="-") {// look for signed (decimal) number
3111 while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++;
3114 while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++;
3116 } else if (ch=="(") {// look for matching closing bracket and function name
3119 while (k<st.length && nested>0) {
3121 if (ch=="(") nested++;
3122 else if (ch==")") nested--;
3125 } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable
3127 while (k<st.length && (ch=st.charAt(k))>="a" && ch<="z" ||
3128 ch>="A" && ch<="Z") k++;
3130 return "Error: incorrect syntax in "+st+" at position "+k;
3132 st = st.slice(0,j+1)+"Math.pow("+st.slice(j+1,i)+","+st.slice(i+1,k)+")"+
3135 while ((i=st.indexOf("!"))!=-1) {
3136 //find left argument
3137 if (i==0) return "Error: missing argument";
3140 if (ch>="0" && ch<="9") {// look for (decimal) number
3142 while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;
3145 while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--;
3147 } else if (ch==")") {// look for matching opening bracket and function name
3150 while (j>=0 && nested>0) {
3152 if (ch=="(") nested--;
3153 else if (ch==")") nested++;
3156 while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")
3158 } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable
3160 while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z")
3163 return "Error: incorrect syntax in "+st+" at position "+j;
3165 st = st.slice(0,j+1)+"factorial("+st.slice(j+1,i)+")"+st.slice(i+1);
3170function plot(fun,x_min,x_max,points,id,endpts) {
3172 var f = function(x) { return x }, g = fun;
3174 if (typeof fun=="string")
3175 eval("g = function(x){ with(Math) return "+mathjs(fun)+" }");
3176 else if (typeof fun=="object") {
3177 eval("f = function(t){ with(Math) return "+mathjs(fun[0])+" }");
3178 eval("g = function(t){ with(Math) return "+mathjs(fun[1])+" }");
3180 if (typeof x_min=="string") { name = x_min; x_min = xmin }
3182 var min = (x_min==null?xmin:x_min);
3183 var max = (x_max==null?xmax:x_max);
3184 var inc = max-min-0.000001*(max-min);
3185 inc = (points==null?inc/200:inc/points);
3187//alert(typeof g(min))
3188 for (var t = min; t <= max; t += inc) {
3190 if (!(isNaN(gt)||Math.abs(gt)=="Infinity")) pth[pth.length] = [f(t), gt];
3192 path(pth,name,null,endpts);
3200function slopefield(fun,dx,dy) {
3202 if (typeof fun=="string")
3203 eval("g = function(x,y){ with(Math) return "+mathjs(fun)+" }");
3207 dz = Math.sqrt(dx*dx+dy*dy)/6;
3208 var x_min = Math.ceil(xmin/dx);
3209 var y_min = Math.ceil(ymin/dy);
3210 for (x = x_min; x <= xmax; x += dx)
3211 for (y = y_min; y <= ymax; y += dy) {
3214 if (Math.abs(gxy)=="Infinity") {u = 0; v = dz;}
3215 else {u = dz/Math.sqrt(1+gxy*gxy); v = gxy*u;}
3216 line([x-u,y-v],[x+u,y+v]);
3221///////////////////////user graphics commands end here/////////////////////////
3223function show_props(obj) {
3225 for (var i=0; i< obj.childNodes.length; i++)
3226 result += obj.childNodes.item(i) + "\n";
3230function displayCoord(evt) {
3231 if (showcoordinates) {
3232 var svgroot = evt.target.parentNode;
3233 var nl = svgroot.childNodes;
3234 for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++);
3235 var cnode = nl.item(i);
3236 cnode.mtext = mtext;
3237 cnode.mtext([svgroot.getAttribute("width")-(-7),svgroot.getAttribute("height")-7],"("+getX(evt).toFixed(2)+", "+getY(evt).toFixed(2)+")", "left", "", "11");
3238/* var dnode = nl.item(i+1);
3239 dnode.mtext = mtext;
3240 dnode.mtext([0,svgroot.getAttribute("height")-6],"Try (shift/alt)-dblclick", "right", "", "8");
3244function removeCoord(evt) {
3245 var svgroot = evt.target.parentNode;
3246 var nl = svgroot.childNodes;
3247 for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++);
3248 var cnode = nl.item(i);
3249 cnode.mtext = mtext;
3250 cnode.mtext([svgroot.getAttribute("width")-0,svgroot.getAttribute("height")-0],"", "aboveleft", "");
3251/* var dnode = nl.item(i+1);
3252 dnode.mtext = mtext;
3253 dnode.mtext([0,svgroot.getAttribute("height")-0],"", "aboveright", "");
3256function initASCIIMathCalculators(li) {
3258 for (i=0; i<li.length; i++) {
3259 li[i].innerHTML = calcstr;
3260 AMprocessNode(li[i]);
3262 li = document.getElementsByTagName("textarea");
3264 for (i=0; i<li.length; i++) {
3265 st = li[i].getAttribute("onkeyup");
3266 if (st!=null) eval(String(st).replace(/function anonymous\(\)/,""));
3270function calculate(inputId,outputId) {
3271 var str = document.getElementById(inputId).value;
3273 var ind = str.lastIndexOf("\n");
3274 if (ind==str.length-1) str = str.slice(0,ind);
3275 str = str.slice(str.lastIndexOf("\n")+1);
3277 var res = eval(mathjs(str));
3279 err = "syntax incomplete";
3281 if (!isNaN(res) && res!="Infinity")
3282 str = "`"+str+" =` "+(Math.abs(res-Math.round(res*1000000)/1000000)<1e-15?Math.round(res*1000000)/1000000:res)+err;
3283 else if (str!="") str = "`"+str+"` = undefined"; //debug:+mathjs(str);
3284 var outnode = document.getElementById(outputId);
3285 var n = outnode.childNodes.length;
3286 for (var i=0; i<n; i++)
3287 outnode.removeChild(outnode.firstChild);
3288 outnode.appendChild(document.createTextNode(str));
3289 AMprocessNode(outnode);
3293 document.getElementById('in').value+=st;
3294 calculate('in','out');
3295 document.getElementById('in').scrollTop = 1000;
3296 document.getElementById('in').focus();
3299function clearTextArea(){
3300 document.getElementById('in').value="";
3301 calculate('in','out');
3302 document.getElementById('in').focus();
3305var calcstr = "<table align=\"center\">\n<tr><th>\nASCIIMath Scientific Calculator\n</th></tr>\n<tr><td>\nClick in the box to use your keyboard or use the buttons\n</td></tr>\n<tr><td>\n<textarea id=\"in\" rows=\"3\" cols=\"40\" onkeyup=\"calculate('in','out')\"></textarea></td></tr>\n<tr><td height=\"50\">Result: <span id=\"out\"></span></td></tr>\n</table>\n<table align=\"center\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody align=\"center\">\n<tr>\n<td colspan=\"4\">\n<button onclick=\"append('sin^-1(')\"><font size=2>`sin^-1`</font></button><button onclick=\"append('cos^-1(')\"><font size=2>`cos^-1`</font></button><button onclick=\"append('tan^-1(')\"><font size=2>`tan^-1`</font></button></td>\n<td><button onclick=\"clearTextArea()\"> `C` </button></td>\n\n</tr>\n<tr>\n<td><button onclick=\"append('pi')\"> `pi` </button></td>\n<td><button onclick=\"append('sin(')\"> `sin`</button></td>\n<td><button onclick=\"append('cos(')\"> `cos`</button></td>\n<td><button onclick=\"append('tan(')\"> `tan`</button></td>\n<td><button onclick=\"append('^')\">`x^y`</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('!')\"> `!` </button></td>\n\n<td><button onclick=\"append('(')\"><font size=2> `(` </font></button></td>\n<td><button onclick=\"append(')')\"><font size=2> `)` </font></button></td>\n<td><button onclick=\"append('sqrt(')\"><font size=2>`sqrt({::}^\ )`</font></button></td>\n<td><button onclick=\"append('/')\"> `-:\ `</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('log(')\">`log`</button></td>\n<td><button onclick=\"append('7')\"> `7` </button></td>\n<td><button onclick=\"append('8')\"> `8` </button></td>\n\n<td><button onclick=\"append('9')\"> `9` </button></td>\n<td><button onclick=\"append('*')\"> `times` </button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('ln(')\"> `ln` </button></td>\n<td><button onclick=\"append('4')\"> `4` </button></td>\n<td><button onclick=\"append('5')\"> `5` </button></td>\n<td><button onclick=\"append('6')\"> `6` </button></td>\n\n<td><button onclick=\"append('-')\"> `-{::}` </button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('e')\"> `e` </button></td>\n<td><button onclick=\"append('1')\"> `1` </button></td>\n<td><button onclick=\"append('2')\"> `2` </button></td>\n<td><button onclick=\"append('3')\"> `3` </button></td>\n<td><button onclick=\"append('+')\"> `+{::}` </button></td>\n\n</tr>\n<tr>\n<td> <!--button onclick=\"append('pi')\"> `pi` </button--></td>\n<td><button onclick=\"append('0')\"> `0` </button></td>\n<td><button onclick=\"append('.')\"> `.` </button></td>\n<td><button onclick=\"append('\\n')\"> `\"ent\"`</button></td>\n</tr>\n</tbody>\n</table>";
3307// GO1.1 Generic onload by Brothercake
3308// http://www.brothercake.com/
3309//onload function (replaces the onload="translate()" in the <body> tag)
3313 if (translateOnLoad) {
3314 var nd = document.getElementById("processasciimathinmoodle");
3315 if (nd!=null) dsvglocation = nd.className;
3316 if (nd!=null || !checkforprocessasciimathinmoodle) {
3318 if (!noSVG && translateASCIIsvg) drawPictures();
3320 var li = getElementsByClass(document,"div","ASCIIMathCalculator");
3321 if (!noMathML && li.length>0) initASCIIMathCalculators(li);
3324//setup onload function
3325if(typeof window.addEventListener != 'undefined')
3327 //.. gecko, safari, konqueror and standard
3328 window.addEventListener('load', generic, false);
3330else if(typeof document.addEventListener != 'undefined')
3333 document.addEventListener('load', generic, false);
3335else if(typeof window.attachEvent != 'undefined')
3338 window.attachEvent('onload', generic);
3340//** remove this condition to degrade older browsers
3343 //.. mac/ie5 and anything else that gets this far
3344 //if there's an existing onload function
3345 if(typeof window.onload == 'function')
3348 var existing = onload;
3349 //add new onload handler
3350 window.onload = function()
3352 //call existing onload function
3354 //call generic onload function
3360 //setup onload function
3361 window.onload = generic;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list