Subversion Repositories wimsdev

Rev

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
}