git.iko.soy/typeable/pandoc
on 4eec413 help sign in
typeable/pandoc/src/ASCIIMathML.js
945 lines 43 kB history raw
1/*
2ASCIIMathML.js
3==============
4This file contains JavaScript functions to convert ASCII math notation
5to Presentation MathML. The conversion is done while the (X)HTML page
6loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet
7Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/).
8Just add the next line to your (X)HTML page with this file in the same folder:
9<script type="text/javascript" src="ASCIIMathML.js"></script>
10This is a convenient and inexpensive solution for authoring MathML.
12Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen
13Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js
14For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt
15If you use it on a webpage, please send the URL to jipsen@chapman.edu
17Modified July 2006 by John MacFarlane (added CODE to list of contexts
18in which replacement does not occur, modified AMisMathMLAvailable
19to better identify Safari browser).
21This program is free software; you can redistribute it and/or modify
22it under the terms of the GNU General Public License as published by
23the Free Software Foundation; either version 2 of the License, or (at
24your option) any later version.
26This program is distributed in the hope that it will be useful,
27but WITHOUT ANY WARRANTY; without even the implied warranty of
28MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29General Public License (at http://www.gnu.org/copyleft/gpl.html)
30for more details.
31*/
33var checkForMathML = true; // check if browser can display MathML
34var notifyIfNoMathML = true; // display note if no MathML capability
35var alertIfNoMathML = false; // show alert box if no MathML capability
36var mathcolor = "red"; // change it to "" (to inherit) or any other color
37var mathfontfamily = "serif"; // change to "" to inherit (works in IE)
38 // or another family (e.g. "arial")
39var displaystyle = true; // puts limits above and below large operators
40var showasciiformulaonhover = true; // helps students learn ASCIIMath
41var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!
42var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
43var AMdelimiter2 = "$", AMescape2 = "\\\\\\$", AMdelimiter2regexp = "\\$";
44var doubleblankmathdelimiter = false; // if true, x+1 is equal to `x+1`
45 // for IE this works only in <!-- -->
46//var separatetokens;// has been removed (email me if this is a problem)
47var isIE = document.createElementNS==null;
49if (document.getElementById==null)
50 alert("This webpage requires a recent browser such as\
51\nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")
53// all further global variables start with "AM"
55function AMcreateElementXHTML(t) {
56 if (isIE) return document.createElement(t);
57 else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
60function AMnoMathMLNote() {
61 var nd = AMcreateElementXHTML("h3");
62 nd.setAttribute("align","center")
63 nd.appendChild(AMcreateElementXHTML("p"));
64 nd.appendChild(document.createTextNode("To view the "));
65 var an = AMcreateElementXHTML("a");
66 an.appendChild(document.createTextNode("ASCIIMathML"));
67 an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");
68 nd.appendChild(an);
69 nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));
70 an = AMcreateElementXHTML("a");
71 an.appendChild(document.createTextNode("MathPlayer"));
72 an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");
73 nd.appendChild(an);
74 nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));
75 nd.appendChild(AMcreateElementXHTML("p"));
76 return nd;
79function AMisMathMLavailable() {
80 var regex = /KHTML/; /* This line and the next two modified by JM for better Safari detection */
81 if (navigator.appName.slice(0,8)=="Netscape")
82 if (navigator.appVersion.slice(0,1)>="5" && !regex.test(navigator.userAgent)) return null;
83 else return AMnoMathMLNote();
84 else if (navigator.appName.slice(0,9)=="Microsoft")
85 try {
86 var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
87 return null;
88 } catch (e) {
89 return AMnoMathMLNote();
90 }
91 else return AMnoMathMLNote();
94// character lists for Mozilla/Netscape fonts
95var 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];
96var 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];
97var 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];
99var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
100 RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
101 LEFTRIGHT = 9, TEXT = 10; // token types
103var AMsqrt = {input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},
104 AMroot = {input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},
105 AMfrac = {input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},
106 AMdiv = {input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},
107 AMover = {input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
108 AMsub = {input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},
109 AMsup = {input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},
110 AMtext = {input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},
111 AMmbox = {input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},
112 AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};
114var AMsymbols = [
115//some greek symbols
116{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},
117{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},
118{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},
119{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},
120{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},
121{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},
122{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},
123{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},
124{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},
125{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},
126{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},
127{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},
128{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
129{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
130{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},
131{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},
132{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},
133{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},
134{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},
135{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},
136{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},
137{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},
138{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},
139{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},
140{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},
141{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},
142{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},
143{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},
144{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},
145{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},
146{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},
147{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},
148{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},
149{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},
150{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},
151{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},
153//binary operation symbols
154{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},
155{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},
156{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},
157{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},
158{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},
159{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},
160{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},
161{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},
162{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},
163{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},
164{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},
165{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},
166{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},
167{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},
168{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},
169{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},
170{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},
171{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},
172{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},
173{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},
174{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},
176//binary relation symbols
177{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},
178{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},
179{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},
180{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},
181{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},
182{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},
183{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},
184{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},
185{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},
186{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},
187{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},
188{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},
189{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},
190{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},
191{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},
192{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},
193{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},
194{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},
195{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},
196{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},
197{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},
198{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},
200//logical symbols
201{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},
202{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},
203{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},
204{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},
205{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},
206{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},
207{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},
208{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},
209{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},
210{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},
211{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},
212{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},
214//grouping brackets
215{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},
216{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},
217{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},
218{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},
219{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},
220{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},
221{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},
222//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
223{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},
224{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},
225{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},
226{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},
227{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},
228{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},
230//miscellaneous symbols
231{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},
232{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},
233{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},
234{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},
235{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},
236{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},
237{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},
238{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},
239{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},
240{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},
241{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},
242{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},
243{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},
244{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},
245{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},
246{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},
247{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},
248{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},
249{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},
250{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},
251{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},
252{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},
253{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},
254{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},
255{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},
256{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},
257{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},
258{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},
259{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},
260{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},
261{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},
262{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},
263{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},
264{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},
266//standard functions
267{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},
268{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},
269{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},
270{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},
271{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},
272{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},
273{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},
274{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},
275{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},
276{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},
277{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},
278{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},
279{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},
280{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},
281{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},
282{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},
283{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},
284{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},
285{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},
286{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},
287{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},
288{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},
290//arrows
291{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},
292{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},
293{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},
294{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},
295{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},
296{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},
297{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},
298{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},
299{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},
300{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},
302//commands with argument
303AMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup,
304{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},
305{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},
306{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},
307{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},
308{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},
309{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},
310AMtext, AMmbox, AMquote,
311{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},
312{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},
313{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},
314{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},
315{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},
316{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},
317{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},
318{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},
319{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},
320{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},
321{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},
322{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}
323];
325function compareNames(s1,s2) {
326 if (s1.input > s2.input) return 1
327 else return -1;
330var AMnames = []; //list of input symbols
332function AMinitSymbols() {
333 var texsymbols = [], i;
334 for (i=0; i<AMsymbols.length; i++)
335 if (AMsymbols[i].tex)
336 texsymbols[texsymbols.length] = {input:AMsymbols[i].tex,
337 tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};
338 AMsymbols = AMsymbols.concat(texsymbols);
339 AMsymbols.sort(compareNames);
340 for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
343var AMmathml = "http://www.w3.org/1998/Math/MathML";
345function AMcreateElementMathML(t) {
346 if (isIE) return document.createElement("m:"+t);
347 else return document.createElementNS(AMmathml,t);
350function AMcreateMmlNode(t,frag) {
351// var node = AMcreateElementMathML(name);
352 if (isIE) var node = document.createElement("m:"+t);
353 else var node = document.createElementNS(AMmathml,t);
354 node.appendChild(frag);
355 return node;
358function newcommand(oldstr,newstr) {
359 AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,
360 tex:null, ttype:DEFINITION}]);
363function AMremoveCharsAndBlanks(str,n) {
364//remove n characters and any following blanks
365 var st;
366 if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ")
367 st = str.slice(n+1);
368 else st = str.slice(n);
369 for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
370 return st.slice(i);
373function AMposition(arr, str, n) {
374// return position >=n where str appears or would be inserted
375// assumes arr is sorted
376 if (n==0) {
377 var h,m;
378 n = -1;
379 h = arr.length;
380 while (n+1<h) {
381 m = (n+h) >> 1;
382 if (arr[m]<str) n = m; else h = m;
383 }
384 return h;
385 } else
386 for (var i=n; i<arr.length && arr[i]<str; i++);
387 return i; // i=arr.length || arr[i]>=str
390function AMgetSymbol(str) {
391//return maximal initial substring of str that appears in names
392//return null if there is none
393 var k = 0; //new pos
394 var j = 0; //old pos
395 var mk; //match pos
396 var st;
397 var tagst;
398 var match = "";
399 var more = true;
400 for (var i=1; i<=str.length && more; i++) {
401 st = str.slice(0,i); //initial substring of length i
402 j = k;
403 k = AMposition(AMnames, st, j);
404 if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
405 match = AMnames[k];
406 mk = k;
407 i = match.length;
408 }
409 more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
410 }
411 AMpreviousSymbol=AMcurrentSymbol;
412 if (match!=""){
413 AMcurrentSymbol=AMsymbols[mk].ttype;
414 return AMsymbols[mk];
415 }
416// if str[0] is a digit or - return maxsubstring of digits.digits
417 AMcurrentSymbol=CONST;
418 k = 1;
419 st = str.slice(0,1);
420 var integ = true;
421 while ("0"<=st && st<="9" && k<=str.length) {
422 st = str.slice(k,k+1);
423 k++;
424 }
425 if (st == decimalsign) {
426 st = str.slice(k,k+1);
427 if ("0"<=st && st<="9") {
428 integ = false;
429 k++;
430 while ("0"<=st && st<="9" && k<=str.length) {
431 st = str.slice(k,k+1);
432 k++;
433 }
434 }
435 }
436 if ((integ && k>1) || k>2) {
437 st = str.slice(0,k-1);
438 tagst = "mn";
439 } else {
440 k = 2;
441 st = str.slice(0,1); //take 1 character
442 tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
443 }
444 if (st=="-" && AMpreviousSymbol==INFIX) {
445 AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse
446 return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
447 }
448 return {input:st, tag:tagst, output:st, ttype:CONST};
451function AMremoveBrackets(node) {
452 var st;
453 if (node.nodeName=="mrow") {
454 st = node.firstChild.firstChild.nodeValue;
455 if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);
456 }
457 if (node.nodeName=="mrow") {
458 st = node.lastChild.firstChild.nodeValue;
459 if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);
460 }
463/*Parsing ASCII math expressions with the following grammar
464v ::= [A-Za-z] | greek letters | numbers | other constant symbols
465u ::= sqrt | text | bb | other unary symbols for font commands
466b ::= frac | root | stackrel binary symbols
467l ::= ( | [ | { | (: | {: left brackets
468r ::= ) | ] | } | :) | :} right brackets
469S ::= v | lEr | uS | bSS Simple expression
470I ::= S_S | S^S | S_S^S | S Intermediate expression
471E ::= IE | I/I Expression
472Each terminal symbol is translated into a corresponding mathml node.*/
474var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;
476function AMparseSexpr(str) { //parses str and returns [node,tailstr]
477 var symbol, node, result, i, st,// rightvert = false,
478 newFrag = document.createDocumentFragment();
479 str = AMremoveCharsAndBlanks(str,0);
480 symbol = AMgetSymbol(str); //either a token or a bracket or empty
481 if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {
482 return [null,str];
483 }
484 if (symbol.ttype == DEFINITION) {
485 str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);
486 symbol = AMgetSymbol(str);
487 }
488 switch (symbol.ttype) {
489 case UNDEROVER:
490 case CONST:
491 str = AMremoveCharsAndBlanks(str,symbol.input.length);
492 return [AMcreateMmlNode(symbol.tag, //its a constant
493 document.createTextNode(symbol.output)),str];
494 case LEFTBRACKET: //read (expr+)
495 AMnestingDepth++;
496 str = AMremoveCharsAndBlanks(str,symbol.input.length);
497 result = AMparseExpr(str,true);
498 AMnestingDepth--;
499 if (typeof symbol.invisible == "boolean" && symbol.invisible)
500 node = AMcreateMmlNode("mrow",result[0]);
501 else {
502 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
503 node = AMcreateMmlNode("mrow",node);
504 node.appendChild(result[0]);
505 }
506 return [node,result[1]];
507 case TEXT:
508 if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);
509 if (str.charAt(0)=="{") i=str.indexOf("}");
510 else if (str.charAt(0)=="(") i=str.indexOf(")");
511 else if (str.charAt(0)=="[") i=str.indexOf("]");
512 else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;
513 else i = 0;
514 if (i==-1) i = str.length;
515 st = str.slice(1,i);
516 if (st.charAt(0) == " ") {
517 node = AMcreateElementMathML("mspace");
518 node.setAttribute("width","1ex");
519 newFrag.appendChild(node);
520 }
521 newFrag.appendChild(
522 AMcreateMmlNode(symbol.tag,document.createTextNode(st)));
523 if (st.charAt(st.length-1) == " ") {
524 node = AMcreateElementMathML("mspace");
525 node.setAttribute("width","1ex");
526 newFrag.appendChild(node);
527 }
528 str = AMremoveCharsAndBlanks(str,i+1);
529 return [AMcreateMmlNode("mrow",newFrag),str];
530 case UNARY:
531 str = AMremoveCharsAndBlanks(str,symbol.input.length);
532 result = AMparseSexpr(str);
533 if (result[0]==null) return [AMcreateMmlNode(symbol.tag,
534 document.createTextNode(symbol.output)),str];
535 if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
536 st = str.charAt(0);
537 if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {
538 return [AMcreateMmlNode(symbol.tag,
539 document.createTextNode(symbol.output)),str];
540 } else {
541 node = AMcreateMmlNode("mrow",
542 AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));
543 node.appendChild(result[0]);
544 return [node,result[1]];
545 }
546 }
547 AMremoveBrackets(result[0]);
548 if (symbol.input == "sqrt") { // sqrt
549 return [AMcreateMmlNode(symbol.tag,result[0]),result[1]];
550 } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent
551 node = AMcreateMmlNode(symbol.tag,result[0]);
552 node.appendChild(AMcreateMmlNode("mo",document.createTextNode(symbol.output)));
553 return [node,result[1]];
554 } else { // font change command
555 if (!isIE && typeof symbol.codes != "undefined") {
556 for (i=0; i<result[0].childNodes.length; i++)
557 if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
558 st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
559 result[0].childNodes[i].firstChild.nodeValue);
560 var newst = [];
561 for (var j=0; j<st.length; j++)
562 if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +
563 String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);
564 else newst = newst + st.charAt(j);
565 if (result[0].nodeName=="mi")
566 result[0]=AMcreateElementMathML("mo").
567 appendChild(document.createTextNode(newst));
568 else result[0].replaceChild(AMcreateElementMathML("mo").
569 appendChild(document.createTextNode(newst)),result[0].childNodes[i]);
570 }
571 }
572 node = AMcreateMmlNode(symbol.tag,result[0]);
573 node.setAttribute(symbol.atname,symbol.atval);
574 return [node,result[1]];
575 }
576 case BINARY:
577 str = AMremoveCharsAndBlanks(str,symbol.input.length);
578 result = AMparseSexpr(str);
579 if (result[0]==null) return [AMcreateMmlNode("mo",
580 document.createTextNode(symbol.input)),str];
581 AMremoveBrackets(result[0]);
582 var result2 = AMparseSexpr(result[1]);
583 if (result2[0]==null) return [AMcreateMmlNode("mo",
584 document.createTextNode(symbol.input)),str];
585 AMremoveBrackets(result2[0]);
586 if (symbol.input=="root" || symbol.input=="stackrel")
587 newFrag.appendChild(result2[0]);
588 newFrag.appendChild(result[0]);
589 if (symbol.input=="frac") newFrag.appendChild(result2[0]);
590 return [AMcreateMmlNode(symbol.tag,newFrag),result2[1]];
591 case INFIX:
592 str = AMremoveCharsAndBlanks(str,symbol.input.length);
593 return [AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str];
594 case SPACE:
595 str = AMremoveCharsAndBlanks(str,symbol.input.length);
596 node = AMcreateElementMathML("mspace");
597 node.setAttribute("width","1ex");
598 newFrag.appendChild(node);
599 newFrag.appendChild(
600 AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));
601 node = AMcreateElementMathML("mspace");
602 node.setAttribute("width","1ex");
603 newFrag.appendChild(node);
604 return [AMcreateMmlNode("mrow",newFrag),str];
605 case LEFTRIGHT:
606// if (rightvert) return [null,str]; else rightvert = true;
607 AMnestingDepth++;
608 str = AMremoveCharsAndBlanks(str,symbol.input.length);
609 result = AMparseExpr(str,false);
610 AMnestingDepth--;
611 var st = "";
612 if (result[0].lastChild!=null)
613 st = result[0].lastChild.firstChild.nodeValue;
614 if (st == "|") { // its an absolute value subterm
615 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
616 node = AMcreateMmlNode("mrow",node);
617 node.appendChild(result[0]);
618 return [node,result[1]];
619 } else { // the "|" is a \mid
620 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
621 node = AMcreateMmlNode("mrow",node);
622 return [node,str];
623 }
624 default:
625//alert("default");
626 str = AMremoveCharsAndBlanks(str,symbol.input.length);
627 return [AMcreateMmlNode(symbol.tag, //its a constant
628 document.createTextNode(symbol.output)),str];
629 }
632function AMparseIexpr(str) {
633 var symbol, sym1, sym2, node, result, underover;
634 str = AMremoveCharsAndBlanks(str,0);
635 sym1 = AMgetSymbol(str);
636 result = AMparseSexpr(str);
637 node = result[0];
638 str = result[1];
639 symbol = AMgetSymbol(str);
640 if (symbol.ttype == INFIX && symbol.input != "/") {
641 str = AMremoveCharsAndBlanks(str,symbol.input.length);
642// if (symbol.input == "/") result = AMparseIexpr(str); else ...
643 result = AMparseSexpr(str);
644 if (result[0] == null) // show box in place of missing argument
645 result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));
646 else AMremoveBrackets(result[0]);
647 str = result[1];
648// if (symbol.input == "/") AMremoveBrackets(node);
649 if (symbol.input == "_") {
650 sym2 = AMgetSymbol(str);
651 underover = (sym1.ttype == UNDEROVER);
652 if (sym2.input == "^") {
653 str = AMremoveCharsAndBlanks(str,sym2.input.length);
654 var res2 = AMparseSexpr(str);
655 AMremoveBrackets(res2[0]);
656 str = res2[1];
657 node = AMcreateMmlNode((underover?"munderover":"msubsup"),node);
658 node.appendChild(result[0]);
659 node.appendChild(res2[0]);
660 node = AMcreateMmlNode("mrow",node); // so sum does not stretch
661 } else {
662 node = AMcreateMmlNode((underover?"munder":"msub"),node);
663 node.appendChild(result[0]);
664 }
665 } else {
666 node = AMcreateMmlNode(symbol.tag,node);
667 node.appendChild(result[0]);
668 }
669 }
670 return [node,str];
673function AMparseExpr(str,rightbracket) {
674 var symbol, node, result, i, nodeList = [],
675 newFrag = document.createDocumentFragment();
676 do {
677 str = AMremoveCharsAndBlanks(str,0);
678 result = AMparseIexpr(str);
679 node = result[0];
680 str = result[1];
681 symbol = AMgetSymbol(str);
682 if (symbol.ttype == INFIX && symbol.input == "/") {
683 str = AMremoveCharsAndBlanks(str,symbol.input.length);
684 result = AMparseIexpr(str);
685 if (result[0] == null) // show box in place of missing argument
686 result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));
687 else AMremoveBrackets(result[0]);
688 str = result[1];
689 AMremoveBrackets(node);
690 node = AMcreateMmlNode(symbol.tag,node);
691 node.appendChild(result[0]);
692 newFrag.appendChild(node);
693 symbol = AMgetSymbol(str);
694 }
695 else if (node!=undefined) newFrag.appendChild(node);
696 } while ((symbol.ttype != RIGHTBRACKET &&
697 (symbol.ttype != LEFTRIGHT || rightbracket)
698 || AMnestingDepth == 0) && symbol!=null && symbol.output!="");
699 if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {
700// if (AMnestingDepth > 0) AMnestingDepth--;
701 var len = newFrag.childNodes.length;
702 if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&
703 newFrag.childNodes[len-2].nodeName == "mo" &&
704 newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix
705 var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;
706 if (right==")" || right=="]") {
707 var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;
708 if (left=="(" && right==")" && symbol.output != "}" ||
709 left=="[" && right=="]") {
710 var pos = []; // positions of commas
711 var matrix = true;
712 var m = newFrag.childNodes.length;
713 for (i=0; matrix && i<m; i=i+2) {
714 pos[i] = [];
715 node = newFrag.childNodes[i];
716 if (matrix) matrix = node.nodeName=="mrow" &&
717 (i==m-1 || node.nextSibling.nodeName=="mo" &&
718 node.nextSibling.firstChild.nodeValue==",")&&
719 node.firstChild.firstChild.nodeValue==left &&
720 node.lastChild.firstChild.nodeValue==right;
721 if (matrix)
722 for (var j=0; j<node.childNodes.length; j++)
723 if (node.childNodes[j].firstChild.nodeValue==",")
724 pos[i][pos[i].length]=j;
725 if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;
726 }
727 if (matrix) {
728 var row, frag, n, k, table = document.createDocumentFragment();
729 for (i=0; i<m; i=i+2) {
730 row = document.createDocumentFragment();
731 frag = document.createDocumentFragment();
732 node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
733 n = node.childNodes.length;
734 k = 0;
735 node.removeChild(node.firstChild); //remove (
736 for (j=1; j<n-1; j++) {
737 if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
738 node.removeChild(node.firstChild); //remove ,
739 row.appendChild(AMcreateMmlNode("mtd",frag));
740 k++;
741 } else frag.appendChild(node.firstChild);
742 }
743 row.appendChild(AMcreateMmlNode("mtd",frag));
744 if (newFrag.childNodes.length>2) {
745 newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>
746 newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>
747 }
748 table.appendChild(AMcreateMmlNode("mtr",row));
749 }
750 node = AMcreateMmlNode("mtable",table);
751 if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");
752 newFrag.replaceChild(node,newFrag.firstChild);
753 }
754 }
755 }
756 }
757 str = AMremoveCharsAndBlanks(str,symbol.input.length);
758 if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
759 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
760 newFrag.appendChild(node);
761 }
762 }
763 return [newFrag,str];
766function AMparseMath(str) {
767 var result, node = AMcreateElementMathML("mstyle");
768 if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);
769 if (displaystyle) node.setAttribute("displaystyle","true");
770 if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily);
771 AMnestingDepth = 0;
772 node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false)[0]);
773 node = AMcreateMmlNode("math",node);
774 if (showasciiformulaonhover) //fixed by djhsu so newline
775 node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
776 if (mathfontfamily != "" && (isIE || mathfontfamily != "serif")) {
777 var fnode = AMcreateElementXHTML("font");
778 fnode.setAttribute("face",mathfontfamily);
779 fnode.appendChild(node);
780 return fnode;
781 }
782 return node;
785function AMstrarr2docFrag(arr, linebreaks) {
786 var newFrag=document.createDocumentFragment();
787 var expr = false;
788 for (var i=0; i<arr.length; i++) {
789 if (expr) newFrag.appendChild(AMparseMath(arr[i]));
790 else {
791 var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
792 newFrag.appendChild(AMcreateElementXHTML("span").
793 appendChild(document.createTextNode(arri[0])));
794 for (var j=1; j<arri.length; j++) {
795 newFrag.appendChild(AMcreateElementXHTML("p"));
796 newFrag.appendChild(AMcreateElementXHTML("span").
797 appendChild(document.createTextNode(arri[j])));
798 }
799 }
800 expr = !expr;
801 }
802 return newFrag;
805function AMprocessNodeR(n, linebreaks) {
806 var mtch, str, arr, frg, i;
807 if (n.childNodes.length == 0) {
808 if ((n.nodeType!=8 || linebreaks) &&
809 n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
810 n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" &&
811 n.parentNode.nodeName!="code" && n.parentNode.nodeName!="CODE" && /* added by JM */
812 n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE") {
813 str = n.nodeValue;
814 if (!(str == null)) {
815 str = str.replace(/\r\n\r\n/g,"\n\n");
816 if (doubleblankmathdelimiter) {
817 str = str.replace(/\x20\x20\./g," "+AMdelimiter1+".");
818 str = str.replace(/\x20\x20,/g," "+AMdelimiter1+",");
819 str = str.replace(/\x20\x20/g," "+AMdelimiter1+" ");
820 }
821 str = str.replace(/\x20+/g," ");
822 str = str.replace(/\s*\r\n/g," ");
823 mtch = false;
824 str = str.replace(new RegExp(AMescape2, "g"),
825 function(st){mtch=true;return "AMescape2"});
826 str = str.replace(new RegExp(AMescape1, "g"),
827 function(st){mtch=true;return "AMescape1"});
828 str = str.replace(new RegExp(AMdelimiter2regexp, "g"),AMdelimiter1);
829 arr = str.split(AMdelimiter1);
830 for (i=0; i<arr.length; i++)
831 arr[i]=arr[i].replace(/AMescape2/g,AMdelimiter2).
832 replace(/AMescape1/g,AMdelimiter1);
833 if (arr.length>1 || mtch) {
834 if (checkForMathML) {
835 checkForMathML = false;
836 var nd = AMisMathMLavailable();
837 AMnoMathML = nd != null;
838 if (AMnoMathML && notifyIfNoMathML)
839 if (alertIfNoMathML)
840 alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\n\
841 or Firefox/Mozilla/Netscape");
842 else AMbody.insertBefore(nd,AMbody.childNodes[0]);
843 }
844 if (!AMnoMathML) {
845 frg = AMstrarr2docFrag(arr,n.nodeType==8);
846 var len = frg.childNodes.length;
847 n.parentNode.replaceChild(frg,n);
848 return len-1;
849 } else return 0;
850 }
851 }
852 } else return 0;
853 } else if (n.nodeName!="math") {
854 for (i=0; i<n.childNodes.length; i++)
855 i += AMprocessNodeR(n.childNodes[i], linebreaks);
856 }
857 return 0;
860function AMprocessNode(n, linebreaks, spanclassAM) {
861 var frag,st;
862 if (spanclassAM!=null) {
863 frag = document.getElementsByTagName("span")
864 for (var i=0;i<frag.length;i++)
865 if (frag[i].className == "AM")
866 AMprocessNodeR(frag[i],linebreaks);
867 } else {
868 try {
869 st = n.innerHTML;
870 } catch(err) {}
871 if (st==null ||
872 st.indexOf(AMdelimiter1)!=-1 || st.indexOf(AMdelimiter2)!=-1)
873 AMprocessNodeR(n,linebreaks);
874 }
875 if (isIE) { //needed to match size and font of formula to surrounding text
876 frag = document.getElementsByTagName('math');
877 for (var i=0;i<frag.length;i++) frag[i].update()
878 }
881var AMbody;
882var AMnoMathML = false, AMtranslated = false;
884function translate(spanclassAM) {
885 if (!AMtranslated) { // run this only once
886 AMtranslated = true;
887 AMinitSymbols();
888 AMbody = document.getElementsByTagName("body")[0];
889 AMprocessNode(AMbody, false, spanclassAM);
890 }
893if (isIE) { // avoid adding MathPlayer info explicitly to each webpage
894 document.write("<object id=\"mathplayer\"\
895 classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
896 document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
899// GO1.1 Generic onload by Brothercake
900// http://www.brothercake.com/
901//onload function (replaces the onload="translate()" in the <body> tag)
902function generic()
904 translate();
905};
906//setup onload function
907if(typeof window.addEventListener != 'undefined')
909 //.. gecko, safari, konqueror and standard
910 window.addEventListener('load', generic, false);
912else if(typeof document.addEventListener != 'undefined')
914 //.. opera 7
915 document.addEventListener('load', generic, false);
917else if(typeof window.attachEvent != 'undefined')
919 //.. win/ie
920 window.attachEvent('onload', generic);
922//** remove this condition to degrade older browsers
923else
925 //.. mac/ie5 and anything else that gets this far
926 //if there's an existing onload function
927 if(typeof window.onload == 'function')
928 {
929 //store it
930 var existing = onload;
931 //add new onload handler
932 window.onload = function()
933 {
934 //call existing onload function
935 existing();
936 //call generic onload function
937 generic();
938 };
939 }
940 else
941 {
942 //setup onload function
943 window.onload = generic;
944 }