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