Changeset 1254


Ignore:
Timestamp:
05/10/10 09:03:16 (5 years ago)
Author:
gogo
Message:

Tickets #1209 and #1182
Upgrade Equation to use new AsciiMath?, fix multiple equation editing.
Thanks to Niraj Bhawnani of University of New South Wales.

Location:
trunk/plugins/Equation
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/plugins/Equation/ASCIIMathML.js

    r874 r1254  
    33============== 
    44This 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/). 
     5and LaTeX to Presentation MathML. Simple graphics commands are also 
     6translated to SVG images. The conversion is done while the (X)HTML  
     7page loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet  
     8Explorer 6/7 + MathPlayer (http://www.dessci.com/en/products/mathplayer/) + 
     9Adobe SVGview 3.03 (http://www.adobe.com/svg/viewer/install/). 
     10 
    811Just add the next line to your (X)HTML page with this file in the same folder: 
     12 
    913<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 
     14 
     15(using the graphics in IE also requires the file "d.svg" in the same folder). 
     16This is a convenient and inexpensive solution for authoring MathML and SVG. 
     17 
     18Version 2.1 Oct 8, 2008, (c) Peter Jipsen http://www.chapman.edu/~jipsen 
     19This version extends ASCIIMathML.js with LaTeXMathML.js and ASCIIsvg.js. 
    1320Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js 
    14 For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt 
    1521If you use it on a webpage, please send the URL to jipsen@chapman.edu 
    1622 
     23The LaTeXMathML modifications were made by Douglas Woodall, June 2006. 
     24(for details see header on the LaTeXMathML part in middle of file) 
     25Extensive clean-up and improvements by Paulo Soares, Oct 2007. 
     26 
    1727This 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 
     28it under the terms of the GNU Lesser General Public License as published by 
     29the Free Software Foundation; either version 2.1 of the License, or (at 
    2030your option) any later version. 
    2131 
    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. 
     32This program is distributed in the hope that it will be useful, but WITHOUT  
     33ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  
     34FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  
     35(at http://www.gnu.org/licences/lgpl.html) for more details. 
    2736*/ 
    2837 
    29 var checkForMathML = true;   // check if browser can display MathML 
    30 var notifyIfNoMathML = true; // put note at top of page if no MathML capability 
    31 var alertIfNoMathML = false;  // show alert box if no MathML capability 
    32 if ( typeof mathcolor == "undefined" ) 
    33 { 
    34         var mathcolor = "red";      // change it to "" (to inherit) or any other color 
    35 } 
    36 if ( typeof mathfontfamily == "undefined" )  
    37 { 
    38         var mathfontfamily = "serif"; // change to "" to inherit (works in IE) or another family (e.g. "arial") 
    39 } 
     38var mathcolor = "blue";        // change it to "" (to inherit) or another color 
     39var mathfontsize = "1em";      // change to e.g. 1.2em for larger math 
     40var mathfontfamily = "serif";  // change to "" to inherit (works in IE)  
     41                               // or another family (e.g. "arial") 
     42var automathrecognize = false; // writing "amath" on page makes this true 
     43var checkForMathML = true;     // check if browser can display MathML 
     44var notifyIfNoMathML = true;   // display note at top if no MathML capability 
     45var alertIfNoMathML = false;   // show alert box if no MathML capability 
     46var translateOnLoad = true;    // set to false to do call translators from js  
     47var translateLaTeX = true;     // false to preserve $..$, $$..$$ 
     48var translateLaTeXformatting = true; // false to preserve \emph,\begin{},\end{} 
     49var translateASCIIMath = true; // false to preserve `..` 
     50var translateASCIIsvg = true;  // false to preserve agraph.., \begin{graph}.. 
     51var avoidinnerHTML = false;   // set true if assigning to innerHTML gives error 
    4052var displaystyle = true;      // puts limits above and below large operators 
    41  
    42 if ( typeof showasciiformulaonhover == "undefined" )  
    43 { 
    44         var showasciiformulaonhover = true; // helps students learn ASCIIMath 
    45 } 
    46  
     53var showasciiformulaonhover = true; // helps students learn ASCIIMath 
    4754var decimalsign = ".";        // change to "," if you like, beware of `(1,2)`! 
    4855var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters 
    49 var AMdelimiter2 = "$", AMescape2 = "\\\\\\$", AMdelimiter2regexp = "\\$"; 
    50 var doubleblankmathdelimiter = false; // if true,  x+1  is equal to `x+1` 
    51                                       // for IE this works only in <!--   --> 
    52 //var separatetokens;// has been removed (email me if this is a problem) 
     56var AMdocumentId = "wikitext" // PmWiki element containing math (default=body) 
     57var checkforprocessasciimathinmoodle = false; // true for systems like Moodle 
     58var dsvglocation = ""; // path to d.svg (blank if same as ASCIIMathML.js loc) 
     59 
     60/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
     61 
    5362var isIE = document.createElementNS==null; 
    54  
    55 if (document.getElementById==null)  
    56   alert("This webpage requires a recent browser such as\ 
    57 \nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer") 
    58  
    59 // all further global variables start with "AM" 
    60  
    61 function AMcreateElementXHTML(t) { 
    62   if (isIE) return document.createElement(t); 
    63   else return document.createElementNS("http://www.w3.org/1999/xhtml",t); 
    64 } 
    65  
    66 function AMnoMathMLNote() { 
    67   var nd = AMcreateElementXHTML("h3"); 
    68   nd.setAttribute("align","center") 
    69   nd.appendChild(AMcreateElementXHTML("p")); 
    70   nd.appendChild(document.createTextNode("To view the ")); 
    71   var an = AMcreateElementXHTML("a"); 
     63var noMathML = false, translated = false; 
     64 
     65if (isIE) { // avoid adding MathPlayer info explicitly to each webpage 
     66  document.write("<object id=\"mathplayer\"\ 
     67  classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>"); 
     68  document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>"); 
     69} 
     70 
     71// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW) 
     72function setStylesheet(s) { 
     73        var id = "AMMLcustomStyleSheet"; 
     74        var n = document.getElementById(id); 
     75        if(document.createStyleSheet) { 
     76                // Test for IE's non-standard createStyleSheet method 
     77                if(n) 
     78                        n.parentNode.removeChild(n); 
     79                // This failed without the &nbsp; 
     80                document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd","&nbsp;<style id='" + id + "'>" + s + "</style>"); 
     81        } else { 
     82                if(n) { 
     83                        n.replaceChild(document.createTextNode(s),n.firstChild); 
     84                } else { 
     85                        n = document.createElement("style"); 
     86                        n.type = "text/css"; 
     87                        n.id = id; 
     88                        n.appendChild(document.createTextNode(s)); 
     89                        document.getElementsByTagName("head")[0].appendChild(n); 
     90                } 
     91        } 
     92} 
     93 
     94setStylesheet("#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}"); 
     95 
     96function init(){ 
     97        var msg, warnings = new Array(); 
     98        if (document.getElementById==null){ 
     99                alert("This webpage requires a recent browser such as Mozilla Firefox/Netscape 7+ or Internet Explorer 6+ with MathPlayer and Adobe SVGviewer"); 
     100                return null; 
     101        } 
     102        if (checkForMathML && (msg = checkMathML())) warnings.push(msg); 
     103        if (checkIfSVGavailable && (msg = checkSVG())) warnings.push(msg); 
     104        if (warnings.length>0) displayWarnings(warnings); 
     105        if (!noMathML) initSymbols(); 
     106        return true; 
     107} 
     108 
     109function checkMathML(){ 
     110  if (navigator.appName.slice(0,8)=="Netscape")  
     111    if (navigator.appVersion.slice(0,1)>="5") noMathML = null; 
     112    else noMathML = true; 
     113  else if (navigator.appName.slice(0,9)=="Microsoft") 
     114    try { 
     115        var ActiveX = new ActiveXObject("MathPlayer.Factory.1"); 
     116        noMathML = null; 
     117    } catch (e) { 
     118        noMathML = true; 
     119    } 
     120  else if (navigator.appName.slice(0,5)=="Opera")  
     121    if (navigator.appVersion.slice(0,3)>="9.5") noMathML = null; 
     122  else noMathML = true; 
     123//noMathML = true; //uncomment to check 
     124  if (noMathML && notifyIfNoMathML) { 
     125    var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later."; 
     126    if (alertIfNoMathML) 
     127       alert(msg); 
     128    else return msg; 
     129  } 
     130} 
     131 
     132function hideWarning(){ 
     133        var body = document.getElementsByTagName("body")[0]; 
     134        body.removeChild(document.getElementById('AMMLwarningBox')); 
     135        body.onclick = null; 
     136} 
     137 
     138function displayWarnings(warnings) { 
     139  var i, frag, nd = createElementXHTML("div"); 
     140  var body = document.getElementsByTagName("body")[0]; 
     141  body.onclick=hideWarning; 
     142  nd.id = 'AMMLwarningBox'; 
     143  for (i=0; i<warnings.length; i++) { 
     144        frag = createElementXHTML("div"); 
     145        frag.appendChild(document.createTextNode(warnings[i])); 
     146        frag.style.paddingBottom = "1.0em"; 
     147        nd.appendChild(frag); 
     148  } 
     149  nd.appendChild(createElementXHTML("p")); 
     150  nd.appendChild(document.createTextNode("For instructions see the ")); 
     151  var an = createElementXHTML("a"); 
    72152  an.appendChild(document.createTextNode("ASCIIMathML")); 
    73153  an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html"); 
    74154  nd.appendChild(an); 
    75   nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));   
    76   an = AMcreateElementXHTML("a"); 
    77   an.appendChild(document.createTextNode("MathPlayer")); 
    78   an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm"); 
     155  nd.appendChild(document.createTextNode(" homepage")); 
     156  an = createElementXHTML("div"); 
     157  an.id = 'AMMLcloseDiv'; 
     158  an.appendChild(document.createTextNode('(click anywhere to close this warning)')); 
    79159  nd.appendChild(an); 
    80   nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox")); 
    81   nd.appendChild(AMcreateElementXHTML("p")); 
    82   return nd; 
    83 } 
    84  
    85 function AMisMathMLavailable() { 
    86   if (navigator.appName.slice(0,8)=="Netscape")  
    87     if (navigator.appVersion.slice(0,1)>="5") return null; 
    88     else return AMnoMathMLNote(); 
    89   else if (navigator.appName.slice(0,9)=="Microsoft") 
    90     try { 
    91         var ActiveX = new ActiveXObject("MathPlayer.Factory.1"); 
    92         return null; 
    93     } catch (e) { 
    94         return AMnoMathMLNote(); 
    95     } 
    96   else return AMnoMathMLNote(); 
     160  var body = document.getElementsByTagName("body")[0]; 
     161  body.insertBefore(nd,body.childNodes[0]); 
     162} 
     163 
     164function translate(spanclassAM) { 
     165  if (!translated) { // run this only once 
     166    translated = true; 
     167    var body = document.getElementsByTagName("body")[0]; 
     168    var processN = document.getElementById(AMdocumentId); 
     169    if (translateLaTeX) LMprocessNode((processN!=null?processN:body)); 
     170    if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM); 
     171  } 
     172} 
     173 
     174function createElementXHTML(t) { 
     175  if (isIE) return document.createElement(t); 
     176  else return document.createElementNS("http://www.w3.org/1999/xhtml",t); 
     177} 
     178 
     179function createMmlNode(t,frag) { 
     180  if (isIE) var node = document.createElement("m:"+t); 
     181  else var node = document.createElementNS("http://www.w3.org/1998/Math/MathML",t); 
     182  if (frag) node.appendChild(frag); 
     183  return node; 
    97184} 
    98185 
     
    102189var 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]; 
    103190 
    104 var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,  
     191var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4, 
    105192    RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8, 
    106     LEFTRIGHT = 9, TEXT = 10; // token types 
    107  
    108 var AMsqrt = {input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY}, 
    109   AMroot  = {input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY}, 
    110   AMfrac  = {input:"frac", tag:"mfrac", output:"/",    tex:null, ttype:BINARY}, 
    111   AMdiv   = {input:"/",    tag:"mfrac", output:"/",    tex:null, ttype:INFIX}, 
    112   AMover  = {input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY}, 
    113   AMsub   = {input:"_",    tag:"msub",  output:"_",    tex:null, ttype:INFIX}, 
    114   AMsup   = {input:"^",    tag:"msup",  output:"^",    tex:null, ttype:INFIX}, 
    115   AMtext  = {input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT}, 
    116   AMmbox  = {input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT}, 
    117   AMquote = {input:"\"",   tag:"mtext", output:"mbox", tex:null, ttype:TEXT}; 
     193    LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13, 
     194    MATRIX = 14;; // token types 
     195 
     196var AMquote = {input:"\"",   tag:"mtext", output:"mbox", tex:null, ttype:TEXT}; 
    118197 
    119198var AMsymbols = [ 
     
    157236 
    158237//binary operation symbols 
     238//{input:"-",  tag:"mo", output:"\u0096", tex:null, ttype:CONST}, 
    159239{input:"*",  tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST}, 
    160240{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST}, 
     
    164244{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST}, 
    165245{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST}, 
    166 {input:"@",  tag:"mo", output:"\u2218", tex:"circ", ttype:CONST}, 
     246{input:"@",  tag:"mo", output:"\u26AC", tex:"circ", ttype:CONST}, 
    167247{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST}, 
    168248{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST}, 
     
    298378{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST}, 
    299379{input:"->",   tag:"mo", output:"\u2192", tex:"to", ttype:CONST}, 
     380{input:">->",   tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST}, 
     381{input:"->>",   tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST}, 
     382{input:">->>",   tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST}, 
    300383{input:"|->",  tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST}, 
    301384{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST}, 
     
    304387{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST}, 
    305388{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST}, 
    306  
    307389//commands with argument 
    308 AMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup, 
     390{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY}, 
     391{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY}, 
     392{input:"frac", tag:"mfrac", output:"/",    tex:null, ttype:BINARY}, 
     393{input:"/",    tag:"mfrac", output:"/",    tex:null, ttype:INFIX}, 
     394{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY}, 
     395{input:"_",    tag:"msub",  output:"_",    tex:null, ttype:INFIX}, 
     396{input:"^",    tag:"msup",  output:"^",    tex:null, ttype:INFIX}, 
    309397{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true}, 
    310398{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true}, 
     
    313401{input:"ddot", tag:"mover", output:"..",    tex:null, ttype:UNARY, acc:true}, 
    314402{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true}, 
    315 AMtext, AMmbox, AMquote, 
     403{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT}, 
     404{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT}, 
     405AMquote, 
    316406{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY}, 
    317407{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY}, 
     
    335425var AMnames = []; //list of input symbols 
    336426 
    337 function AMinitSymbols() { 
     427function initSymbols() { 
    338428  var texsymbols = [], i; 
    339429  for (i=0; i<AMsymbols.length; i++) 
     
    342432        tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype}; 
    343433  AMsymbols = AMsymbols.concat(texsymbols); 
     434  refreshSymbols(); 
     435} 
     436 
     437function refreshSymbols(){ 
     438  var i; 
    344439  AMsymbols.sort(compareNames); 
    345440  for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input; 
    346 } 
    347  
    348 var AMmathml = "http://www.w3.org/1998/Math/MathML"; 
    349  
    350 function AMcreateElementMathML(t) { 
    351   if (isIE) return document.createElement("m:"+t); 
    352   else return document.createElementNS(AMmathml,t); 
    353 } 
    354  
    355 function AMcreateMmlNode(t,frag) { 
    356 //  var node = AMcreateElementMathML(name); 
    357   if (isIE) var node = document.createElement("m:"+t); 
    358   else var node = document.createElementNS(AMmathml,t); 
    359   node.appendChild(frag); 
    360   return node; 
    361 } 
    362  
    363 function newcommand(oldstr,newstr) { 
    364   AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,  
     441  LMsymbols.sort(compareNames); 
     442  for (i=0; i<LMsymbols.length; i++) LMnames[i] = LMsymbols[i].input; 
     443} 
     444 
     445function define(oldstr,newstr) { 
     446  if(oldstr.substr(0,1)=="\\") 
     447    LMsymbols = LMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, 
     448                                 ttype:DEFINITION}]); 
     449  else 
     450    AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,  
    365451                                 tex:null, ttype:DEFINITION}]); 
     452  refreshSymbols(); // this may be a problem if many symbols are defined! 
    366453} 
    367454 
     
    376463} 
    377464 
    378 function AMposition(arr, str, n) {  
     465function position(arr, str, n) {  
    379466// return position >=n where str appears or would be inserted 
    380467// assumes arr is sorted 
     
    406493    st = str.slice(0,i); //initial substring of length i 
    407494    j = k; 
    408     k = AMposition(AMnames, st, j); 
     495    k = position(AMnames, st, j); 
    409496    if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){ 
    410497      match = AMnames[k]; 
     
    491578    symbol = AMgetSymbol(str); 
    492579  } 
    493   switch (symbol.ttype) { 
    494   case UNDEROVER: 
     580  switch (symbol.ttype) {  case UNDEROVER: 
    495581  case CONST: 
    496582    str = AMremoveCharsAndBlanks(str,symbol.input.length);  
    497     return [AMcreateMmlNode(symbol.tag,        //its a constant 
     583    return [createMmlNode(symbol.tag,        //its a constant 
    498584                             document.createTextNode(symbol.output)),str]; 
    499585  case LEFTBRACKET:   //read (expr+) 
     
    503589    AMnestingDepth--; 
    504590    if (typeof symbol.invisible == "boolean" && symbol.invisible)  
    505       node = AMcreateMmlNode("mrow",result[0]); 
     591      node = createMmlNode("mrow",result[0]); 
    506592    else { 
    507       node = AMcreateMmlNode("mo",document.createTextNode(symbol.output)); 
    508       node = AMcreateMmlNode("mrow",node); 
     593      node = createMmlNode("mo",document.createTextNode(symbol.output)); 
     594      node = createMmlNode("mrow",node); 
    509595      node.appendChild(result[0]); 
    510596    } 
     
    520606      st = str.slice(1,i); 
    521607      if (st.charAt(0) == " ") { 
    522         node = AMcreateElementMathML("mspace"); 
     608        node = createMmlNode("mspace"); 
    523609        node.setAttribute("width","1ex"); 
    524610        newFrag.appendChild(node); 
    525611      } 
    526612      newFrag.appendChild( 
    527         AMcreateMmlNode(symbol.tag,document.createTextNode(st))); 
     613        createMmlNode(symbol.tag,document.createTextNode(st))); 
    528614      if (st.charAt(st.length-1) == " ") { 
    529         node = AMcreateElementMathML("mspace"); 
     615        node = createMmlNode("mspace"); 
    530616        node.setAttribute("width","1ex"); 
    531617        newFrag.appendChild(node); 
    532618      } 
    533619      str = AMremoveCharsAndBlanks(str,i+1); 
    534       return [AMcreateMmlNode("mrow",newFrag),str]; 
     620      return [createMmlNode("mrow",newFrag),str]; 
    535621  case UNARY: 
    536622      str = AMremoveCharsAndBlanks(str,symbol.input.length);  
    537623      result = AMparseSexpr(str); 
    538       if (result[0]==null) return [AMcreateMmlNode(symbol.tag, 
     624      if (result[0]==null) return [createMmlNode(symbol.tag, 
    539625                             document.createTextNode(symbol.output)),str]; 
    540626      if (typeof symbol.func == "boolean" && symbol.func) { // functions hack 
    541627        st = str.charAt(0); 
    542628        if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") { 
    543           return [AMcreateMmlNode(symbol.tag, 
     629          return [createMmlNode(symbol.tag, 
    544630                    document.createTextNode(symbol.output)),str]; 
    545631        } else { 
    546           node = AMcreateMmlNode("mrow", 
    547            AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output))); 
     632          node = createMmlNode("mrow", 
     633           createMmlNode(symbol.tag,document.createTextNode(symbol.output))); 
    548634          node.appendChild(result[0]); 
    549635          return [node,result[1]]; 
     
    552638      AMremoveBrackets(result[0]); 
    553639      if (symbol.input == "sqrt") {           // sqrt 
    554         return [AMcreateMmlNode(symbol.tag,result[0]),result[1]]; 
     640        return [createMmlNode(symbol.tag,result[0]),result[1]]; 
    555641      } else if (typeof symbol.acc == "boolean" && symbol.acc) {   // accent 
    556         node = AMcreateMmlNode(symbol.tag,result[0]); 
    557         node.appendChild(AMcreateMmlNode("mo",document.createTextNode(symbol.output))); 
     642        node = createMmlNode(symbol.tag,result[0]); 
     643        node.appendChild(createMmlNode("mo",document.createTextNode(symbol.output))); 
    558644        return [node,result[1]]; 
    559645      } else {                        // font change command 
     
    569655                else newst = newst + st.charAt(j); 
    570656              if (result[0].nodeName=="mi") 
    571                 result[0]=AMcreateElementMathML("mo"). 
     657                result[0]=createMmlNode("mo"). 
    572658                          appendChild(document.createTextNode(newst)); 
    573               else result[0].replaceChild(AMcreateElementMathML("mo"). 
    574           appendChild(document.createTextNode(newst)),result[0].childNodes[i]); 
     659              else result[0].replaceChild(createMmlNode("mo"). 
     660                               appendChild(document.createTextNode(newst)), 
     661                                           result[0].childNodes[i]); 
    575662            } 
    576663        } 
    577         node = AMcreateMmlNode(symbol.tag,result[0]); 
     664        node = createMmlNode(symbol.tag,result[0]); 
    578665        node.setAttribute(symbol.atname,symbol.atval); 
    579666        return [node,result[1]]; 
     
    582669    str = AMremoveCharsAndBlanks(str,symbol.input.length);  
    583670    result = AMparseSexpr(str); 
    584     if (result[0]==null) return [AMcreateMmlNode("mo", 
     671    if (result[0]==null) return [createMmlNode("mo", 
    585672                           document.createTextNode(symbol.input)),str]; 
    586673    AMremoveBrackets(result[0]); 
    587674    var result2 = AMparseSexpr(result[1]); 
    588     if (result2[0]==null) return [AMcreateMmlNode("mo", 
     675    if (result2[0]==null) return [createMmlNode("mo", 
    589676                           document.createTextNode(symbol.input)),str]; 
    590677    AMremoveBrackets(result2[0]); 
     
    593680    newFrag.appendChild(result[0]); 
    594681    if (symbol.input=="frac") newFrag.appendChild(result2[0]); 
    595     return [AMcreateMmlNode(symbol.tag,newFrag),result2[1]]; 
     682    return [createMmlNode(symbol.tag,newFrag),result2[1]]; 
    596683  case INFIX: 
    597684    str = AMremoveCharsAndBlanks(str,symbol.input.length);  
    598     return [AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str]; 
     685    return [createMmlNode("mo",document.createTextNode(symbol.output)),str]; 
    599686  case SPACE: 
    600687    str = AMremoveCharsAndBlanks(str,symbol.input.length);  
    601     node = AMcreateElementMathML("mspace"); 
     688    node = createMmlNode("mspace"); 
    602689    node.setAttribute("width","1ex"); 
    603690    newFrag.appendChild(node); 
    604691    newFrag.appendChild( 
    605       AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output))); 
    606     node = AMcreateElementMathML("mspace"); 
     692      createMmlNode(symbol.tag,document.createTextNode(symbol.output))); 
     693    node = createMmlNode("mspace"); 
    607694    node.setAttribute("width","1ex"); 
    608695    newFrag.appendChild(node); 
    609     return [AMcreateMmlNode("mrow",newFrag),str]; 
     696    return [createMmlNode("mrow",newFrag),str]; 
    610697  case LEFTRIGHT: 
    611698//    if (rightvert) return [null,str]; else rightvert = true; 
     
    618705      st = result[0].lastChild.firstChild.nodeValue; 
    619706    if (st == "|") { // its an absolute value subterm 
    620       node = AMcreateMmlNode("mo",document.createTextNode(symbol.output)); 
    621       node = AMcreateMmlNode("mrow",node); 
     707      node = createMmlNode("mo",document.createTextNode(symbol.output)); 
     708      node = createMmlNode("mrow",node); 
    622709      node.appendChild(result[0]); 
    623710      return [node,result[1]]; 
    624     } else { // the "|" is a \mid 
    625       node = AMcreateMmlNode("mo",document.createTextNode(symbol.output)); 
    626       node = AMcreateMmlNode("mrow",node); 
     711    } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing 
     712      node = createMmlNode("mo",document.createTextNode("\u2223")); 
     713      node = createMmlNode("mrow",node); 
    627714      return [node,str]; 
    628715    } 
     
    630717//alert("default"); 
    631718    str = AMremoveCharsAndBlanks(str,symbol.input.length);  
    632     return [AMcreateMmlNode(symbol.tag,        //its a constant 
     719    return [createMmlNode(symbol.tag,        //its a constant 
    633720                             document.createTextNode(symbol.output)),str]; 
    634721  } 
     
    648735    result = AMparseSexpr(str); 
    649736    if (result[0] == null) // show box in place of missing argument 
    650       result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1")); 
     737      result[0] = createMmlNode("mo",document.createTextNode("\u25A1")); 
    651738    else AMremoveBrackets(result[0]); 
    652739    str = result[1]; 
     
    660747        AMremoveBrackets(res2[0]); 
    661748        str = res2[1]; 
    662         node = AMcreateMmlNode((underover?"munderover":"msubsup"),node); 
     749        node = createMmlNode((underover?"munderover":"msubsup"),node); 
    663750        node.appendChild(result[0]); 
    664751        node.appendChild(res2[0]); 
    665         node = AMcreateMmlNode("mrow",node); // so sum does not stretch 
     752        node = createMmlNode("mrow",node); // so sum does not stretch 
    666753      } else { 
    667         node = AMcreateMmlNode((underover?"munder":"msub"),node); 
     754        node = createMmlNode((underover?"munder":"msub"),node); 
    668755        node.appendChild(result[0]); 
    669756      } 
    670757    } else { 
    671       node = AMcreateMmlNode(symbol.tag,node); 
     758      node = createMmlNode(symbol.tag,node); 
    672759      node.appendChild(result[0]); 
    673760    } 
     
    689776      result = AMparseIexpr(str); 
    690777      if (result[0] == null) // show box in place of missing argument 
    691         result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1")); 
     778        result[0] = createMmlNode("mo",document.createTextNode("\u25A1")); 
    692779      else AMremoveBrackets(result[0]); 
    693780      str = result[1]; 
    694781      AMremoveBrackets(node); 
    695       node = AMcreateMmlNode(symbol.tag,node); 
     782      node = createMmlNode(symbol.tag,node); 
    696783      node.appendChild(result[0]); 
    697784      newFrag.appendChild(node); 
     
    742829              if (typeof pos[i][k] != "undefined" && j==pos[i][k]){ 
    743830                node.removeChild(node.firstChild); //remove , 
    744                 row.appendChild(AMcreateMmlNode("mtd",frag)); 
     831                row.appendChild(createMmlNode("mtd",frag)); 
    745832                k++; 
    746833              } else frag.appendChild(node.firstChild); 
    747834            } 
    748             row.appendChild(AMcreateMmlNode("mtd",frag)); 
     835            row.appendChild(createMmlNode("mtd",frag)); 
    749836            if (newFrag.childNodes.length>2) { 
    750837              newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow> 
    751838              newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo> 
    752839            } 
    753             table.appendChild(AMcreateMmlNode("mtr",row)); 
     840            table.appendChild(createMmlNode("mtr",row)); 
    754841          } 
    755           node = AMcreateMmlNode("mtable",table); 
     842          node = createMmlNode("mtable",table); 
    756843          if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left"); 
    757844          newFrag.replaceChild(node,newFrag.firstChild); 
     
    762849    str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    763850    if (typeof symbol.invisible != "boolean" || !symbol.invisible) { 
    764       node = AMcreateMmlNode("mo",document.createTextNode(symbol.output)); 
     851      node = createMmlNode("mo",document.createTextNode(symbol.output)); 
    765852      newFrag.appendChild(node); 
    766853    } 
     
    769856} 
    770857 
    771 function AMparseMath(str) { 
    772   var result, node = AMcreateElementMathML("mstyle"); 
    773   if (mathcolor != "") node.setAttribute("mathcolor",mathcolor); 
     858function parseMath(str,latex) { 
     859  var frag, node; 
     860  AMnestingDepth = 0; 
     861  frag = latex ? LMparseExpr(str.replace(/^\s+/g,""),false,false)[0] : AMparseExpr(str.replace(/^\s+/g,""),false)[0]; 
     862  node = createMmlNode("mstyle",frag); 
     863  node.setAttribute("mathcolor",mathcolor); 
     864  node.setAttribute("fontfamily",mathfontfamily); 
     865  node.setAttribute("mathsize",mathfontsize); 
    774866  if (displaystyle) node.setAttribute("displaystyle","true"); 
    775   if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily); 
    776   AMnestingDepth = 0; 
    777   node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false)[0]); 
    778   node = AMcreateMmlNode("math",node); 
     867  node = createMmlNode("math",node); 
    779868  if (showasciiformulaonhover)                      //fixed by djhsu so newline 
    780869    node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko 
    781   if (mathfontfamily != "" && (isIE || mathfontfamily != "serif")) { 
    782     var fnode = AMcreateElementXHTML("font"); 
    783     fnode.setAttribute("face",mathfontfamily); 
    784     fnode.appendChild(node); 
    785     return fnode; 
    786   } 
    787870  return node; 
    788871} 
    789872 
    790 function AMstrarr2docFrag(arr, linebreaks) { 
     873function strarr2docFrag(arr, linebreaks, latex) { 
    791874  var newFrag=document.createDocumentFragment(); 
    792875  var expr = false; 
    793876  for (var i=0; i<arr.length; i++) { 
    794     if (expr) newFrag.appendChild(AMparseMath(arr[i])); 
     877    if (expr) newFrag.appendChild(parseMath(arr[i],latex)); 
    795878    else { 
    796879      var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]); 
    797       newFrag.appendChild(AMcreateElementXHTML("span"). 
     880      newFrag.appendChild(createElementXHTML("span"). 
    798881      appendChild(document.createTextNode(arri[0]))); 
    799882      for (var j=1; j<arri.length; j++) { 
    800         newFrag.appendChild(AMcreateElementXHTML("p")); 
    801         newFrag.appendChild(AMcreateElementXHTML("span"). 
     883        newFrag.appendChild(createElementXHTML("p")); 
     884        newFrag.appendChild(createElementXHTML("span"). 
    802885        appendChild(document.createTextNode(arri[j]))); 
    803886      } 
     
    808891} 
    809892 
    810 function AMprocessNodeR(n, linebreaks) { 
     893function AMautomathrec(str) { 
     894//formula is a space (or start of str) followed by a maximal sequence of *two* or more tokens, possibly separated by runs of digits and/or space. 
     895//tokens are single letters (except a, A, I) and ASCIIMathML tokens 
     896  var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|"; 
     897  var ambigAMtoken = "\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|"; 
     898  var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|"; 
     899  var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out 
     900  var simpleAMtoken = "NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta"; // uuu nnn? 
     901  var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|"; 
     902  var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken; 
     903  var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g"); 
     904  str = str.replace(re," `$2`$7"); 
     905  var arr = str.split(AMdelimiter1); 
     906  var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g"); 
     907  var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now 
     908  for (i=0; i<arr.length; i++)   //single nonenglish tokens 
     909    if (i%2==0) { 
     910      arr[i] = arr[i].replace(re1," `$2`$3"); 
     911      arr[i] = arr[i].replace(re2," `$2`$3"); 
     912      arr[i] = arr[i].replace(/([{}[\]])/,"`$1`"); 
     913    } 
     914  str = arr.join(AMdelimiter1); 
     915  str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)");  //fix parentheses 
     916  str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3");  //fix parentheses 
     917  str = str.replace(/\sin`/g,"` in"); 
     918  str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`"); 
     919  str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2"); 
     920  str = str.replace(/`([0-9.]+:)`/g,"$1"); 
     921  return str; 
     922} 
     923 
     924function processNodeR(n, linebreaks,latex) { 
    811925  var mtch, str, arr, frg, i; 
    812926  if (n.childNodes.length == 0) { 
    813927   if ((n.nodeType!=8 || linebreaks) && 
    814928    n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" && 
    815     n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" && 
    816     n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE") { 
     929    n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /*&& 
     930    n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"*/) { 
    817931    str = n.nodeValue; 
    818932    if (!(str == null)) { 
    819933      str = str.replace(/\r\n\r\n/g,"\n\n"); 
    820       if (doubleblankmathdelimiter) { 
    821         str = str.replace(/\x20\x20\./g," "+AMdelimiter1+"."); 
    822         str = str.replace(/\x20\x20,/g," "+AMdelimiter1+","); 
    823         str = str.replace(/\x20\x20/g," "+AMdelimiter1+" "); 
    824       } 
    825934      str = str.replace(/\x20+/g," "); 
    826935      str = str.replace(/\s*\r\n/g," "); 
     936      if(latex) { 
     937// DELIMITERS: 
     938        mtch = (str.indexOf("\$")==-1 ? false : true); 
     939        str = str.replace(/([^\\])\$/g,"$1 \$"); 
     940        str = str.replace(/^\$/," \$"); // in case \$ at start of string 
     941        arr = str.split(" \$"); 
     942        for (i=0; i<arr.length; i++) 
     943          arr[i]=arr[i].replace(/\\\$/g,"\$"); 
     944      } else { 
    827945      mtch = false; 
    828       str = str.replace(new RegExp(AMescape2, "g"), 
    829               function(st){mtch=true;return "AMescape2"}); 
    830946      str = str.replace(new RegExp(AMescape1, "g"), 
    831               function(st){mtch=true;return "AMescape1"}); 
    832       str = str.replace(new RegExp(AMdelimiter2regexp, "g"),AMdelimiter1); 
     947              function(){mtch = true; return "AMescape1"}); 
     948      str = str.replace(/\\?end{?a?math}?/i, 
     949              function(){automathrecognize = false; mtch = true; return ""}); 
     950      str = str.replace(/amath\b|\\begin{a?math}/i, 
     951              function(){automathrecognize = true; mtch = true; return ""}); 
    833952      arr = str.split(AMdelimiter1); 
    834       for (i=0; i<arr.length; i++) 
    835         arr[i]=arr[i].replace(/AMescape2/g,AMdelimiter2). 
    836                       replace(/AMescape1/g,AMdelimiter1); 
     953      if (automathrecognize) 
     954        for (i=0; i<arr.length; i++) 
     955          if (i%2==0) arr[i] = AMautomathrec(arr[i]); 
     956      str = arr.join(AMdelimiter1); 
     957      arr = str.split(AMdelimiter1); 
     958      for (i=0; i<arr.length; i++) // this is a problem ************ 
     959        arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1); 
     960      } 
    837961      if (arr.length>1 || mtch) { 
    838         if (checkForMathML) { 
    839           checkForMathML = false; 
    840           var nd = AMisMathMLavailable(); 
    841           AMnoMathML = nd != null; 
    842           if (AMnoMathML && notifyIfNoMathML)  
    843             if (alertIfNoMathML) 
    844               alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\n\ 
    845                 or Firefox/Mozilla/Netscape"); 
    846             else AMbody.insertBefore(nd,AMbody.childNodes[0]); 
    847         } 
    848         if (!AMnoMathML) { 
    849           frg = AMstrarr2docFrag(arr,n.nodeType==8); 
     962        if (!noMathML) { 
     963          frg = strarr2docFrag(arr,n.nodeType==8,latex); 
    850964          var len = frg.childNodes.length; 
    851965          n.parentNode.replaceChild(frg,n); 
     
    857971  } else if (n.nodeName!="math") { 
    858972    for (i=0; i<n.childNodes.length; i++) 
    859       i += AMprocessNodeR(n.childNodes[i], linebreaks); 
     973      i += processNodeR(n.childNodes[i], linebreaks,latex); 
    860974  } 
    861975  return 0; 
     
    867981    frag = document.getElementsByTagName("span") 
    868982    for (var i=0;i<frag.length;i++) 
    869       if (frag[i].className == "AM") 
    870         AMprocessNodeR(frag[i],linebreaks); 
     983      if (frag[i].className == "AM")  
     984        processNodeR(frag[i],linebreaks,false); 
    871985  } else { 
    872986    try { 
    873       st = n.innerHTML; 
     987      st = n.innerHTML; // look for AMdelimiter on page 
    874988    } catch(err) {} 
    875     if (st==null ||  
    876         st.indexOf(AMdelimiter1)!=-1 || st.indexOf(AMdelimiter2)!=-1)  
    877       AMprocessNodeR(n,linebreaks); 
    878   } 
    879   if (isIE) { //needed to match size and font of formula to surrounding text 
     989//alert(st) 
     990    if (st==null || /amath\b|\\begin{a?math}/i.test(st) || 
     991      st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 || 
     992      st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) { 
     993      processNodeR(n,linebreaks,false); 
     994    } 
     995  } 
     996/*  if (isIE) { //needed to match size and font of formula to surrounding text 
    880997    frag = document.getElementsByTagName('math'); 
    881     for (var i=0;i<frag.length;i++) frag[i].update() 
    882   } 
    883 } 
    884  
    885 var AMbody; 
    886 var AMnoMathML = false, AMtranslated = false; 
    887  
    888 function translate(spanclassAM) { 
    889   if (!AMtranslated) { // run this only once 
    890     AMtranslated = true; 
    891     AMinitSymbols(); 
    892     AMbody = document.getElementsByTagName("body")[0]; 
    893     AMprocessNode(AMbody, false, spanclassAM); 
    894   } 
    895 } 
    896  
    897 if (isIE) { // avoid adding MathPlayer info explicitly to each webpage 
    898   document.write("<object id=\"mathplayer\"\ 
    899   classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>"); 
    900   document.write("<"+"?import namespace=\"m\" implementation=\"#mathplayer\"?>"); 
    901 } 
    902  
    903 // GO1.1 Generic onload by Brothercake  
     998    for (var i=0;i<frag.length;i++) frag[i].update() //What is this? 
     999  }*/ 
     1000} 
     1001 
     1002/* 
     1003LaTeXMathML.js 
     1004============== 
     1005 
     1006Version 1.1, July 20, 2007 (c) modifications by Peter Jipsen 
     1007 
     1008(changes: renamed global variables from AM... to LM... so that 
     1009LaTeXMathML and ASCIIMathML can be used simultaneously) 
     1010 
     1011Previous header notice: 
     1012This file (Version 1.0), is due to Douglas Woodall, June 2006. 
     1013It contains JavaScript functions to convert (most simple) LaTeX 
     1014math notation to Presentation MathML.  It was obtained by 
     1015downloading the file ASCIIMathML.js from 
     1016        http://www1.chapman.edu/~jipsen/mathml/asciimathdownload/ 
     1017and modifying it so that it carries out ONLY those conversions 
     1018that would be carried out in LaTeX.  A description of the original 
     1019file, with examples, can be found at 
     1020        www1.chapman.edu/~jipsen/mathml/asciimath.html 
     1021        ASCIIMathML: Math on the web for everyone 
     1022 
     1023Here is the header notice from the original file: 
     1024 
     1025ASCIIMathML.js 
     1026============== 
     1027This file contains JavaScript functions to convert ASCII math notation 
     1028to Presentation MathML. The conversion is done while the (X)HTML page 
     1029loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet 
     1030Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/). 
     1031Just add the next line to your (X)HTML page with this file in the same folder: 
     1032<script type="text/javascript" src="ASCIIMathML.js"></script> 
     1033This is a convenient and inexpensive solution for authoring MathML. 
     1034 
     1035Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen 
     1036Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js 
     1037For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt 
     1038If you use it on a webpage, please send the URL to jipsen@chapman.edu 
     1039 
     1040This program is free software; you can redistribute it and/or modify 
     1041it under the terms of the GNU Lesser General Public License as published by 
     1042the Free Software Foundation; either version 2.1 of the License, or (at 
     1043your option) any later version. 
     1044 
     1045This program is distributed in the hope that it will be useful, 
     1046but WITHOUT ANY WARRANTY; without even the implied warranty of 
     1047MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
     1048General Public License (at http://www.gnu.org/license/lgpl.html) 
     1049for more details. 
     1050 
     1051LaTeXMathML.js (ctd) 
     1052============== 
     1053 
     1054Content between $...$ and $$...$$ is converted by this part of the file 
     1055*/ 
     1056 
     1057// all further global variables start with "LM" 
     1058 
     1059// Commented out by DRW to prevent 1/2 turning into a 2-line fraction 
     1060// LMdiv   = {input:"/",         tag:"mfrac", output:"/",    ttype:INFIX}, 
     1061// Commented out by DRW so that " prints literally in equations 
     1062// LMquote = {input:"\"",        tag:"mtext", output:"mbox", ttype:TEXT}; 
     1063 
     1064var LMsymbols = [ 
     1065//Greek letters 
     1066{input:"\\alpha",       tag:"mi", output:"\u03B1", ttype:CONST}, 
     1067{input:"\\beta",        tag:"mi", output:"\u03B2", ttype:CONST}, 
     1068{input:"\\gamma",       tag:"mi", output:"\u03B3", ttype:CONST}, 
     1069{input:"\\delta",       tag:"mi", output:"\u03B4", ttype:CONST}, 
     1070{input:"\\epsilon",     tag:"mi", output:"\u03B5", ttype:CONST}, 
     1071{input:"\\varepsilon",  tag:"mi", output:"\u025B", ttype:CONST}, 
     1072{input:"\\zeta",        tag:"mi", output:"\u03B6", ttype:CONST}, 
     1073{input:"\\eta",         tag:"mi", output:"\u03B7", ttype:CONST}, 
     1074{input:"\\theta",       tag:"mi", output:"\u03B8", ttype:CONST}, 
     1075{input:"\\vartheta",    tag:"mi", output:"\u03D1", ttype:CONST}, 
     1076{input:"\\iota",        tag:"mi", output:"\u03B9", ttype:CONST}, 
     1077{input:"\\kappa",       tag:"mi", output:"\u03BA", ttype:CONST}, 
     1078{input:"\\lambda",      tag:"mi", output:"\u03BB", ttype:CONST}, 
     1079{input:"\\mu",          tag:"mi", output:"\u03BC", ttype:CONST}, 
     1080{input:"\\nu",          tag:"mi", output:"\u03BD", ttype:CONST}, 
     1081{input:"\\xi",          tag:"mi", output:"\u03BE", ttype:CONST}, 
     1082{input:"\\pi",          tag:"mi", output:"\u03C0", ttype:CONST}, 
     1083{input:"\\varpi",       tag:"mi", output:"\u03D6", ttype:CONST}, 
     1084{input:"\\rho",         tag:"mi", output:"\u03C1", ttype:CONST}, 
     1085{input:"\\varrho",      tag:"mi", output:"\u03F1", ttype:CONST}, 
     1086{input:"\\varsigma",    tag:"mi", output:"\u03C2", ttype:CONST}, 
     1087{input:"\\sigma",       tag:"mi", output:"\u03C3", ttype:CONST}, 
     1088{input:"\\tau",         tag:"mi", output:"\u03C4", ttype:CONST}, 
     1089{input:"\\upsilon",     tag:"mi", output:"\u03C5", ttype:CONST}, 
     1090{input:"\\phi",         tag:"mi", output:"\u03C6", ttype:CONST}, 
     1091{input:"\\varphi",      tag:"mi", output:"\u03D5", ttype:CONST}, 
     1092{input:"\\chi",         tag:"mi", output:"\u03C7", ttype:CONST}, 
     1093{input:"\\psi",         tag:"mi", output:"\u03C8", ttype:CONST}, 
     1094{input:"\\omega",       tag:"mi", output:"\u03C9", ttype:CONST}, 
     1095{input:"\\Gamma",       tag:"mo", output:"\u0393", ttype:CONST}, 
     1096{input:"\\Delta",       tag:"mo", output:"\u0394", ttype:CONST}, 
     1097{input:"\\Theta",       tag:"mo", output:"\u0398", ttype:CONST}, 
     1098{input:"\\Lambda",      tag:"mo", output:"\u039B", ttype:CONST}, 
     1099{input:"\\Xi",          tag:"mo", output:"\u039E", ttype:CONST}, 
     1100{input:"\\Pi",          tag:"mo", output:"\u03A0", ttype:CONST}, 
     1101{input:"\\Sigma",       tag:"mo", output:"\u03A3", ttype:CONST}, 
     1102{input:"\\Upsilon",     tag:"mo", output:"\u03A5", ttype:CONST}, 
     1103{input:"\\Phi",         tag:"mo", output:"\u03A6", ttype:CONST}, 
     1104{input:"\\Psi",         tag:"mo", output:"\u03A8", ttype:CONST}, 
     1105{input:"\\Omega",       tag:"mo", output:"\u03A9", ttype:CONST}, 
     1106 
     1107//fractions 
     1108{input:"\\frac12",      tag:"mo", output:"\u00BD", ttype:CONST}, 
     1109{input:"\\frac14",      tag:"mo", output:"\u00BC", ttype:CONST}, 
     1110{input:"\\frac34",      tag:"mo", output:"\u00BE", ttype:CONST}, 
     1111{input:"\\frac13",      tag:"mo", output:"\u2153", ttype:CONST}, 
     1112{input:"\\frac23",      tag:"mo", output:"\u2154", ttype:CONST}, 
     1113{input:"\\frac15",      tag:"mo", output:"\u2155", ttype:CONST}, 
     1114{input:"\\frac25",      tag:"mo", output:"\u2156", ttype:CONST}, 
     1115{input:"\\frac35",      tag:"mo", output:"\u2157", ttype:CONST}, 
     1116{input:"\\frac45",      tag:"mo", output:"\u2158", ttype:CONST}, 
     1117{input:"\\frac16",      tag:"mo", output:"\u2159", ttype:CONST}, 
     1118{input:"\\frac56",      tag:"mo", output:"\u215A", ttype:CONST}, 
     1119{input:"\\frac18",      tag:"mo", output:"\u215B", ttype:CONST}, 
     1120{input:"\\frac38",      tag:"mo", output:"\u215C", ttype:CONST}, 
     1121{input:"\\frac58",      tag:"mo", output:"\u215D", ttype:CONST}, 
     1122{input:"\\frac78",      tag:"mo", output:"\u215E", ttype:CONST}, 
     1123 
     1124//binary operation symbols 
     1125{input:"\\pm",          tag:"mo", output:"\u00B1", ttype:CONST}, 
     1126{input:"\\mp",          tag:"mo", output:"\u2213", ttype:CONST}, 
     1127{input:"\\triangleleft",tag:"mo", output:"\u22B2", ttype:CONST}, 
     1128{input:"\\triangleright",tag:"mo",output:"\u22B3", ttype:CONST}, 
     1129{input:"\\cdot",        tag:"mo", output:"\u22C5", ttype:CONST}, 
     1130{input:"\\star",        tag:"mo", output:"\u22C6", ttype:CONST}, 
     1131{input:"\\ast",         tag:"mo", output:"\u002A", ttype:CONST}, 
     1132{input:"\\times",       tag:"mo", output:"\u00D7", ttype:CONST}, 
     1133{input:"\\div",         tag:"mo", output:"\u00F7", ttype:CONST}, 
     1134{input:"\\circ",        tag:"mo", output:"\u2218", ttype:CONST}, 
     1135//{input:"\\bullet",      tag:"mo", output:"\u2219", ttype:CONST}, 
     1136{input:"\\bullet",      tag:"mo", output:"\u2022", ttype:CONST}, 
     1137{input:"\\oplus",       tag:"mo", output:"\u2295", ttype:CONST}, 
     1138{input:"\\ominus",      tag:"mo", output:"\u2296", ttype:CONST}, 
     1139{input:"\\otimes",      tag:"mo", output:"\u2297", ttype:CONST}, 
     1140{input:"\\bigcirc",     tag:"mo", output:"\u25CB", ttype:CONST}, 
     1141{input:"\\oslash",      tag:"mo", output:"\u2298", ttype:CONST}, 
     1142{input:"\\odot",        tag:"mo", output:"\u2299", ttype:CONST}, 
     1143{input:"\\land",        tag:"mo", output:"\u2227", ttype:CONST}, 
     1144{input:"\\wedge",       tag:"mo", output:"\u2227", ttype:CONST}, 
     1145{input:"\\lor",         tag:"mo", output:"\u2228", ttype:CONST}, 
     1146{input:"\\vee",         tag:"mo", output:"\u2228", ttype:CONST}, 
     1147{input:"\\cap",         tag:"mo", output:"\u2229", ttype:CONST}, 
     1148{input:"\\cup",         tag:"mo", output:"\u222A", ttype:CONST}, 
     1149{input:"\\sqcap",       tag:"mo", output:"\u2293", ttype:CONST}, 
     1150{input:"\\sqcup",       tag:"mo", output:"\u2294", ttype:CONST}, 
     1151{input:"\\uplus",       tag:"mo", output:"\u228E", ttype:CONST}, 
     1152{input:"\\amalg",       tag:"mo", output:"\u2210", ttype:CONST}, 
     1153{input:"\\bigtriangleup",tag:"mo",output:"\u25B3", ttype:CONST}, 
     1154{input:"\\bigtriangledown",tag:"mo",output:"\u25BD", ttype:CONST}, 
     1155{input:"\\dag",         tag:"mo", output:"\u2020", ttype:CONST}, 
     1156{input:"\\dagger",      tag:"mo", output:"\u2020", ttype:CONST}, 
     1157{input:"\\ddag",        tag:"mo", output:"\u2021", ttype:CONST}, 
     1158{input:"\\ddagger",     tag:"mo", output:"\u2021", ttype:CONST}, 
     1159{input:"\\lhd",         tag:"mo", output:"\u22B2", ttype:CONST}, 
     1160{input:"\\rhd",         tag:"mo", output:"\u22B3", ttype:CONST}, 
     1161{input:"\\unlhd",       tag:"mo", output:"\u22B4", ttype:CONST}, 
     1162{input:"\\unrhd",       tag:"mo", output:"\u22B5", ttype:CONST}, 
     1163 
     1164 
     1165//BIG Operators 
     1166{input:"\\sum",         tag:"mo", output:"\u2211", ttype:UNDEROVER}, 
     1167{input:"\\prod",        tag:"mo", output:"\u220F", ttype:UNDEROVER}, 
     1168{input:"\\bigcap",      tag:"mo", output:"\u22C2", ttype:UNDEROVER}, 
     1169{input:"\\bigcup",      tag:"mo", output:"\u22C3", ttype:UNDEROVER}, 
     1170{input:"\\bigwedge",    tag:"mo", output:"\u22C0", ttype:UNDEROVER}, 
     1171{input:"\\bigvee",      tag:"mo", output:"\u22C1", ttype:UNDEROVER}, 
     1172{input:"\\bigsqcap",    tag:"mo", output:"\u2A05", ttype:UNDEROVER}, 
     1173{input:"\\bigsqcup",    tag:"mo", output:"\u2A06", ttype:UNDEROVER}, 
     1174{input:"\\coprod",      tag:"mo", output:"\u2210", ttype:UNDEROVER}, 
     1175{input:"\\bigoplus",    tag:"mo", output:"\u2A01", ttype:UNDEROVER}, 
     1176{input:"\\bigotimes",   tag:"mo", output:"\u2A02", ttype:UNDEROVER}, 
     1177{input:"\\bigodot",     tag:"mo", output:"\u2A00", ttype:UNDEROVER}, 
     1178{input:"\\biguplus",    tag:"mo", output:"\u2A04", ttype:UNDEROVER}, 
     1179{input:"\\int",         tag:"mo", output:"\u222B", ttype:CONST}, 
     1180{input:"\\oint",        tag:"mo", output:"\u222E", ttype:CONST}, 
     1181 
     1182//binary relation symbols 
     1183{input:":=",            tag:"mo", output:":=",     ttype:CONST}, 
     1184{input:"\\lt",          tag:"mo", output:"<",      ttype:CONST}, 
     1185{input:"\\gt",          tag:"mo", output:">",      ttype:CONST}, 
     1186{input:"\\ne",          tag:"mo", output:"\u2260", ttype:CONST}, 
     1187{input:"\\neq",         tag:"mo", output:"\u2260", ttype:CONST}, 
     1188{input:"\\le",          tag:"mo", output:"\u2264", ttype:CONST}, 
     1189{input:"\\leq",         tag:"mo", output:"\u2264", ttype:CONST}, 
     1190{input:"\\leqslant",    tag:"mo", output:"\u2264", ttype:CONST}, 
     1191{input:"\\ge",          tag:"mo", output:"\u2265", ttype:CONST}, 
     1192{input:"\\geq",         tag:"mo", output:"\u2265", ttype:CONST}, 
     1193{input:"\\geqslant",    tag:"mo", output:"\u2265", ttype:CONST}, 
     1194{input:"\\equiv",       tag:"mo", output:"\u2261", ttype:CONST}, 
     1195{input:"\\ll",          tag:"mo", output:"\u226A", ttype:CONST}, 
     1196{input:"\\gg",          tag:"mo", output:"\u226B", ttype:CONST}, 
     1197{input:"\\doteq",       tag:"mo", output:"\u2250", ttype:CONST}, 
     1198{input:"\\prec",        tag:"mo", output:"\u227A", ttype:CONST}, 
     1199{input:"\\succ",        tag:"mo", output:"\u227B", ttype:CONST}, 
     1200{input:"\\preceq",      tag:"mo", output:"\u227C", ttype:CONST}, 
     1201{input:"\\succeq",      tag:"mo", output:"\u227D", ttype:CONST}, 
     1202{input:"\\subset",      tag:"mo", output:"\u2282", ttype:CONST}, 
     1203{input:"\\supset",      tag:"mo", output:"\u2283", ttype:CONST}, 
     1204{input:"\\subseteq",    tag:"mo", output:"\u2286", ttype:CONST}, 
     1205{input:"\\supseteq",    tag:"mo", output:"\u2287", ttype:CONST}, 
     1206{input:"\\sqsubset",    tag:"mo", output:"\u228F", ttype:CONST}, 
     1207{input:"\\sqsupset",    tag:"mo", output:"\u2290", ttype:CONST}, 
     1208{input:"\\sqsubseteq",  tag:"mo", output:"\u2291", ttype:CONST}, 
     1209{input:"\\sqsupseteq",  tag:"mo", output:"\u2292", ttype:CONST}, 
     1210{input:"\\sim",         tag:"mo", output:"\u223C", ttype:CONST}, 
     1211{input:"\\simeq",       tag:"mo", output:"\u2243", ttype:CONST}, 
     1212{input:"\\approx",      tag:"mo", output:"\u2248", ttype:CONST}, 
     1213{input:"\\cong",        tag:"mo", output:"\u2245", ttype:CONST}, 
     1214{input:"\\Join",        tag:"mo", output:"\u22C8", ttype:CONST}, 
     1215{input:"\\bowtie",      tag:"mo", output:"\u22C8", ttype:CONST}, 
     1216{input:"\\in",          tag:"mo", output:"\u2208", ttype:CONST}, 
     1217{input:"\\ni",          tag:"mo", output:"\u220B", ttype:CONST}, 
     1218{input:"\\owns",        tag:"mo", output:"\u220B", ttype:CONST}, 
     1219{input:"\\propto",      tag:"mo", output:"\u221D", ttype:CONST}, 
     1220{input:"\\vdash",       tag:"mo", output:"\u22A2", ttype:CONST}, 
     1221{input:"\\dashv",       tag:"mo", output:"\u22A3", ttype:CONST}, 
     1222{input:"\\models",      tag:"mo", output:"\u22A8", ttype:CONST}, 
     1223{input:"\\perp",        tag:"mo", output:"\u22A5", ttype:CONST}, 
     1224{input:"\\smile",       tag:"mo", output:"\u2323", ttype:CONST}, 
     1225{input:"\\frown",       tag:"mo", output:"\u2322", ttype:CONST}, 
     1226{input:"\\asymp",       tag:"mo", output:"\u224D", ttype:CONST}, 
     1227{input:"\\notin",       tag:"mo", output:"\u2209", ttype:CONST}, 
     1228 
     1229//matrices 
     1230{input:"\\begin{eqnarray}",     output:"X",     ttype:MATRIX, invisible:true}, 
     1231{input:"\\begin{array}",        output:"X",     ttype:MATRIX, invisible:true}, 
     1232{input:"\\\\",                  output:"}&{",   ttype:DEFINITION}, 
     1233{input:"\\end{eqnarray}",       output:"}}",    ttype:DEFINITION}, 
     1234{input:"\\end{array}",          output:"}}",    ttype:DEFINITION}, 
     1235 
     1236//grouping and literal brackets -- ieval is for IE 
     1237{input:"\\big",    tag:"mo", output:"X", atval:"1.2", ieval:"2.2", ttype:BIG}, 
     1238{input:"\\Big",    tag:"mo", output:"X", atval:"1.6", ieval:"2.6", ttype:BIG}, 
     1239{input:"\\bigg",   tag:"mo", output:"X", atval:"2.2", ieval:"3.2", ttype:BIG}, 
     1240{input:"\\Bigg",   tag:"mo", output:"X", atval:"2.9", ieval:"3.9", ttype:BIG}, 
     1241{input:"\\left",   tag:"mo", output:"X", ttype:LEFTBRACKET}, 
     1242{input:"\\right",  tag:"mo", output:"X", ttype:RIGHTBRACKET}, 
     1243{input:"{",        output:"{", ttype:LEFTBRACKET,  invisible:true}, 
     1244{input:"}",        output:"}", ttype:RIGHTBRACKET, invisible:true}, 
     1245 
     1246{input:"(",        tag:"mo", output:"(",      atval:"1", ttype:STRETCHY}, 
     1247{input:"[",        tag:"mo", output:"[",      atval:"1", ttype:STRETCHY}, 
     1248{input:"\\lbrack", tag:"mo", output:"[",      atval:"1", ttype:STRETCHY}, 
     1249{input:"\\{",      tag:"mo", output:"{",      atval:"1", ttype:STRETCHY}, 
     1250{input:"\\lbrace", tag:"mo", output:"{",      atval:"1", ttype:STRETCHY}, 
     1251{input:"\\langle", tag:"mo", output:"\u2329", atval:"1", ttype:STRETCHY}, 
     1252{input:"\\lfloor", tag:"mo", output:"\u230A", atval:"1", ttype:STRETCHY}, 
     1253{input:"\\lceil",  tag:"mo", output:"\u2308", atval:"1", ttype:STRETCHY}, 
     1254 
     1255// rtag:"mi" causes space to be inserted before a following sin, cos, etc. 
     1256// (see function LMparseExpr() ) 
     1257{input:")",       tag:"mo",output:")",      rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1258{input:"]",       tag:"mo",output:"]",      rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1259{input:"\\rbrack",tag:"mo",output:"]",      rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1260{input:"\\}",     tag:"mo",output:"}",      rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1261{input:"\\rbrace",tag:"mo",output:"}",      rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1262{input:"\\rangle",tag:"mo",output:"\u232A", rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1263{input:"\\rfloor",tag:"mo",output:"\u230B", rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1264{input:"\\rceil", tag:"mo",output:"\u2309", rtag:"mi",atval:"1",ttype:STRETCHY}, 
     1265 
     1266// "|", "\\|", "\\vert" and "\\Vert" modified later: lspace = rspace = 0em 
     1267{input:"|",             tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY}, 
     1268{input:"\\|",           tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY}, 
     1269{input:"\\vert",        tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY}, 
     1270{input:"\\Vert",        tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY}, 
     1271{input:"\\mid",         tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY}, 
     1272{input:"\\parallel",    tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY}, 
     1273{input:"/",             tag:"mo", output:"/",   atval:"1.01", ttype:STRETCHY}, 
     1274{input:"\\backslash",   tag:"mo", output:"\u2216", atval:"1", ttype:STRETCHY}, 
     1275{input:"\\setminus",    tag:"mo", output:"\\",     ttype:CONST}, 
     1276 
     1277//miscellaneous symbols 
     1278{input:"\\!",     tag:"mspace", atname:"width", atval:"-0.167em", ttype:SPACE}, 
     1279{input:"\\,",     tag:"mspace", atname:"width", atval:"0.167em", ttype:SPACE}, 
     1280{input:"\\>",     tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE}, 
     1281{input:"\\:",     tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE}, 
     1282{input:"\\;",     tag:"mspace", atname:"width", atval:"0.278em", ttype:SPACE}, 
     1283{input:"~",       tag:"mspace", atname:"width", atval:"0.333em", ttype:SPACE}, 
     1284{input:"\\quad",  tag:"mspace", atname:"width", atval:"1em", ttype:SPACE}, 
     1285{input:"\\qquad", tag:"mspace", atname:"width", atval:"2em", ttype:SPACE}, 
     1286//{input:"{}",            tag:"mo", output:"\u200B", ttype:CONST}, // zero-width 
     1287{input:"\\prime",       tag:"mo", output:"\u2032", ttype:CONST}, 
     1288{input:"'",             tag:"mo", output:"\u02B9", ttype:CONST}, 
     1289{input:"''",            tag:"mo", output:"\u02BA", ttype:CONST}, 
     1290{input:"'''",           tag:"mo", output:"\u2034", ttype:CONST}, 
     1291{input:"''''",          tag:"mo", output:"\u2057", ttype:CONST}, 
     1292{input:"\\ldots",       tag:"mo", output:"\u2026", ttype:CONST}, 
     1293{input:"\\cdots",       tag:"mo", output:"\u22EF", ttype:CONST}, 
     1294{input:"\\vdots",       tag:"mo", output:"\u22EE", ttype:CONST}, 
     1295{input:"\\ddots",       tag:"mo", output:"\u22F1", ttype:CONST}, 
     1296{input:"\\forall",      tag:"mo", output:"\u2200", ttype:CONST}, 
     1297{input:"\\exists",      tag:"mo", output:"\u2203", ttype:CONST}, 
     1298{input:"\\Re",          tag:"mo", output:"\u211C", ttype:CONST}, 
     1299{input:"\\Im",          tag:"mo", output:"\u2111", ttype:CONST}, 
     1300{input:"\\aleph",       tag:"mo", output:"\u2135", ttype:CONST}, 
     1301{input:"\\hbar",        tag:"mo", output:"\u210F", ttype:CONST}, 
     1302{input:"\\ell",         tag:"mo", output:"\u2113", ttype:CONST}, 
     1303{input:"\\wp",          tag:"mo", output:"\u2118", ttype:CONST}, 
     1304{input:"\\emptyset",    tag:"mo", output:"\u2205", ttype:CONST}, 
     1305{input:"\\infty",       tag:"mo", output:"\u221E", ttype:CONST}, 
     1306{input:"\\surd",        tag:"mo", output:"\\sqrt{}", ttype:DEFINITION}, 
     1307{input:"\\partial",     tag:"mo", output:"\u2202", ttype:CONST}, 
     1308{input:"\\nabla",       tag:"mo", output:"\u2207", ttype:CONST}, 
     1309{input:"\\triangle",    tag:"mo", output:"\u25B3", ttype:CONST}, 
     1310{input:"\\therefore",   tag:"mo", output:"\u2234", ttype:CONST}, 
     1311{input:"\\angle",       tag:"mo", output:"\u2220", ttype:CONST}, 
     1312//{input:"\\\\ ",         tag:"mo", output:"\u00A0", ttype:CONST}, 
     1313{input:"\\diamond",     tag:"mo", output:"\u22C4", ttype:CONST}, 
     1314//{input:"\\Diamond",     tag:"mo", output:"\u25CA", ttype:CONST}, 
     1315{input:"\\Diamond",     tag:"mo", output:"\u25C7", ttype:CONST}, 
     1316{input:"\\neg",         tag:"mo", output:"\u00AC", ttype:CONST}, 
     1317{input:"\\lnot",        tag:"mo", output:"\u00AC", ttype:CONST}, 
     1318{input:"\\bot",         tag:"mo", output:"\u22A5", ttype:CONST}, 
     1319{input:"\\top",         tag:"mo", output:"\u22A4", ttype:CONST}, 
     1320{input:"\\square",      tag:"mo", output:"\u25AB", ttype:CONST}, 
     1321{input:"\\Box",         tag:"mo", output:"\u25A1", ttype:CONST}, 
     1322{input:"\\wr",          tag:"mo", output:"\u2240", ttype:CONST}, 
     1323 
     1324//standard functions 
     1325//Note UNDEROVER *must* have tag:"mo" to work properly 
     1326{input:"\\arccos", tag:"mi", output:"arccos", ttype:UNARY, func:true}, 
     1327{input:"\\arcsin", tag:"mi", output:"arcsin", ttype:UNARY, func:true}, 
     1328{input:"\\arctan", tag:"mi", output:"arctan", ttype:UNARY, func:true}, 
     1329{input:"\\arg",    tag:"mi", output:"arg",    ttype:UNARY, func:true}, 
     1330{input:"\\cos",    tag:"mi", output:"cos",    ttype:UNARY, func:true}, 
     1331{input:"\\cosh",   tag:"mi", output:"cosh",   ttype:UNARY, func:true}, 
     1332{input:"\\cot",    tag:"mi", output:"cot",    ttype:UNARY, func:true}, 
     1333{input:"\\coth",   tag:"mi", output:"coth",   ttype:UNARY, func:true}, 
     1334{input:"\\csc",    tag:"mi", output:"csc",    ttype:UNARY, func:true}, 
     1335{input:"\\deg",    tag:"mi", output:"deg",    ttype:UNARY, func:true}, 
     1336{input:"\\det",    tag:"mi", output:"det",    ttype:UNARY, func:true}, 
     1337{input:"\\dim",    tag:"mi", output:"dim",    ttype:UNARY, func:true}, //CONST? 
     1338{input:"\\exp",    tag:"mi", output:"exp",    ttype:UNARY, func:true}, 
     1339{input:"\\gcd",    tag:"mi", output:"gcd",    ttype:UNARY, func:true}, //CONST? 
     1340{input:"\\hom",    tag:"mi", output:"hom",    ttype:UNARY, func:true}, 
     1341{input:"\\inf",       tag:"mo", output:"inf",    ttype:UNDEROVER}, 
     1342{input:"\\ker",    tag:"mi", output:"ker",    ttype:UNARY, func:true}, 
     1343{input:"\\lg",     tag:"mi", output:"lg",     ttype:UNARY, func:true}, 
     1344{input:"\\lim",       tag:"mo", output:"lim",    ttype:UNDEROVER}, 
     1345{input:"\\liminf",    tag:"mo", output:"liminf", ttype:UNDEROVER}, 
     1346{input:"\\limsup",    tag:"mo", output:"limsup", ttype:UNDEROVER}, 
     1347{input:"\\ln",     tag:"mi", output:"ln",     ttype:UNARY, func:true}, 
     1348{input:"\\log",    tag:"mi", output:"log",    ttype:UNARY, func:true}, 
     1349{input:"\\max",       tag:"mo", output:"max",    ttype:UNDEROVER}, 
     1350{input:"\\min",       tag:"mo", output:"min",    ttype:UNDEROVER}, 
     1351{input:"\\Pr",     tag:"mi", output:"Pr",     ttype:UNARY, func:true}, 
     1352{input:"\\sec",    tag:"mi", output:"sec",    ttype:UNARY, func:true}, 
     1353{input:"\\sin",    tag:"mi", output:"sin",    ttype:UNARY, func:true}, 
     1354{input:"\\sinh",   tag:"mi", output:"sinh",   ttype:UNARY, func:true}, 
     1355{input:"\\sup",       tag:"mo", output:"sup",    ttype:UNDEROVER}, 
     1356{input:"\\tan",    tag:"mi", output:"tan",    ttype:UNARY, func:true}, 
     1357{input:"\\tanh",   tag:"mi", output:"tanh",   ttype:UNARY, func:true}, 
     1358 
     1359//arrows 
     1360{input:"\\gets",                tag:"mo", output:"\u2190", ttype:CONST}, 
     1361{input:"\\leftarrow",           tag:"mo", output:"\u2190", ttype:CONST}, 
     1362{input:"\\to",                  tag:"mo", output:"\u2192", ttype:CONST}, 
     1363{input:"\\rightarrow",          tag:"mo", output:"\u2192", ttype:CONST}, 
     1364{input:"\\leftrightarrow",      tag:"mo", output:"\u2194", ttype:CONST}, 
     1365{input:"\\uparrow",             tag:"mo", output:"\u2191", ttype:CONST}, 
     1366{input:"\\downarrow",           tag:"mo", output:"\u2193", ttype:CONST}, 
     1367{input:"\\updownarrow",         tag:"mo", output:"\u2195", ttype:CONST}, 
     1368{input:"\\Leftarrow",           tag:"mo", output:"\u21D0", ttype:CONST}, 
     1369{input:"\\Rightarrow",          tag:"mo", output:"\u21D2", ttype:CONST}, 
     1370{input:"\\Leftrightarrow",      tag:"mo", output:"\u21D4", ttype:CONST}, 
     1371{input:"\\iff", tag:"mo", output:"~\\Longleftrightarrow~", ttype:DEFINITION}, 
     1372{input:"\\Uparrow",             tag:"mo", output:"\u21D1", ttype:CONST}, 
     1373{input:"\\Downarrow",           tag:"mo", output:"\u21D3", ttype:CONST}, 
     1374{input:"\\Updownarrow",         tag:"mo", output:"\u21D5", ttype:CONST}, 
     1375{input:"\\mapsto",              tag:"mo", output:"\u21A6", ttype:CONST}, 
     1376{input:"\\longleftarrow",       tag:"mo", output:"\u2190", ttype:LONG}, 
     1377{input:"\\longrightarrow",      tag:"mo", output:"\u2192", ttype:LONG}, 
     1378{input:"\\longleftrightarrow",  tag:"mo", output:"\u2194", ttype:LONG}, 
     1379{input:"\\Longleftarrow",       tag:"mo", output:"\u21D0", ttype:LONG}, 
     1380{input:"\\Longrightarrow",      tag:"mo", output:"\u21D2", ttype:LONG}, 
     1381{input:"\\implies",             tag:"mo", output:"\u21D2", ttype:LONG}, 
     1382{input:"\\Longleftrightarrow",  tag:"mo", output:"\u21D4", ttype:LONG}, 
     1383{input:"\\longmapsto",          tag:"mo", output:"\u21A6", ttype:CONST}, 
     1384                                                        // disaster if LONG 
     1385 
     1386//commands with argument 
     1387 
     1388{input:"\\sqrt",        tag:"msqrt", output:"sqrt",     ttype:UNARY}, 
     1389{input:"\\root",        tag:"mroot", output:"root",     ttype:BINARY}, 
     1390{input:"\\frac",        tag:"mfrac", output:"/",        ttype:BINARY}, 
     1391{input:"\\stackrel",    tag:"mover", output:"stackrel", ttype:BINARY}, 
     1392{input:"\\atop",        tag:"mfrac", output:"",         ttype:INFIX}, 
     1393{input:"\\choose",      tag:"mfrac", output:"",         ttype:INFIX}, 
     1394{input:"_",             tag:"msub",  output:"_",        ttype:INFIX}, 
     1395{input:"^",             tag:"msup",  output:"^",        ttype:INFIX}, 
     1396{input:"\\mathrm",      tag:"mtext", output:"text",     ttype:TEXT}, 
     1397{input:"\\mbox",        tag:"mtext", output:"mbox",     ttype:TEXT}, 
     1398 
     1399//diacritical marks 
     1400{input:"\\acute",       tag:"mover",  output:"\u00B4", ttype:UNARY, acc:true}, 
     1401//{input:"\\acute",       tag:"mover",  output:"\u0317", ttype:UNARY, acc:true}, 
     1402//{input:"\\acute",       tag:"mover",  output:"\u0301", ttype:UNARY, acc:true}, 
     1403//{input:"\\grave",       tag:"mover",  output:"\u0300", ttype:UNARY, acc:true}, 
     1404//{input:"\\grave",       tag:"mover",  output:"\u0316", ttype:UNARY, acc:true}, 
     1405{input:"\\grave",       tag:"mover",  output:"\u0060", ttype:UNARY, acc:true}, 
     1406{input:"\\breve",       tag:"mover",  output:"\u02D8", ttype:UNARY, acc:true}, 
     1407{input:"\\check",       tag:"mover",  output:"\u02C7", ttype:UNARY, acc:true}, 
     1408{input:"\\dot",         tag:"mover",  output:".",      ttype:UNARY, acc:true}, 
     1409{input:"\\ddot",        tag:"mover",  output:"..",     ttype:UNARY, acc:true}, 
     1410//{input:"\\ddot",        tag:"mover",  output:"\u00A8", ttype:UNARY, acc:true}, 
     1411{input:"\\mathring",    tag:"mover",  output:"\u00B0", ttype:UNARY, acc:true}, 
     1412{input:"\\vec",         tag:"mover",  output:"\u20D7", ttype:UNARY, acc:true}, 
     1413{input:"\\overrightarrow",tag:"mover",output:"\u20D7", ttype:UNARY, acc:true}, 
     1414{input:"\\overleftarrow",tag:"mover", output:"\u20D6", ttype:UNARY, acc:true}, 
     1415{input:"\\hat",         tag:"mover",  output:"\u005E", ttype:UNARY, acc:true}, 
     1416{input:"\\widehat",     tag:"mover",  output:"\u0302", ttype:UNARY, acc:true}, 
     1417{input:"\\tilde",       tag:"mover",  output:"~",      ttype:UNARY, acc:true}, 
     1418//{input:"\\tilde",       tag:"mover",  output:"\u0303", ttype:UNARY, acc:true}, 
     1419{input:"\\widetilde",   tag:"mover",  output:"\u02DC", ttype:UNARY, acc:true}, 
     1420{input:"\\bar",         tag:"mover",  output:"\u203E", ttype:UNARY, acc:true}, 
     1421{input:"\\overbrace",   tag:"mover",  output:"\u23B4", ttype:UNARY, acc:true}, 
     1422{input:"\\overline",    tag:"mover",  output:"\u00AF", ttype:UNARY, acc:true}, 
     1423{input:"\\underbrace",  tag:"munder", output:"\u23B5", ttype:UNARY, acc:true}, 
     1424{input:"\\underline",   tag:"munder", output:"\u00AF", ttype:UNARY, acc:true}, 
     1425//{input:"underline",   tag:"munder", output:"\u0332", ttype:UNARY, acc:true}, 
     1426 
     1427//typestyles and fonts 
     1428{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true", ttype:UNARY}, 
     1429{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false", ttype:UNARY}, 
     1430{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1", ttype:UNARY}, 
     1431{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2", ttype:UNARY}, 
     1432{input:"\\textrm", tag:"mstyle", output:"\\mathrm", ttype: DEFINITION}, 
     1433{input:"\\mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY}, 
     1434{input:"\\textbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY}, 
     1435{input:"\\mathit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY}, 
     1436{input:"\\textit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY}, 
     1437{input:"\\mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY}, 
     1438{input:"\\texttt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY}, 
     1439{input:"\\mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", ttype:UNARY}, 
     1440{input:"\\mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", ttype:UNARY, codes:AMbbb}, 
     1441{input:"\\mathcal",tag:"mstyle", atname:"mathvariant", atval:"script", ttype:UNARY, codes:AMcal}, 
     1442{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant", atval:"fraktur",ttype:UNARY, codes:AMfrk} 
     1443]; 
     1444 
     1445var LMnames = []; //list of input symbols 
     1446 
     1447function LMremoveCharsAndBlanks(str,n) { 
     1448//remove n characters and any following blanks 
     1449  var st; 
     1450  st = str.slice(n); 
     1451  for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1); 
     1452  return st.slice(i); 
     1453} 
     1454 
     1455function LMgetSymbol(str) { 
     1456//return maximal initial substring of str that appears in names 
     1457//return null if there is none 
     1458  var k = 0; //new pos 
     1459  var j = 0; //old pos 
     1460  var mk; //match pos 
     1461  var st; 
     1462  var tagst; 
     1463  var match = ""; 
     1464  var more = true; 
     1465  for (var i=1; i<=str.length && more; i++) { 
     1466    st = str.slice(0,i); //initial substring of length i 
     1467    j = k; 
     1468    k = position(LMnames, st, j); 
     1469    if (k<LMnames.length && str.slice(0,LMnames[k].length)==LMnames[k]){ 
     1470      match = LMnames[k]; 
     1471      mk = k; 
     1472      i = match.length; 
     1473    } 
     1474    more = k<LMnames.length && str.slice(0,LMnames[k].length)>=LMnames[k]; 
     1475  } 
     1476  LMpreviousSymbol=LMcurrentSymbol; 
     1477  if (match!=""){ 
     1478    LMcurrentSymbol=LMsymbols[mk].ttype; 
     1479    return LMsymbols[mk]; 
     1480  } 
     1481  LMcurrentSymbol=CONST; 
     1482  k = 1; 
     1483  st = str.slice(0,1); //take 1 character 
     1484  if ("0"<=st && st<="9") tagst = "mn"; 
     1485  else tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi"); 
     1486/* 
     1487// Commented out by DRW (not fully understood, but probably to do with 
     1488// use of "/" as an INFIX version of "\\frac", which we don't want): 
     1489//} 
     1490//if (st=="-" && LMpreviousSymbol==INFIX) { 
     1491//  LMcurrentSymbol = INFIX;  //trick "/" into recognizing "-" on second parse 
     1492//  return {input:st, tag:tagst, output:st, ttype:UNARY, func:true}; 
     1493//} 
     1494*/ 
     1495  return {input:st, tag:tagst, output:st, ttype:CONST}; 
     1496} 
     1497 
     1498 
     1499/*Parsing ASCII math expressions with the following grammar 
     1500v ::= [A-Za-z] | greek letters | numbers | other constant symbols 
     1501u ::= sqrt | text | bb | other unary symbols for font commands 
     1502b ::= frac | root | stackrel    binary symbols 
     1503l ::= { | \left                 left brackets 
     1504r ::= } | \right                right brackets 
     1505S ::= v | lEr | uS | bSS        Simple expression 
     1506I ::= S_S | S^S | S_S^S | S     Intermediate expression 
     1507E ::= IE | I/I                  Expression 
     1508Each terminal symbol is translated into a corresponding mathml node.*/ 
     1509 
     1510var LMpreviousSymbol,LMcurrentSymbol; 
     1511 
     1512function LMparseSexpr(str) { //parses str and returns [node,tailstr,(node)tag] 
     1513  var symbol, node, result, result2, i, st,// rightvert = false, 
     1514    newFrag = document.createDocumentFragment(); 
     1515  str = LMremoveCharsAndBlanks(str,0); 
     1516  symbol = LMgetSymbol(str);             //either a token or a bracket or empty 
     1517  if (symbol == null || symbol.ttype == RIGHTBRACKET) 
     1518    return [null,str,null]; 
     1519  if (symbol.ttype == DEFINITION) { 
     1520    str = symbol.output+LMremoveCharsAndBlanks(str,symbol.input.length); 
     1521    symbol = LMgetSymbol(str); 
     1522    if (symbol == null || symbol.ttype == RIGHTBRACKET) 
     1523      return [null,str,null]; 
     1524  } 
     1525  str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1526  switch (symbol.ttype) { 
     1527  case SPACE: 
     1528    node = createMmlNode(symbol.tag); 
     1529    node.setAttribute(symbol.atname,symbol.atval); 
     1530    return [node,str,symbol.tag]; 
     1531  case UNDEROVER: 
     1532    if (isIE) { 
     1533      if (symbol.input.substr(0,4) == "\\big") {   // botch for missing symbols 
     1534        str = "\\"+symbol.input.substr(4)+str;     // make \bigcup = \cup etc. 
     1535        symbol = LMgetSymbol(str); 
     1536        symbol.ttype = UNDEROVER; 
     1537        str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1538      } 
     1539    } 
     1540    return [createMmlNode(symbol.tag, 
     1541                        document.createTextNode(symbol.output)),str,symbol.tag]; 
     1542  case CONST: 
     1543    var output = symbol.output; 
     1544    if (isIE) { 
     1545      if (symbol.input == "'") 
     1546        output = "\u2032"; 
     1547      else if (symbol.input == "''") 
     1548        output = "\u2033"; 
     1549      else if (symbol.input == "'''") 
     1550        output = "\u2033\u2032"; 
     1551      else if (symbol.input == "''''") 
     1552        output = "\u2033\u2033"; 
     1553      else if (symbol.input == "\\square") 
     1554        output = "\u25A1";      // same as \Box 
     1555      else if (symbol.input.substr(0,5) == "\\frac") { 
     1556                                                // botch for missing fractions 
     1557        var denom = symbol.input.substr(6,1); 
     1558        if (denom == "5" || denom == "6") { 
     1559          str = symbol.input.replace(/\\frac/,"\\frac ")+str; 
     1560          return [node,str,symbol.tag]; 
     1561        } 
     1562      } 
     1563    } 
     1564    node = createMmlNode(symbol.tag,document.createTextNode(output)); 
     1565    return [node,str,symbol.tag]; 
     1566  case LONG:  // added by DRW 
     1567    node = createMmlNode(symbol.tag,document.createTextNode(symbol.output)); 
     1568    node.setAttribute("minsize","1.5"); 
     1569    node.setAttribute("maxsize","1.5"); 
     1570    node = createMmlNode("mover",node); 
     1571    node.appendChild(createMmlNode("mspace")); 
     1572    return [node,str,symbol.tag]; 
     1573  case STRETCHY:  // added by DRW 
     1574    if (isIE && symbol.input == "\\backslash") 
     1575        symbol.output = "\\";   // doesn't expand, but then nor does "\u2216" 
     1576    node = createMmlNode(symbol.tag,document.createTextNode(symbol.output)); 
     1577    if (symbol.input == "|" || symbol.input == "\\vert" || 
     1578        symbol.input == "\\|" || symbol.input == "\\Vert") { 
     1579          node.setAttribute("lspace","0em"); 
     1580          node.setAttribute("rspace","0em"); 
     1581    } 
     1582    node.setAttribute("maxsize",symbol.atval);  // don't allow to stretch here 
     1583    if (symbol.rtag != null) 
     1584      return [node,str,symbol.rtag]; 
     1585    else 
     1586      return [node,str,symbol.tag]; 
     1587  case BIG:  // added by DRW 
     1588    var atval = symbol.atval; 
     1589    if (isIE) 
     1590      atval = symbol.ieval; 
     1591    symbol = LMgetSymbol(str); 
     1592    if (symbol == null) 
     1593        return [null,str,null]; 
     1594    str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1595    node = createMmlNode(symbol.tag,document.createTextNode(symbol.output)); 
     1596    if (isIE) {         // to get brackets to expand 
     1597      var space = createMmlNode("mspace"); 
     1598      space.setAttribute("height",atval+"ex"); 
     1599      node = createMmlNode("mrow",node); 
     1600      node.appendChild(space); 
     1601    } else {            // ignored in IE 
     1602      node.setAttribute("minsize",atval); 
     1603      node.setAttribute("maxsize",atval); 
     1604    } 
     1605    return [node,str,symbol.tag]; 
     1606  case LEFTBRACKET:   //read (expr+) 
     1607    if (symbol.input == "\\left") { // left what? 
     1608      symbol = LMgetSymbol(str); 
     1609      if (symbol != null) { 
     1610        if (symbol.input == ".") 
     1611          symbol.invisible = true; 
     1612        str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1613      } 
     1614    } 
     1615    result = LMparseExpr(str,true,false); 
     1616    if (symbol==null || 
     1617        (typeof symbol.invisible == "boolean" && symbol.invisible)) 
     1618      node = createMmlNode("mrow",result[0]); 
     1619    else { 
     1620      node = createMmlNode("mo",document.createTextNode(symbol.output)); 
     1621      node = createMmlNode("mrow",node); 
     1622      node.appendChild(result[0]); 
     1623    } 
     1624    return [node,result[1],result[2]]; 
     1625  case MATRIX:   //read (expr+) 
     1626    if (symbol.input == "\\begin{array}") { 
     1627      var mask = ""; 
     1628      symbol = LMgetSymbol(str); 
     1629      str = LMremoveCharsAndBlanks(str,0); 
     1630      if (symbol == null) 
     1631        mask = "l"; 
     1632      else { 
     1633        str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1634        if (symbol.input != "{") 
     1635          mask = "l"; 
     1636        else do { 
     1637          symbol = LMgetSymbol(str); 
     1638          if (symbol != null) { 
     1639            str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1640            if (symbol.input != "}") 
     1641              mask = mask+symbol.input; 
     1642          } 
     1643        } while (symbol != null && symbol.input != "" && symbol.input != "}"); 
     1644      } 
     1645      result = LMparseExpr("{"+str,true,true); 
     1646//    if (result[0]==null) return [createMmlNode("mo", 
     1647//                         document.createTextNode(symbol.input)),str]; 
     1648      node = createMmlNode("mtable",result[0]); 
     1649      mask = mask.replace(/l/g,"left "); 
     1650      mask = mask.replace(/r/g,"right "); 
     1651      mask = mask.replace(/c/g,"center "); 
     1652      node.setAttribute("columnalign",mask); 
     1653      node.setAttribute("displaystyle","false"); 
     1654      if (isIE) 
     1655        return [node,result[1],null]; 
     1656// trying to get a *little* bit of space around the array 
     1657// (IE already includes it) 
     1658      var lspace = createMmlNode("mspace"); 
     1659      lspace.setAttribute("width","0.167em"); 
     1660      var rspace = createMmlNode("mspace"); 
     1661      rspace.setAttribute("width","0.167em"); 
     1662      var node1 = createMmlNode("mrow",lspace); 
     1663      node1.appendChild(node); 
     1664      node1.appendChild(rspace); 
     1665      return [node1,result[1],null]; 
     1666    } else {    // eqnarray 
     1667      result = LMparseExpr("{"+str,true,true); 
     1668      node = createMmlNode("mtable",result[0]); 
     1669      if (isIE) 
     1670        node.setAttribute("columnspacing","0.25em"); // best in practice? 
     1671      else 
     1672        node.setAttribute("columnspacing","0.167em"); // correct (but ignored?) 
     1673      node.setAttribute("columnalign","right center left"); 
     1674      node.setAttribute("displaystyle","true"); 
     1675      node = createMmlNode("mrow",node); 
     1676      return [node,result[1],null]; 
     1677    } 
     1678  case TEXT: 
     1679      if (str.charAt(0)=="{") i=str.indexOf("}"); 
     1680      else i = 0; 
     1681      if (i==-1) 
     1682                 i = str.length; 
     1683      st = str.slice(1,i); 
     1684      if (st.charAt(0) == " ") { 
     1685        node = createMmlNode("mspace"); 
     1686        node.setAttribute("width","0.33em");    // was 1ex 
     1687        newFrag.appendChild(node); 
     1688      } 
     1689      newFrag.appendChild( 
     1690        createMmlNode(symbol.tag,document.createTextNode(st))); 
     1691      if (st.charAt(st.length-1) == " ") { 
     1692        node = createMmlNode("mspace"); 
     1693        node.setAttribute("width","0.33em");    // was 1ex 
     1694        newFrag.appendChild(node); 
     1695      } 
     1696      str = LMremoveCharsAndBlanks(str,i+1); 
     1697      return [createMmlNode("mrow",newFrag),str,null]; 
     1698  case UNARY: 
     1699      result = LMparseSexpr(str); 
     1700      if (result[0]==null) return [createMmlNode(symbol.tag, 
     1701                             document.createTextNode(symbol.output)),str]; 
     1702      if (typeof symbol.func == "boolean" && symbol.func) { // functions hack 
     1703        st = str.charAt(0); 
     1704//      if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") { 
     1705        if (st=="^" || st=="_" || st==",") { 
     1706          return [createMmlNode(symbol.tag, 
     1707                    document.createTextNode(symbol.output)),str,symbol.tag]; 
     1708        } else { 
     1709          node = createMmlNode("mrow", 
     1710           createMmlNode(symbol.tag,document.createTextNode(symbol.output))); 
     1711          if (isIE) { 
     1712            var space = createMmlNode("mspace"); 
     1713            space.setAttribute("width","0.167em"); 
     1714            node.appendChild(space); 
     1715          } 
     1716          node.appendChild(result[0]); 
     1717          return [node,result[1],symbol.tag]; 
     1718        } 
     1719      } 
     1720      if (symbol.input == "\\sqrt") {           // sqrt 
     1721        if (isIE) {     // set minsize, for \surd 
     1722          var space = createMmlNode("mspace"); 
     1723          space.setAttribute("height","1.2ex"); 
     1724          space.setAttribute("width","0em");    // probably no effect 
     1725          node = createMmlNode(symbol.tag,result[0]) 
     1726//        node.setAttribute("minsize","1");     // ignored 
     1727//        node = createMmlNode("mrow",node);  // hopefully unnecessary 
     1728          node.appendChild(space); 
     1729          return [node,result[1],symbol.tag]; 
     1730        } else 
     1731          return [createMmlNode(symbol.tag,result[0]),result[1],symbol.tag]; 
     1732      } else if (typeof symbol.acc == "boolean" && symbol.acc) {   // accent 
     1733        node = createMmlNode(symbol.tag,result[0]); 
     1734        var output = symbol.output; 
     1735        if (isIE) { 
     1736                if (symbol.input == "\\hat") 
     1737                        output = "\u0302"; 
     1738                else if (symbol.input == "\\widehat") 
     1739                        output = "\u005E"; 
     1740                else if (symbol.input == "\\bar") 
     1741                        output = "\u00AF"; 
     1742                else if (symbol.input == "\\grave") 
     1743                        output = "\u0300"; 
     1744                else if (symbol.input == "\\tilde") 
     1745                        output = "\u0303"; 
     1746        } 
     1747        var node1 = createMmlNode("mo",document.createTextNode(output)); 
     1748        if (symbol.input == "\\vec" || symbol.input == "\\check") 
     1749                                                // don't allow to stretch 
     1750            node1.setAttribute("maxsize","1.2"); 
     1751                 // why doesn't "1" work?  \vec nearly disappears in firefox 
     1752        if (isIE && symbol.input == "\\bar") 
     1753            node1.setAttribute("maxsize","0.5"); 
     1754        if (symbol.input == "\\underbrace" || symbol.input == "\\underline") 
     1755          node1.setAttribute("accentunder","true"); 
     1756        else 
     1757          node1.setAttribute("accent","true"); 
     1758        node.appendChild(node1); 
     1759        if (symbol.input == "\\overbrace" || symbol.input == "\\underbrace") 
     1760          node.ttype = UNDEROVER; 
     1761        return [node,result[1],symbol.tag]; 
     1762      } else {                        // font change or displaystyle command 
     1763        if (!isIE && typeof symbol.codes != "undefined") { 
     1764          for (i=0; i<result[0].childNodes.length; i++) 
     1765            if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") { 
     1766              st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue: 
     1767                              result[0].childNodes[i].firstChild.nodeValue); 
     1768              var newst = []; 
     1769              for (var j=0; j<st.length; j++) 
     1770                if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst + 
     1771                  String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]); 
     1772                else newst = newst + st.charAt(j); 
     1773              if (result[0].nodeName=="mi") 
     1774                result[0]=createMmlNode("mo"). 
     1775                          appendChild(document.createTextNode(newst)); 
     1776              else result[0].replaceChild(createMmlNode("mo"). 
     1777          appendChild(document.createTextNode(newst)),result[0].childNodes[i]); 
     1778            } 
     1779        } 
     1780        node = createMmlNode(symbol.tag,result[0]); 
     1781        node.setAttribute(symbol.atname,symbol.atval); 
     1782        if (symbol.input == "\\scriptstyle" || 
     1783            symbol.input == "\\scriptscriptstyle") 
     1784                node.setAttribute("displaystyle","false"); 
     1785        return [node,result[1],symbol.tag]; 
     1786      } 
     1787  case BINARY: 
     1788    result = LMparseSexpr(str); 
     1789    if (result[0]==null) return [createMmlNode("mo", 
     1790                           document.createTextNode(symbol.input)),str,null]; 
     1791    result2 = LMparseSexpr(result[1]); 
     1792    if (result2[0]==null) return [createMmlNode("mo", 
     1793                           document.createTextNode(symbol.input)),str,null]; 
     1794    if (symbol.input=="\\root" || symbol.input=="\\stackrel") 
     1795      newFrag.appendChild(result2[0]); 
     1796    newFrag.appendChild(result[0]); 
     1797    if (symbol.input=="\\frac") newFrag.appendChild(result2[0]); 
     1798    return [createMmlNode(symbol.tag,newFrag),result2[1],symbol.tag]; 
     1799  case INFIX: 
     1800    str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1801    return [createMmlNode("mo",document.createTextNode(symbol.output)), 
     1802        str,symbol.tag]; 
     1803  default: 
     1804    return [createMmlNode(symbol.tag,        //its a constant 
     1805        document.createTextNode(symbol.output)),str,symbol.tag]; 
     1806  } 
     1807} 
     1808 
     1809function LMparseIexpr(str) { 
     1810  var symbol, sym1, sym2, node, result, tag, underover; 
     1811  str = LMremoveCharsAndBlanks(str,0); 
     1812  sym1 = LMgetSymbol(str); 
     1813  result = LMparseSexpr(str); 
     1814  node = result[0]; 
     1815  str = result[1]; 
     1816  tag = result[2]; 
     1817  symbol = LMgetSymbol(str); 
     1818  if (symbol.ttype == INFIX) { 
     1819    str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1820    result = LMparseSexpr(str); 
     1821    if (result[0] == null) // show box in place of missing argument 
     1822      result[0] = createMmlNode("mo",document.createTextNode("\u25A1")); 
     1823    str = result[1]; 
     1824    tag = result[2]; 
     1825    if (symbol.input == "_" || symbol.input == "^") { 
     1826      sym2 = LMgetSymbol(str); 
     1827      tag = null;       // no space between x^2 and a following sin, cos, etc. 
     1828// This is for \underbrace and \overbrace 
     1829      underover = ((sym1.ttype == UNDEROVER) || (node.ttype == UNDEROVER)); 
     1830//    underover = (sym1.ttype == UNDEROVER); 
     1831      if (symbol.input == "_" && sym2.input == "^") { 
     1832        str = LMremoveCharsAndBlanks(str,sym2.input.length); 
     1833        var res2 = LMparseSexpr(str); 
     1834        str = res2[1]; 
     1835        tag = res2[2];  // leave space between x_1^2 and a following sin etc. 
     1836        node = createMmlNode((underover?"munderover":"msubsup"),node); 
     1837        node.appendChild(result[0]); 
     1838        node.appendChild(res2[0]); 
     1839      } else if (symbol.input == "_") { 
     1840        node = createMmlNode((underover?"munder":"msub"),node); 
     1841        node.appendChild(result[0]); 
     1842      } else { 
     1843        node = createMmlNode((underover?"mover":"msup"),node); 
     1844        node.appendChild(result[0]); 
     1845      } 
     1846      node = createMmlNode("mrow",node); // so sum does not stretch 
     1847    } else { 
     1848      node = createMmlNode(symbol.tag,node); 
     1849      if (symbol.input == "\\atop" || symbol.input == "\\choose") 
     1850        node.setAttribute("linethickness","0ex"); 
     1851      node.appendChild(result[0]); 
     1852      if (symbol.input == "\\choose") 
     1853        node = createMmlNode("mfenced",node); 
     1854    } 
     1855  } 
     1856  return [node,str,tag]; 
     1857} 
     1858 
     1859function LMparseExpr(str,rightbracket,matrix) { 
     1860  var symbol, node, result, i, tag, 
     1861  newFrag = document.createDocumentFragment(); 
     1862  do { 
     1863    str = LMremoveCharsAndBlanks(str,0); 
     1864    result = LMparseIexpr(str); 
     1865    node = result[0]; 
     1866    str = result[1]; 
     1867    tag = result[2]; 
     1868    symbol = LMgetSymbol(str); 
     1869    if (node!=undefined) { 
     1870      if ((tag == "mn" || tag == "mi") && symbol!=null && 
     1871        typeof symbol.func == "boolean" && symbol.func) { 
     1872                        // Add space before \sin in 2\sin x or x\sin x 
     1873          var space = createMmlNode("mspace"); 
     1874          space.setAttribute("width","0.167em"); 
     1875          node = createMmlNode("mrow",node); 
     1876          node.appendChild(space); 
     1877      } 
     1878      newFrag.appendChild(node); 
     1879    } 
     1880  } while ((symbol.ttype != RIGHTBRACKET) 
     1881        && symbol!=null && symbol.output!=""); 
     1882  tag = null; 
     1883  if (symbol.ttype == RIGHTBRACKET) { 
     1884    if (symbol.input == "\\right") { // right what? 
     1885      str = LMremoveCharsAndBlanks(str,symbol.input.length); 
     1886      symbol = LMgetSymbol(str); 
     1887      if (symbol != null && symbol.input == ".") 
     1888        symbol.invisible = true; 
     1889      if (symbol != null) 
     1890        tag = symbol.rtag; 
     1891    } 
     1892    if (symbol!=null) 
     1893      str = LMremoveCharsAndBlanks(str,symbol.input.length); // ready to return 
     1894    var len = newFrag.childNodes.length; 
     1895    if (matrix && 
     1896      len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 && 
     1897      newFrag.childNodes[len-2].nodeName == "mo" && 
     1898      newFrag.childNodes[len-2].firstChild.nodeValue == "&") { //matrix 
     1899        var pos = []; // positions of ampersands 
     1900        var m = newFrag.childNodes.length; 
     1901        for (i=0; matrix && i<m; i=i+2) { 
     1902          pos[i] = []; 
     1903          node = newFrag.childNodes[i]; 
     1904          for (var j=0; j<node.childNodes.length; j++) 
     1905            if (node.childNodes[j].firstChild.nodeValue=="&") 
     1906              pos[i][pos[i].length]=j; 
     1907        } 
     1908        var row, frag, n, k, table = document.createDocumentFragment(); 
     1909        for (i=0; i<m; i=i+2) { 
     1910          row = document.createDocumentFragment(); 
     1911          frag = document.createDocumentFragment(); 
     1912          node = newFrag.firstChild; // <mrow> -&-&...&-&- </mrow> 
     1913          n = node.childNodes.length; 
     1914          k = 0; 
     1915          for (j=0; j<n; j++) { 
     1916            if (typeof pos[i][k] != "undefined" && j==pos[i][k]){ 
     1917              node.removeChild(node.firstChild); //remove & 
     1918              row.appendChild(createMmlNode("mtd",frag)); 
     1919              k++; 
     1920            } else frag.appendChild(node.firstChild); 
     1921          } 
     1922          row.appendChild(createMmlNode("mtd",frag)); 
     1923          if (newFrag.childNodes.length>2) { 
     1924            newFrag.removeChild(newFrag.firstChild); //remove <mrow> </mrow> 
     1925            newFrag.removeChild(newFrag.firstChild); //remove <mo>&</mo> 
     1926          } 
     1927          table.appendChild(createMmlNode("mtr",row)); 
     1928        } 
     1929        return [table,str]; 
     1930    } 
     1931    if (typeof symbol.invisible != "boolean" || !symbol.invisible) { 
     1932      node = createMmlNode("mo",document.createTextNode(symbol.output)); 
     1933      newFrag.appendChild(node); 
     1934    } 
     1935  } 
     1936  return [newFrag,str,tag]; 
     1937} 
     1938 
     1939var tcnt = 0, dcnt = 0; //theorem and definition counters 
     1940 
     1941function simpleLaTeXformatting(st) { 
     1942  st = st.replace(/\$\$((.|\n)*?)\$\$/g,"<p align=\"center\">$\\displaystyle{$1}$</p>"); 
     1943  st = st.replace(/\\begin{(theorem|lemma|proposition|corollary)}((.|\n)*?)\\end{\1}/g,function(r,s,t){tcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+tcnt+".</b> <i>"+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+"</i>"}); 
     1944  st = st.replace(/\\begin{(definition|example|remark|problem|exercise|conjecture|solution)}((.|\n)*?)\\end{\1}/g,function(r,s,t){dcnt++; return "<b>"+s.charAt(0).toUpperCase()+s.slice(1)+" "+dcnt+".</b> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")}); 
     1945  st = st.replace(/\\begin{proof}((.|\n)*?)\\end{proof}/g,function(s,t){return "<i>Proof:</i> "+t.replace(/^\s*<\/?\w+\/?>|\s*<\/?\w+\/?>$/g,"")+" &#x25A1;"}); 
     1946  st = st.replace(/\\emph{(.*?)}/g,"<em>$1</em>"); 
     1947  st = st.replace(/\\textbf{(.*?)}/g,"<b>$1</b>"); 
     1948  st = st.replace(/\\cite{(.*?)}/g,"[$1]"); 
     1949  st = st.replace(/\\chapter{(.*?)}/g,"<h2>$1</h2>"); 
     1950  st = st.replace(/\\section{(.*?)}(\s*<\/?(br|p)\s?\/?>)?/g,"<h3>$1</h3>"); 
     1951  st = st.replace(/\\subsection{((.|\n)*?)}/g,"<h4>$1</h4>"); 
     1952  st = st.replace(/\\begin{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"<ul>"); 
     1953  st = st.replace(/\\item\s((.|\n)*?)(?=(\\item|\\end))/g,"<li>$1</li>"); 
     1954  st = st.replace(/\\end{itemize}(\s*<\/?(br|p)\s?\/?>)?/g,"</ul>"); 
     1955  st = st.replace(/\\begin{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"<ol>"); 
     1956  st = st.replace(/\\end{enumerate}(\s*<\/?(br|p)\s?\/?>)?/g,"</ol>"); 
     1957  st = st.replace(/\\item\[(.*?)]{(.*?)}/g,"<dt>$1</dt><dd>$2</dd>"); 
     1958  st = st.replace(/\\begin{description}/g,"<dl>"); 
     1959  st = st.replace(/\\end{description}/g,"</dl>"); 
     1960  st = st.replace(/\\newline\b/g,"<br/>"); 
     1961  st = st.replace(/\\newpage\b/g,"<br style=\"page-break-after:always;\">"); 
     1962  st = st.replace(/\\par\b/g,"<p>&nbsp;</p>"); 
     1963  st = st.replace(/\\bigskip/g,"<p style=\"margin-bottom:0.5in\">&nbsp;</p>"); 
     1964  st = st.replace(/\\medskip/g,"<p style=\"margin-bottom:0.3in\">&nbsp;</p>"); 
     1965  st = st.replace(/\\smallskip/g,"<p style=\"margin-bottom:0.15in\">&nbsp;</p>"); 
     1966  st = st.replace(/\\begin{center}((.|\n)*?)\\end{center}/g,"<center>$1</center>"); 
     1967  return st 
     1968} 
     1969 
     1970function ASCIIandgraphformatting(st) { 
     1971  st = st.replace(/<sup>(.*?)<\/sup>(\s|(\S))/gi,"^{$1} $3"); 
     1972//st = st.replace(/<\/?font.*?>/gi,""); // do this only in amath...endamath 
     1973  st = st.replace(/(Proof:)/g,"<i>$1</i>"); 
     1974  st = st.replace(/QED/g,"&nbsp; &nbsp; &#x25A1;"); 
     1975  st = st.replace(/(\\?end{?a?math}?)/ig,"<span></span>$1"); 
     1976  st = st.replace(/(\bamath\b|\\begin{a?math})/ig,"<span></span>$1"); 
     1977  st = st.replace(/([>\n])(Theorem|Lemma|Proposition|Corollary|Definition|Example|Remark|Problem|Exercise|Conjecture|Solution)(:|\W\W?(\w|\s|-|\.)*?\W?:)/g,"$1<b>$2$3</b>"); 
     1978  st = st.replace(/<embed\s+class\s?=\s?"?ASCIIsvg"?/gi,"<embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\""); 
     1979  st = st.replace(/(?:\\begin{a?graph}|\bagraph|\(:graph\s)((.|\n)*?)(?:\\end{a?graph}|enda?graph|:\))/g,function(s,t){return "<table><tr><td><div class=\"ASCIIsvg\"><embed class=\"ASCIIsvg\" src=\""+dsvglocation+"d.svg\" wmode=\"transparent\" script=\'"+t.replace(/<\/?(br|p|pre)\s?\/?>/gi,"\n")+"\'/></div></td></tr></table>"}); 
     1980  st = st.replace(/insertASCIIMathCalculator/g,"<div class=\"ASCIIMathCalculator\"></div>"); 
     1981//alert(dsvglocation) 
     1982  return st 
     1983} 
     1984 
     1985function LMprocessNode(n) { 
     1986  var frag,st; 
     1987  try { 
     1988    st = n.innerHTML; 
     1989  } catch(err) {} 
     1990  var am = /amath\b|graph/i.test(st); 
     1991  if ((st==null || st.indexOf("\$ ")!=-1 || st.indexOf("\$<")!=-1 ||  
     1992       st.indexOf("\\begin")!=-1 || am || st.slice(-1)=="$" || 
     1993       st.indexOf("\$\n")!=-1)&& !/edit-content|HTMLArea|wikiedit|wpTextbox1/.test(st)){ 
     1994    if (!avoidinnerHTML && translateLaTeXformatting)  
     1995      st = simpleLaTeXformatting(st); 
     1996    if (st!=null && am && !avoidinnerHTML) { 
     1997      st = ASCIIandgraphformatting(st); 
     1998    } 
     1999    st = st.replace(/%7E/g,"~"); // else PmWiki has url issues 
     2000//alert(st) 
     2001    if (!avoidinnerHTML) n.innerHTML = st; 
     2002    processNodeR(n,false,true); 
     2003  } 
     2004/*  if (isIE) { //needed to match size and font of formula to surrounding text 
     2005    frag = document.getElementsByTagName('math'); 
     2006    for (var i=0;i<frag.length;i++) frag[i].update() //is this really needed? 
     2007  }*/ 
     2008} 
     2009 
     2010/* ASCIIsvg.js 
     2011============== 
     2012JavaScript routines to dynamically generate Scalable Vector Graphics 
     2013using a mathematical xy-coordinate system (y increases upwards) and 
     2014very intuitive JavaScript commands (no programming experience required). 
     2015ASCIIsvg.js is good for learning math and illustrating online math texts. 
     2016Works with Internet Explorer+Adobe SVGviewer and SVG enabled Mozilla/Firefox. 
     2017 
     2018Ver 1.2.9 July 31, 2007 (c) Peter Jipsen http://www.chapman.edu/~jipsen 
     2019Latest version at http://math.chapman.edu/~jipsen/math/pub/ASCIIsvg.js 
     2020If you use it on a webpage, please send the URL to jipsen@chapman.edu 
     2021 
     2022This program is free software; you can redistribute it and/or modify 
     2023it under the terms of the GNU Lesser General Public License as published by 
     2024the Free Software Foundation; either version 2.1 of the License, or (at 
     2025your option) any later version. 
     2026 
     2027This program is distributed in the hope that it will be useful,  
     2028but WITHOUT ANY WARRANTY; without even the implied warranty of 
     2029MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser 
     2030General Public License (at http://www.gnu.org/license/lgpl.html)  
     2031for more details.*/ 
     2032 
     2033// you can change these 
     2034var checkIfSVGavailable = true; 
     2035var notifyIfNoSVG = true; 
     2036var alertIfNoSVG = false; 
     2037var noSVG = false; 
     2038 
     2039// global defaults used if not specified by graph (you can change these) 
     2040var defaultwidth = 300; defaultheight = 200;   // in pixels 
     2041var defaultxmin = -5.5; defaultxmax = 5.5;     // in usercoords 
     2042var defaultborder = 0; border = defaultborder; // in pixel 
     2043var defaultstrokewidth = "1"; // default line width in pixel 
     2044var defaultstroke = "blue";   // default line color 
     2045var defaultstrokeopacity = 1; // transparent = 0, solid =1 
     2046var defaultstrokedasharray = null; // "10,10" gives 10px long dashes 
     2047var defaultfill = "none";        // default fill color 
     2048var defaultfillopacity = 1;      // transparent = 0, solid =1 
     2049var defaultfontstyle = "normal"; // default text shape normal|italic|inherit 
     2050var defaultfontfamily = "times"; // default font times|ariel|helvetica|... 
     2051var defaultfontsize = "16";      // default size (scaled automatically) 
     2052var defaultfontweight = "normal";// normal|bold|bolder|lighter|100|...|900 
     2053var defaultfontstroke = "none";  // default font outline color 
     2054var defaultfontfill = "none";    // default font color 
     2055var defaultmarker = "none";      // "dot" | "arrow" | "+" | "-" | "|" 
     2056var defaultendpoints = "";       // "c-d" where c is <|o|* and d is >|o|* 
     2057 
     2058// global values used for all pictures (you can change these) 
     2059var showcoordinates = true; 
     2060var markerstrokewidth = "1"; 
     2061var markerstroke = "black"; 
     2062var markerfill = "yellow"; 
     2063var markersize = 4; 
     2064var arrowfill = stroke; 
     2065var dotradius = 4; 
     2066var ticklength = 4; 
     2067var axesstroke = "black"; 
     2068var gridstroke = "grey"; 
     2069var backgroundstyle = "fill-opacity:1; fill:white"; 
     2070var singlelettersitalic = true; 
     2071 
     2072// internal variables (probably no need to change these) 
     2073var picturepos = null; // position of picture relative to top of HTML page 
     2074var xunitlength;       // in pixels, used to convert to user coordinates 
     2075var yunitlength;       // in pixels 
     2076var origin = [0,0];    // in pixels (default is bottom left corner) 
     2077var above = "above";   // shorthands (to avoid typing quotes) 
     2078var below = "below"; 
     2079var left = "left"; 
     2080var right = "right"; 
     2081var aboveleft = "aboveleft"; 
     2082var aboveright = "aboveright"; 
     2083var belowleft = "belowleft"; 
     2084var belowright = "belowright"; 
     2085var xmin, xmax, ymin, ymax, xscl, yscl,  
     2086    xgrid, ygrid, xtick, ytick, initialized; 
     2087var strokewidth, strokedasharray, stroke, fill, strokeopacity, fillopacity; 
     2088var fontstyle, fontfamily, fontsize, fontweight, fontstroke, fontfill; 
     2089var marker, endpoints, dynamic = {}; 
     2090var picture, svgpicture, doc, width, height; 
     2091var isIE = document.createElementNS==null; 
     2092 
     2093var cpi = "\u03C0", ctheta = "\u03B8";      // character for pi, theta 
     2094var log = function(x) { return ln(x)/ln(10) }; 
     2095var pi = Math.PI, e = Math.E, ln = Math.log, sqrt = Math.sqrt; 
     2096var floor = Math.floor, ceil = Math.ceil, abs = Math.abs; 
     2097var sin = Math.sin, cos = Math.cos, tan = Math.tan; 
     2098var arcsin = Math.asin, arccos = Math.acos, arctan = Math.atan; 
     2099var sec = function(x) { return 1/Math.cos(x) }; 
     2100var csc = function(x) { return 1/Math.sin(x) }; 
     2101var cot = function(x) { return 1/Math.tan(x) }; 
     2102var arcsec = function(x) { return arccos(1/x) }; 
     2103var arccsc = function(x) { return arcsin(1/x) }; 
     2104var arccot = function(x) { return arctan(1/x) }; 
     2105var sinh = function(x) { return (Math.exp(x)-Math.exp(-x))/2 }; 
     2106var cosh = function(x) { return (Math.exp(x)+Math.exp(-x))/2 }; 
     2107var tanh =  
     2108  function(x) { return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x)) }; 
     2109var sech = function(x) { return 1/cosh(x) }; 
     2110var csch = function(x) { return 1/sinh(x) }; 
     2111var coth = function(x) { return 1/tanh(x) }; 
     2112var arcsinh = function(x) { return ln(x+Math.sqrt(x*x+1)) }; 
     2113var arccosh = function(x) { return ln(x+Math.sqrt(x*x-1)) }; 
     2114var arctanh = function(x) { return ln((1+x)/(1-x))/2 }; 
     2115var sech = function(x) { return 1/cosh(x) }; 
     2116var csch = function(x) { return 1/sinh(x) }; 
     2117var coth = function(x) { return 1/tanh(x) }; 
     2118var arcsech = function(x) { return arccosh(1/x) }; 
     2119var arccsch = function(x) { return arcsinh(1/x) }; 
     2120var arccoth = function(x) { return arctanh(1/x) }; 
     2121var sign = function(x) { return (x==0?0:(x<0?-1:1)) }; 
     2122 
     2123function factorial(x,n) { // Factorial function 
     2124  if (n==null) n=1; 
     2125  if (Math.abs(x-Math.round(x*1000000)/1000000)<1e-15) 
     2126    x = Math.round(x*1000000)/1000000; 
     2127  if (x-Math.floor(x)!=0) return NaN; 
     2128  for (var i=x-n; i>0; i-=n) x*=i; 
     2129  return (x<0?NaN:(x==0?1:x)); 
     2130} 
     2131 
     2132function C(x,k) {  // Binomial coefficient function 
     2133  var res=1; 
     2134  for (var i=0; i<k; i++) res*=(x-i)/(k-i); 
     2135  return res; 
     2136} 
     2137 
     2138function chop(x,n) { // Truncate decimal number to n places after decimal point 
     2139  if (n==null) n=0; 
     2140  return Math.floor(x*Math.pow(10,n))/Math.pow(10,n); 
     2141} 
     2142 
     2143function ran(a,b,n) { // Generate random number in [a,b] with n digits after . 
     2144  if (n==null) n=0; 
     2145  return chop((b+Math.pow(10,-n)-a)*Math.random()+a,n); 
     2146} 
     2147 
     2148function myCreateElementSVG(t) { 
     2149  if (isIE) return doc.createElement(t); 
     2150  else return doc.createElementNS("http://www.w3.org/2000/svg",t); 
     2151} 
     2152 
     2153function getElementsByClass(container, tagName, clsName){ 
     2154  var list = new Array(0); 
     2155  var collection = container.getElementsByTagName(tagName); 
     2156  for(var i = 0; i < collection.length; i++) 
     2157    if(collection[i].className.slice(0,clsName.length)==clsName) 
     2158      list[list.length] = collection[i]; 
     2159  return list; 
     2160} 
     2161 
     2162function showobj(obj) { 
     2163  var st="", i; 
     2164  for (i in obj)  
     2165    st += (obj.getAttribute(i)==null?"":" "+i+":"+obj.getAttribute(i)); 
     2166  return st; 
     2167} 
     2168 
     2169function findPos(obj) { // top-left corner of obj on HTML page in pixel 
     2170  var curleft = curtop = 0; 
     2171  if (obj.offsetParent) { 
     2172    curleft = obj.offsetLeft 
     2173    curtop = obj.offsetTop 
     2174    while (obj = obj.offsetParent) { 
     2175      curleft += obj.offsetLeft 
     2176      curtop += obj.offsetTop 
     2177//alert(showobj(obj)+[curleft,curtop]) 
     2178    } 
     2179  } 
     2180  return [curleft,curtop]; 
     2181} 
     2182 
     2183function checkSVG(){ 
     2184  if (navigator.appName.slice(0,8)=="Netscape")  
     2185    if (window['SVGElement']) noSVG = null; 
     2186    else noSVG = true; 
     2187  else if (navigator.appName.slice(0,9)=="Microsoft") 
     2188    try { 
     2189      var oSVG=eval("new ActiveXObject('Adobe.SVGCtl.3');"); 
     2190        noSVG = null; 
     2191    } catch (e) { 
     2192        noSVG = true; 
     2193    } 
     2194  else if (navigator.appName.slice(0,5)=="Opera") // works only for 9.50b1 
     2195    noSVG = null; 
     2196  else noSVG = true; 
     2197//noSVG = true; //uncomment to check 
     2198  if (noSVG && notifyIfNoSVG) { 
     2199    var msg = "To view the ASCIIsvg images use Internet Explorer + Adobe SVGviewer or Mozilla Firefox 2.0 or later." 
     2200    if (alertIfNoSVG) 
     2201      alert(msg); 
     2202    else return msg; 
     2203  } 
     2204} 
     2205 
     2206function setText(st,id) { // add text to an existing node with given id 
     2207  var node = document.getElementById(id); 
     2208  if (node!=null) 
     2209    if (node.childNodes.length!=0) node.childNodes[0].nodeValue = st; 
     2210    else node.appendChild(document.createTextNode(st)); 
     2211} 
     2212 
     2213function getX(evt) { // return mouse x-coord in user coordinate system 
     2214  var svgroot = evt.target.parentNode; 
     2215    pos = findPos(svgroot.parentNode); 
     2216  return (evt.clientX+(isIE?0:window.pageXOffset)-pos[0]-svgroot.getAttribute("ox"))/parseFloat(svgroot.getAttribute("xunitlength")); 
     2217} 
     2218 
     2219function getY(evt) { // return mouse y-coord in user coordinate system 
     2220  var svgroot = evt.target.parentNode; 
     2221    pos = findPos(svgroot.parentNode); 
     2222//alert(showobj(svgroot)+svgroot.getAttribute("mytop")) 
     2223  return (svgroot.getAttribute("height")-svgroot.getAttribute("oy")-(evt.clientY+(isIE?0:window.pageYOffset)-pos[1]))/parseFloat(svgroot.getAttribute("yunitlength")); 
     2224} 
     2225 
     2226function translateandeval(src) { //modify user input to JavaScript syntax 
     2227  var errstr; 
     2228  // replace plot(f(x),...) with plot("f(x)",...)   
     2229  src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+?)\,/g,"plot\(\"$1\","); 
     2230  src = src.replace(/plot\(\x20*([^\"f\[][^\n\r;]+)\)/g,"plot(\"$1\")"); 
     2231 
     2232  // replace (expr,expr) by [expr,expr] where expr has no (,) in it 
     2233  src = src.replace(/([=[(,]\x20*)\(([-a-z0-9./+*]+?),([-a-z0-9./+*]+?)\)/g,"$1[$2,$3]"); 
     2234//alert(src) 
     2235  // insert * between digit and letter e.g. 2x --> 2*x 
     2236  src = src.replace(/([0-9])([a-df-zA-Z]|e^)/g,"$1*$2"); 
     2237  src = src.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1"); 
     2238 
     2239  try { 
     2240    with (Math) eval(src);          // here the svgpicture object is created 
     2241  } catch(err) { 
     2242    if (err!="wait") { 
     2243//alert(dsvglocation) 
     2244      if (typeof err=="object")  
     2245        errstr = err.name+" "+err.message+" "+err.number+" "+err.description; 
     2246      else errstr = err; 
     2247      alert(errstr+"\n"+src) 
     2248    } 
     2249  } 
     2250} 
     2251 
     2252var lastSlot = 0; 
     2253 
     2254function drawPictures() { // main routine; called after webpage has loaded 
     2255  var src, id, dsvg, nd, node, ht, index, cols, arr, i, node2; 
     2256  var ASbody = document.getElementsByTagName("body")[0]; 
     2257  pictures = getElementsByClass(ASbody,"embed","ASCIIsvg"); 
     2258  var len = pictures.length; 
     2259  if(len==0) return; 
     2260  for (index = lastSlot; index < len+lastSlot; index++) { 
     2261   width = null; height = null;  
     2262   xmin = null; xmax = null; ymin = null; ymax = null; 
     2263   xscl = null; xgrid = null; yscl = null; ygrid = null; 
     2264   initialized = false; 
     2265   picture = pictures[index-lastSlot];  // current picture object 
     2266   src = picture.getAttribute("script"); // get the ASCIIsvg code 
     2267   if (src==null) src = ""; 
     2268   // insert "axes()" if not present  ******** experimental 
     2269   if (!/axes\b|initPicture/.test(src)) { 
     2270     var i = 0; 
     2271     while (/((yscl|ymax|ymin|xscl|xmax|xmin|\bwidth|\bheight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/.test(src.slice(i))) i++; 
     2272     src = (i==0?"axes(); "+src: src.slice(0,i)+src.slice(i).replace(/((scl|max|min|idth|eight)\s*=\s*-?\d*(\d\.|\.\d|\d)\d*\s*;?)/,"$1\naxes();")); 
     2273   } 
     2274   ht = picture.getAttribute("height"); 
     2275   if (isIE) { 
     2276     picture.setAttribute("wmode","transparent"); 
     2277//alert("*"+picture.getAttribute("src")+dsvglocation); 
     2278//adding d.svg dynamically greates problems in IE... 
     2279//     if (picture.getAttribute("src")=="") picture.setAttribute("src",dsvglocation+"d.svg"); 
     2280   } 
     2281   if (document.getElementById("picture"+(index+1)+"mml")==null) { 
     2282     picture.parentNode.style.position = "relative"; 
     2283     node = createElementXHTML("div"); 
     2284     node.style.position = "absolute"; 
     2285     node.style.top = "0px"; 
     2286     node.style.left = "0px"; 
     2287     node.setAttribute("id","picture"+(index+1)+"mml"); 
     2288     picture.parentNode.insertBefore(node,picture.nextSibling); 
     2289   } 
     2290   if (ht==null) ht =""; 
     2291//   if (ht!="") defaultborder = 25; 
     2292   if (ht=="" || src=="")  
     2293    if (document.getElementById("picture"+(index+1)+"input")==null) { 
     2294      node = createElementXHTML("textarea"); 
     2295      arr = src.split("\n"); 
     2296      cols = 0; 
     2297      for (i=0;i<arr.length;i++) cols = Math.max(cols,arr[i].length); 
     2298      node.setAttribute("rows",Math.min(10,arr.length)+1); 
     2299      node.setAttribute("cols",Math.max(Math.min(60,cols),20)+5); 
     2300//      node.setAttribute("style","display:block"); 
     2301      if (isIE) src = src.replace(/([^\r])\n/g,"$1\r"); 
     2302      node.appendChild(document.createTextNode(src)); 
     2303      if (src.indexOf("showcode()")==-1) node.style.display = "none"; 
     2304      node.setAttribute("id","picture"+(index+1)+"input"); 
     2305      picture.parentNode.insertBefore(node,picture.nextSibling); 
     2306      picture.parentNode.insertBefore(createElementXHTML("br"),node); 
     2307      node2 = createElementXHTML("button"); 
     2308      node2.setAttribute("id","picture"+(index+1)+"button"); 
     2309      if (isIE) node2.onclick = function() {updatePicture(this)}; 
     2310      else node2.setAttribute("onclick","updatePicture(this)"); 
     2311      node2.appendChild(document.createTextNode("Update")); 
     2312      if (src.indexOf("showcode()")==-1) node2.style.display = "none"; 
     2313      picture.parentNode.insertBefore(node2,node); 
     2314//      picture.parentNode.insertBefore(document.createTextNode("ASCII"),node); 
     2315      picture.parentNode.insertBefore(createElementXHTML("br"),node); 
     2316    } else src = document.getElementById("picture"+(index+1)+"input").value; 
     2317    id = picture.getAttribute("id"); 
     2318    dsvg = picture.getAttribute("src"); 
     2319    if (id == null || id == "") { 
     2320      id = "picture"+(index+1); 
     2321      picture.setAttribute("id",id); 
     2322    } 
     2323    translateandeval(src); 
     2324  } 
     2325  lastSlot+=len; 
     2326} 
     2327 
     2328function setdefaults() { //called before each graph is evaluated 
     2329  strokewidth = defaultstrokewidth; 
     2330  stroke = defaultstroke; 
     2331  strokeopacity = defaultstrokeopacity; 
     2332  strokedasharray = defaultstrokedasharray; 
     2333  fill = defaultfill; 
     2334  fillopacity = defaultfillopacity; 
     2335  fontstyle = defaultfontstyle; 
     2336  fontfamily = defaultfontfamily; 
     2337  fontsize = defaultfontsize; 
     2338  fontweight = defaultfontweight; 
     2339  fontstroke = defaultfontstroke; 
     2340  fontfill = defaultfontfill; 
     2341  marker = defaultmarker; 
     2342  endpoints = defaultendpoints; 
     2343} 
     2344 
     2345function switchTo(id) { // used by dynamic code to select appropriate graph 
     2346  if (id==undefined) return; 
     2347  var name = id; 
     2348  if (typeof name!="string") name = id.target.parentNode.getAttribute("name"); 
     2349  picture = document.getElementById(name); 
     2350  width = picture.getAttribute("width")-0; 
     2351  height = picture.getAttribute("height")-0; 
     2352  setdefaults(); 
     2353  if ((picture.nodeName == "EMBED" || picture.nodeName == "embed") && isIE) { 
     2354    svgpicture = picture.getSVGDocument().getElementById("root"); 
     2355    doc = picture.getSVGDocument(); 
     2356  } else { 
     2357    svgpicture = picture; 
     2358    doc = document; 
     2359  } 
     2360  xunitlength = parseFloat(svgpicture.getAttribute("xunitlength")); 
     2361  yunitlength = parseFloat(svgpicture.getAttribute("yunitlength")); 
     2362  xmin = parseFloat(svgpicture.getAttribute("xmin")); 
     2363  xmax = parseFloat(svgpicture.getAttribute("xmax")); 
     2364  ymin = parseFloat(svgpicture.getAttribute("ymin")); 
     2365  ymax = parseFloat(svgpicture.getAttribute("ymax")); 
     2366  origin = [svgpicture.getAttribute("ox")-0,svgpicture.getAttribute("oy")-0]; 
     2367} 
     2368 
     2369function updatePicture(obj) { 
     2370  var node, src, id, top, left; 
     2371  if (typeof obj=="object") id = obj.id.slice(0,-6); 
     2372  else id = (typeof obj=="string"?obj:"picture"+(obj+1)); 
     2373  src = document.getElementById(id+"input").value; 
     2374  xmin = null; xmax = null; ymin = null; ymax = null; 
     2375  xscl = null; xgrid = null; yscl = null; ygrid = null; 
     2376  initialized = false; 
     2377  picture = document.getElementById(id); 
     2378  translateandeval(src) 
     2379} 
     2380 
     2381function changepicturesize(evt,factor) { 
     2382  var obj = evt.target; 
     2383  var name = obj.parentNode.getAttribute("name"); 
     2384  var pic = document.getElementById(name); 
     2385  var src = document.getElementById(name+"input").value; 
     2386  if (!/height/.test(src)) src = "height=0; "+src; 
     2387  if (!/width/.test(src)) src = "width=0; "+src; 
     2388  src = src.replace(/width\s*=\s*\d+/,"width="+(factor*(pic.getAttribute("width")-0))); 
     2389  src = src.replace(/height\s*=\s*\d+/,"height="+(factor*(pic.getAttribute("height")-0))); 
     2390  document.getElementById(name+"input").value = src; 
     2391//alert(getKey(evt.keycode)) 
     2392  updatePicture(name); 
     2393} 
     2394 
     2395function zoom(evt,factor) { 
     2396  switchTo(evt); 
     2397  var obj = evt.target; 
     2398  var name = obj.parentNode.getAttribute("name"); 
     2399  var pic = document.getElementById(name); 
     2400  var src = document.getElementById(name+"input").value; 
     2401  var xlen = (xmax-xmin)/2; 
     2402  var ylen = (ymax-ymin)/2; 
     2403  var xcen = getX(evt), ycen = getY(evt); 
     2404  if (!/ymax/.test(src)) src = "ymax=0; "+src; 
     2405  if (!/ymin/.test(src)) src = "ymin=0; "+src; 
     2406  if (!/xmax/.test(src)) src = "xmax=0; "+src; 
     2407  if (!/xmin/.test(src)) src = "xmin=0; "+src; 
     2408  src = src.replace(/xmin\s*=\s*[-\d.e]+/,"xmin="+(xcen-factor*xlen)); 
     2409  src = src.replace(/xmax\s*=\s*[-\d.e]+/,"xmax="+(xcen+factor*xlen)); 
     2410  src = src.replace(/ymin\s*=\s*[-\d.e]+/,"ymin="+(ycen-factor*ylen)); 
     2411  src = src.replace(/ymax\s*=\s*[-\d.e]+/,"ymax="+(ycen+factor*ylen)); 
     2412  document.getElementById(name+"input").value = src; 
     2413  updatePicture(name); 
     2414} 
     2415 
     2416var sinceFirstClick = 0; // ondblclick simulation from  
     2417var dblClkTimer;         // http://www.enja.org/david/?cat=13 Thanks! 
     2418function timer() { 
     2419  if(sinceFirstClick<60) { 
     2420    sinceFirstClick++; 
     2421    setTimeout("timer()",10); 
     2422  } else { 
     2423    clearTimeout(dblClkTimer); 
     2424    dblClkTimer = ""; 
     2425  } 
     2426} 
     2427function mClick(evt) { 
     2428  if(sinceFirstClick!=0) { 
     2429    if(sinceFirstClick <= 40) { 
     2430      if (evt.shiftKey) { 
     2431        if (evt.altKey) changepicturesize(evt,2); 
     2432        else zoom(evt,.5); 
     2433      } else if (evt.altKey) zoom(evt,2);//changepicturesize(evt,.5); 
     2434      else showHideCode(evt);             // do this on dblclick 
     2435      clearTimeout(dblClkTimer); 
     2436      dblClkTimer = ""; 
     2437    } else { 
     2438      clearTimeout(dblClkTimer); 
     2439      sinceFirstClick = 0; 
     2440      dblClkTimer = setTimeout("timer()",10); 
     2441    }          
     2442  } else { 
     2443    sinceFirstClick = 0; 
     2444    dblClkTimer = setTimeout("timer()",10); 
     2445  } 
     2446} 
     2447 
     2448function showHideCode(evt) { // called by onclick event 
     2449//  if (evt.getDetail()==2) {//getDetail unfortunately not in Firefox 
     2450  var obj=evt.target; 
     2451  var name = obj.parentNode.getAttribute("name"); 
     2452  var node = document.getElementById(name+"input"); 
     2453  node.style.display = (node.style.display == "none"?"":"none"); 
     2454  var node = document.getElementById(name+"button"); 
     2455  node.style.display = (node.style.display == "none"?"":"none"); 
     2456//  } 
     2457} 
     2458 
     2459function showcode() {} // do nothing 
     2460 
     2461function setBorder(x) { border = x } //deprecate 
     2462 
     2463function initPicture(x_min,x_max,y_min,y_max) { // set up the graph 
     2464// usually called by axes() or noaxes(), but can be used directly 
     2465 if (!initialized) { 
     2466  setdefaults(); 
     2467  initialized = true; 
     2468  if (x_min!=null) xmin = x_min; 
     2469  if (x_max!=null) xmax = x_max; 
     2470  if (y_min!=null) ymin = y_min; 
     2471  if (y_max!=null) ymax = y_max; 
     2472  if (xmin==null) xmin = defaultxmin; 
     2473  if (xmax==null) xmax = defaultxmax; 
     2474 if (typeof xmin != "number" || typeof xmax != "number" || xmin >= xmax)  
     2475   alert("Picture requires at least two numbers: xmin < xmax"); 
     2476 else if (y_max != null && (typeof y_min != "number" ||  
     2477          typeof y_max != "number" || y_min >= y_max)) 
     2478   alert("initPicture(xmin,xmax,ymin,ymax) requires numbers ymin < ymax"); 
     2479 else { 
     2480  if (width==null) { 
     2481    width = picture.getAttribute("width"); 
     2482    if (width==null || width=="") width=defaultwidth; 
     2483  } 
     2484  picture.setAttribute("width",width); 
     2485  if (height==null) {  
     2486    height = picture.getAttribute("height"); 
     2487    if (height==null || height=="") height=defaultheight; 
     2488  } 
     2489  picture.setAttribute("height",height); 
     2490  xunitlength = (width-2*border)/(xmax-xmin); 
     2491  yunitlength = xunitlength; 
     2492//alert(xmin+" "+xmax+" "+ymin+" "+ymax) 
     2493  if (ymin==null) { 
     2494    origin = [-xmin*xunitlength+border,height/2]; 
     2495    ymin = -(height-2*border)/(2*yunitlength); 
     2496    ymax = -ymin; 
     2497  } else { 
     2498    if (ymax!=null) yunitlength = (height-2*border)/(ymax-ymin); 
     2499    else ymax = (height-2*border)/yunitlength + ymin; 
     2500    origin = [-xmin*xunitlength+border,-ymin*yunitlength+border]; 
     2501  } 
     2502  if (isIE) { 
     2503    if (picture.FULLSCREEN==undefined) { 
     2504      setTimeout('drawPictures()',50); 
     2505      throw "wait"; 
     2506    } 
     2507    svgpicture = picture.getSVGDocument().getElementById("root"); 
     2508    if (svgpicture==null) { 
     2509      setTimeout('drawPictures()',50); 
     2510      throw "wait"; 
     2511    } 
     2512    svgpicture = picture.getSVGDocument().getElementById("root"); 
     2513    while (svgpicture.childNodes.length>0)  
     2514      svgpicture.removeChild(svgpicture.lastChild);  
     2515    svgpicture.setAttribute("width",width); 
     2516    svgpicture.setAttribute("height",height); 
     2517    svgpicture.setAttribute("name",picture.getAttribute("id")); 
     2518    doc = picture.getSVGDocument(); 
     2519  } else { 
     2520    var qnode = document.createElementNS("http://www.w3.org/2000/svg","svg"); 
     2521    qnode.setAttribute("id",picture.getAttribute("id")); 
     2522    qnode.setAttribute("name",picture.getAttribute("id")); 
     2523//    qnode.setAttribute("style","display:inline"); 
     2524    qnode.setAttribute("width",picture.getAttribute("width")); 
     2525    qnode.setAttribute("height",picture.getAttribute("height")); 
     2526    picturepos = findPos(picture); 
     2527//  qnode.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink"); 
     2528    if (picture.parentNode!=null) { 
     2529      picture.parentNode.replaceChild(qnode,picture); 
     2530    } else { 
     2531      svgpicture.parentNode.replaceChild(qnode,svgpicture); 
     2532    } 
     2533    svgpicture = qnode; 
     2534    doc = document; 
     2535  } 
     2536  var nd = document.getElementById(picture.getAttribute("id")+"mml"); 
     2537  if (nd!=null) // clear out MathML layer 
     2538    while (nd.childNodes.length>0) nd.removeChild(nd.lastChild);  
     2539  svgpicture.setAttribute("xunitlength",xunitlength); 
     2540  svgpicture.setAttribute("yunitlength",yunitlength); 
     2541  svgpicture.setAttribute("xmin",xmin); 
     2542  svgpicture.setAttribute("xmax",xmax); 
     2543  svgpicture.setAttribute("ymin",ymin); 
     2544  svgpicture.setAttribute("ymax",ymax); 
     2545  svgpicture.setAttribute("ox",origin[0]); 
     2546  svgpicture.setAttribute("oy",origin[1]); 
     2547  var node = myCreateElementSVG("rect"); 
     2548  node.setAttribute("x","0"); 
     2549  node.setAttribute("y","0"); 
     2550  node.setAttribute("width",width); 
     2551  node.setAttribute("height",height); 
     2552  node.setAttribute("style",backgroundstyle); 
     2553  svgpicture.appendChild(node); 
     2554  svgpicture.setAttribute("onmousemove","displayCoord(evt)"); 
     2555  svgpicture.setAttribute("onmouseout","removeCoord(evt)"); 
     2556  svgpicture.setAttribute("onclick","mClick(evt)"); 
     2557  node = myCreateElementSVG("text"); // used for displayCoord 
     2558  node.appendChild(doc.createTextNode(" ")); 
     2559  node.setAttribute("id","coords"); 
     2560  svgpicture.appendChild(node); 
     2561  node = myCreateElementSVG("text"); // used for text display 
     2562  node.appendChild(doc.createTextNode(" ")); 
     2563  node.setAttribute("id","coords"); 
     2564  svgpicture.appendChild(node); 
     2565  border = defaultborder; 
     2566 } 
     2567 } 
     2568} 
     2569 
     2570//////////////////////////user graphics commands start///////////////////////// 
     2571 
     2572function line(p,q,id,endpts) { // segment connecting points p,q (coordinates in units) 
     2573  var node; 
     2574  if (id!=null) node = doc.getElementById(id); 
     2575  if (node==null) { 
     2576    node = myCreateElementSVG("path"); 
     2577    node.setAttribute("id", id); 
     2578    svgpicture.appendChild(node); 
     2579  } 
     2580  node.setAttribute("d","M"+(p[0]*xunitlength+origin[0])+","+ 
     2581    (height-p[1]*yunitlength-origin[1])+" "+ 
     2582    (q[0]*xunitlength+origin[0])+","+(height-q[1]*yunitlength-origin[1])); 
     2583  node.setAttribute("stroke-width", strokewidth); 
     2584  if (strokedasharray!=null)  
     2585    node.setAttribute("stroke-dasharray", strokedasharray); 
     2586  node.setAttribute("stroke", stroke); 
     2587  node.setAttribute("fill", fill); 
     2588  node.setAttribute("stroke-opacity", strokeopacity); 
     2589  node.setAttribute("fill-opacity", fillopacity); 
     2590  if (marker=="dot" || marker=="arrowdot") { 
     2591    ASdot(p,markersize,markerstroke,markerfill); 
     2592    if (marker=="arrowdot") arrowhead(p,q); 
     2593    ASdot(q,markersize,markerstroke,markerfill); 
     2594  } else if (marker=="arrow") arrowhead(p,q); 
     2595  if (endpts==null && endpoints!="") endpts = endpoints; 
     2596  if (endpts!=null) { 
     2597    if (endpts.indexOf("<-") != -1) arrowhead(q,p); 
     2598    if (endpts.indexOf("o-") != -1) dot(p, "open"); 
     2599    if (endpts.indexOf("*-") != -1) dot(p, "closed"); 
     2600    if (endpts.indexOf("->") != -1) arrowhead(p,q); 
     2601    if (endpts.indexOf("-o") != -1) dot(q, "open"); 
     2602    if (endpts.indexOf("-*") != -1) dot(q, "closed"); 
     2603  } 
     2604} 
     2605 
     2606function path(plist,id,c,endpts) { 
     2607  if (c==null) c=""; 
     2608  var node, st, i; 
     2609  if (id!=null) node = doc.getElementById(id); 
     2610  if (node==null) { 
     2611    node = myCreateElementSVG("path"); 
     2612    node.setAttribute("id", id); 
     2613    svgpicture.appendChild(node); 
     2614  } 
     2615  if (typeof plist == "string") st = plist; 
     2616  else { 
     2617    st = "M"; 
     2618    st += (plist[0][0]*xunitlength+origin[0])+","+ 
     2619          (height-plist[0][1]*yunitlength-origin[1])+" "+c; 
     2620    for (i=1; i<plist.length; i++) 
     2621      st += (plist[i][0]*xunitlength+origin[0])+","+ 
     2622            (height-plist[i][1]*yunitlength-origin[1])+" "; 
     2623  } 
     2624  node.setAttribute("d", st); 
     2625  node.setAttribute("stroke-width", strokewidth); 
     2626  if (strokedasharray!=null)  
     2627    node.setAttribute("stroke-dasharray", strokedasharray); 
     2628  node.setAttribute("stroke", stroke); 
     2629  node.setAttribute("fill", fill); 
     2630  node.setAttribute("stroke-opacity", strokeopacity); 
     2631  node.setAttribute("fill-opacity", fillopacity); 
     2632  if (marker=="dot" || marker=="arrowdot") 
     2633    for (i=0; i<plist.length; i++) 
     2634      if (c!="C" && c!="T" || i!=1 && i!=2) 
     2635        ASdot(plist[i],markersize,markerstroke,markerfill); 
     2636  if (endpts==null && endpoints!="") endpts = endpoints; 
     2637  if (endpts!=null) { 
     2638    if (endpts.indexOf("<-") != -1) arrowhead(plist[1],plist[0]); 
     2639    if (endpts.indexOf("o-") != -1) dot(plist[0], "open"); 
     2640    if (endpts.indexOf("*-") != -1) dot(plist[0], "closed"); 
     2641    if (endpts.indexOf("->") != -1) arrowhead(plist[plist.length-2],plist[plist.length-1]); 
     2642    if (endpts.indexOf("-o") != -1) dot(plist[plist.length-1], "open"); 
     2643    if (endpts.indexOf("-*") != -1) dot(plist[plist.length-1], "closed"); 
     2644  } 
     2645} 
     2646 
     2647function curve(plist,id,endpts) { 
     2648  path(plist,id,"T",endpts); 
     2649} 
     2650 
     2651function vector(p,q,id) { 
     2652  line(p,q,id,"","->"); 
     2653} 
     2654 
     2655function circle(center,radius,id) { // coordinates in units 
     2656  var node; 
     2657  if (id!=null) node = doc.getElementById(id); 
     2658  if (node==null) { 
     2659    node = myCreateElementSVG("circle"); 
     2660    node.setAttribute("id", id); 
     2661    svgpicture.appendChild(node); 
     2662  } 
     2663  node.setAttribute("cx",center[0]*xunitlength+origin[0]); 
     2664  node.setAttribute("cy",height-center[1]*yunitlength-origin[1]); 
     2665  node.setAttribute("r",radius*xunitlength); 
     2666  node.setAttribute("stroke-width", strokewidth); 
     2667  node.setAttribute("stroke", stroke); 
     2668  node.setAttribute("fill", fill); 
     2669  node.setAttribute("stroke-opacity", strokeopacity); 
     2670  node.setAttribute("fill-opacity", fillopacity); 
     2671} 
     2672 
     2673function loop(p,d,id) {  
     2674// d is a direction vector e.g. [1,0] means loop starts in that direction 
     2675  if (d==null) d=[1,0]; 
     2676  path([p,[p[0]+d[0],p[1]+d[1]],[p[0]-d[1],p[1]+d[0]],p],id,"C"); 
     2677  if (marker=="arrow" || marker=="arrowdot")  
     2678    arrowhead([p[0]+Math.cos(1.4)*d[0]-Math.sin(1.4)*d[1], 
     2679               p[1]+Math.sin(1.4)*d[0]+Math.cos(1.4)*d[1]],p); 
     2680} 
     2681 
     2682function arc(start,end,radius,id,largearc) { // coordinates in units 
     2683  var node, v; 
     2684//alert([fill, stroke, origin, xunitlength, yunitlength, height]) 
     2685  if (id!=null) node = doc.getElementById(id); 
     2686  if (largearc==null) largearc=0; 
     2687  if (radius==null) { 
     2688    v=[end[0]-start[0],end[1]-start[1]]; 
     2689    radius = Math.sqrt(v[0]*v[0]+v[1]*v[1]); 
     2690  } 
     2691  if (node==null) { 
     2692    node = myCreateElementSVG("path"); 
     2693    node.setAttribute("id", id); 
     2694    svgpicture.appendChild(node); 
     2695  } 
     2696  node.setAttribute("d","M"+(start[0]*xunitlength+origin[0])+","+ 
     2697    (height-start[1]*yunitlength-origin[1])+" A"+radius*xunitlength+","+ 
     2698     radius*yunitlength+" 0 "+largearc+",0 "+(end[0]*xunitlength+origin[0])+","+ 
     2699    (height-end[1]*yunitlength-origin[1])); 
     2700  node.setAttribute("stroke-width", strokewidth); 
     2701  node.setAttribute("stroke", stroke); 
     2702  node.setAttribute("fill", fill); 
     2703  node.setAttribute("stroke-opacity", strokeopacity); 
     2704  node.setAttribute("fill-opacity", fillopacity); 
     2705  if (marker=="arrow" || marker=="arrowdot") { 
     2706    u = [(end[1]-start[1])/4,(start[0]-end[0])/4]; 
     2707    v = [(end[0]-start[0])/2,(end[1]-start[1])/2]; 
     2708//alert([u,v]) 
     2709    v = [start[0]+v[0]+u[0],start[1]+v[1]+u[1]]; 
     2710  } else v=[start[0],start[1]]; 
     2711  if (marker=="dot" || marker=="arrowdot") { 
     2712    ASdot(start,markersize,markerstroke,markerfill); 
     2713    if (marker=="arrowdot") arrowhead(v,end); 
     2714    ASdot(end,markersize,markerstroke,markerfill); 
     2715  } else if (marker=="arrow") arrowhead(v,end); 
     2716} 
     2717 
     2718function sector(center,start,end,id) { // center,start,end should be isoceles 
     2719  var rx = start[0]-center[0], ry = start[1]-center[1]; 
     2720  arc(start,end,Math.sqrt(rx*rx+ry*ry),id+"arc"); 
     2721  path([end,center,start],id+"path"); 
     2722} 
     2723 
     2724function ellipse(center,rx,ry,id) { // coordinates in units 
     2725  var node; 
     2726  if (id!=null) node = doc.getElementById(id); 
     2727  if (node==null) { 
     2728    node = myCreateElementSVG("ellipse"); 
     2729    node.setAttribute("id", id); 
     2730    svgpicture.appendChild(node); 
     2731  } 
     2732  node.setAttribute("cx",center[0]*xunitlength+origin[0]); 
     2733  node.setAttribute("cy",height-center[1]*yunitlength-origin[1]); 
     2734  node.setAttribute("rx",rx*xunitlength); 
     2735  node.setAttribute("ry",ry*yunitlength); 
     2736  node.setAttribute("stroke-width", strokewidth); 
     2737  node.setAttribute("stroke", stroke); 
     2738  node.setAttribute("fill", fill); 
     2739  node.setAttribute("stroke-opacity", strokeopacity); 
     2740  node.setAttribute("fill-opacity", fillopacity); 
     2741} 
     2742 
     2743function triangle(p,q,r,id) { 
     2744  path([p,q,r,p],id) 
     2745} 
     2746 
     2747function rect(p,q,id,rx,ry) { // opposite corners in units, rounded by radii 
     2748  var node; 
     2749  if (id!=null) node = doc.getElementById(id); 
     2750  if (node==null) { 
     2751    node = myCreateElementSVG("rect"); 
     2752    node.setAttribute("id", id); 
     2753    svgpicture.appendChild(node); 
     2754  } 
     2755  node.setAttribute("x",p[0]*xunitlength+origin[0]); 
     2756  node.setAttribute("y",height-q[1]*yunitlength-origin[1]); 
     2757  node.setAttribute("width",(q[0]-p[0])*xunitlength); 
     2758  node.setAttribute("height",(q[1]-p[1])*yunitlength); 
     2759  if (rx!=null) node.setAttribute("rx",rx*xunitlength); 
     2760  if (ry!=null) node.setAttribute("ry",ry*yunitlength); 
     2761  node.setAttribute("stroke-width", strokewidth); 
     2762  node.setAttribute("stroke", stroke); 
     2763  node.setAttribute("fill", fill); 
     2764  node.setAttribute("stroke-opacity", strokeopacity); 
     2765  node.setAttribute("fill-opacity", fillopacity); 
     2766} 
     2767 
     2768function text(p,st,pos,id,fontsty) { 
     2769  var dnode, node, dx = 0, dy = fontsize/3, str = st.toString(); 
     2770  if (/(`|\$)/.test(str)) {  // layer for ASCIIMathML and LaTeXMathML 
     2771    dnode = document.getElementById(svgpicture.getAttribute("name")+"mml"); 
     2772    if (dnode!=null) { 
     2773      if (id!=null) node = document.getElementById(id); 
     2774      if (node==null) { 
     2775//alert(dnode.childNodes.length) 
     2776        node = createElementXHTML("div"); 
     2777        node.setAttribute("id", id); 
     2778        node.style.position = "absolute"; 
     2779        dnode.appendChild(node); 
     2780      } 
     2781      while (node.childNodes.length>0) node.removeChild(node.lastChild);  
     2782      node.appendChild(document.createTextNode(str)); 
     2783      if (/`/.test(str)) AMprocessNode(node); else LMprocessNode(node); 
     2784      dx = -node.offsetWidth/2; 
     2785      dy = -node.offsetHeight/2; 
     2786      if (pos!=null) { 
     2787        if (/above/.test(pos)) dy = -node.offsetHeight; 
     2788        if (/below/.test(pos)) dy = 0; 
     2789        if (/right/.test(pos)) dx = 0; 
     2790        if ( /left/.test(pos)) dx = -node.offsetWidth; 
     2791      } 
     2792      node.style.left = ""+(p[0]*xunitlength+origin[0]+dx)+"px"; 
     2793      node.style.top = ""+(height-p[1]*yunitlength-origin[1]+dy)+"px"; 
     2794    } 
     2795    return p; 
     2796  } 
     2797  var textanchor = "middle";  // regular text goes into SVG 
     2798  if (pos!=null) { 
     2799    if (/above/.test(pos)) dy = -fontsize/2; 
     2800    if (/below/.test(pos)) dy = fontsize-0; 
     2801    if (/right/.test(pos)) {textanchor = "start"; dx = fontsize/4;} 
     2802    if ( /left/.test(pos)) {textanchor = "end";  dx = -fontsize/4;} 
     2803  } 
     2804  if (id!=null) node = doc.getElementById(id); 
     2805  if (node==null) { 
     2806    node = myCreateElementSVG("text"); 
     2807    node.setAttribute("id", id); 
     2808    svgpicture.appendChild(node); 
     2809    node.appendChild(doc.createTextNode(str)); 
     2810  } 
     2811  while (node.childNodes.length>1) node.removeChild(node.lastChild);  
     2812  node.lastChild.nodeValue = "\xA0"+str+"\xA0"; 
     2813  node.setAttribute("x",p[0]*xunitlength+origin[0]+dx); 
     2814  node.setAttribute("y",height-p[1]*yunitlength-origin[1]+dy); 
     2815  node.setAttribute("font-style",(fontsty!=null?fontsty: 
     2816    (str.search(/^[a-zA-Z]$/)!=-1?"italic":fontstyle))); 
     2817  node.setAttribute("font-family",fontfamily); 
     2818  node.setAttribute("font-size",fontsize); 
     2819  node.setAttribute("font-weight",fontweight); 
     2820  node.setAttribute("text-anchor",textanchor); 
     2821  if (fontstroke!="none") node.setAttribute("stroke",fontstroke); 
     2822  if (fontfill!="none") node.setAttribute("fill",fontfill); 
     2823  return p; 
     2824} 
     2825 
     2826function mtext(p,st,pos,fontsty,fontsz) { // method for updating text on an svg 
     2827// "this" is the text object or the svgpicture object 
     2828  var textanchor = "middle"; 
     2829  var dx = 0; var dy = fontsize/3; 
     2830  if (pos!=null) { 
     2831    if (pos.slice(0,5)=="above") dy = -fontsize/2; 
     2832    if (pos.slice(0,5)=="below") dy = fontsize-0; 
     2833    if (pos.slice(0,5)=="right" || pos.slice(5,10)=="right") { 
     2834      textanchor = "start"; 
     2835      dx = fontsize/2; 
     2836    } 
     2837    if (pos.slice(0,4)=="left" || pos.slice(5,9)=="left") { 
     2838      textanchor = "end"; 
     2839      dx = -fontsize/2; 
     2840    } 
     2841  } 
     2842  var node = this; 
     2843  if (this.nodeName=="svg") { 
     2844    node = myCreateElementSVG("text"); 
     2845    this.appendChild(node); 
     2846    node.appendChild(doc.createTextNode(st)); 
     2847  } 
     2848  node.lastChild.nodeValue = st; 
     2849  node.setAttribute("x",p[0]+dx); 
     2850  node.setAttribute("y",p[1]+dy); 
     2851  node.setAttribute("font-style",(fontsty!=null?fontsty:fontstyle)); 
     2852  node.setAttribute("font-family",fontfamily); 
     2853  node.setAttribute("font-size",(fontsz!=null?fontsz:fontsize)); 
     2854  node.setAttribute("font-weight",fontweight); 
     2855  node.setAttribute("text-anchor",textanchor); 
     2856  if (fontstroke!="none") node.setAttribute("stroke",fontstroke); 
     2857  if (fontfill!="none") node.setAttribute("fill",fontfill); 
     2858} 
     2859 
     2860function image(imgurl,p,w,h,id) { // not working yet 
     2861  var node; 
     2862  if (id!=null) node = doc.getElementById(id); 
     2863  if (node==null) { 
     2864    node = myCreateElementSVG("image"); 
     2865    node.setAttribute("id", id); 
     2866    svgpicture.appendChild(node); 
     2867  } 
     2868  node.setAttribute("x",p[0]*xunitlength+origin[0]); 
     2869  node.setAttribute("y",height-p[1]*yunitlength-origin[1]); 
     2870  node.setAttribute("width",w); 
     2871  node.setAttribute("height",h); 
     2872  node.setAttribute("xlink:href", imgurl); 
     2873} 
     2874 
     2875function ASdot(center,radius,s,f) { // coordinates in units, radius in pixel 
     2876  if (s==null) s = stroke; if (f==null) f = fill; 
     2877  var node = myCreateElementSVG("circle"); 
     2878  node.setAttribute("cx",center[0]*xunitlength+origin[0]); 
     2879  node.setAttribute("cy",height-center[1]*yunitlength-origin[1]); 
     2880  node.setAttribute("r",radius); 
     2881  node.setAttribute("stroke-width", strokewidth); 
     2882  node.setAttribute("stroke", s); 
     2883  node.setAttribute("fill", f); 
     2884  svgpicture.appendChild(node); 
     2885} 
     2886 
     2887function dot(center, typ, label, pos, id) { 
     2888  var node; 
     2889  var cx = center[0]*xunitlength+origin[0]; 
     2890  var cy = height-center[1]*yunitlength-origin[1]; 
     2891  if (id!=null) node = doc.getElementById(id); 
     2892  if (typ=="+" || typ=="-" || typ=="|") { 
     2893    if (node==null) { 
     2894      node = myCreateElementSVG("path"); 
     2895      node.setAttribute("id", id); 
     2896      svgpicture.appendChild(node); 
     2897    } 
     2898    if (typ=="+") { 
     2899      node.setAttribute("d", 
     2900        " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy+ 
     2901        " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength)); 
     2902      node.setAttribute("stroke-width", .5); 
     2903      node.setAttribute("stroke", axesstroke); 
     2904    } else { 
     2905      if (typ=="-") node.setAttribute("d", 
     2906        " M "+(cx-ticklength)+" "+cy+" L "+(cx+ticklength)+" "+cy); 
     2907      else node.setAttribute("d", 
     2908        " M "+cx+" "+(cy-ticklength)+" L "+cx+" "+(cy+ticklength)); 
     2909      node.setAttribute("stroke-width", strokewidth); 
     2910      node.setAttribute("stroke", stroke); 
     2911    } 
     2912  } else { 
     2913    if (node==null) { 
     2914      node = myCreateElementSVG("circle"); 
     2915      node.setAttribute("id", id); 
     2916      svgpicture.appendChild(node); 
     2917    } 
     2918    node.setAttribute("cx",cx); 
     2919    node.setAttribute("cy",cy); 
     2920    node.setAttribute("r",dotradius); 
     2921    node.setAttribute("stroke-width", strokewidth); 
     2922    node.setAttribute("stroke", stroke); 
     2923    node.setAttribute("fill", (typ=="open"?"white": 
     2924                              (typ=="closed"?stroke:markerfill))); 
     2925  } 
     2926  if (label!=null)  
     2927    text(center,label,(pos==null?"below":pos),(id==null?id:id+"label")) 
     2928} 
     2929 
     2930point = dot; //alternative name 
     2931 
     2932function arrowhead(p,q) { // draw arrowhead at q (in units) add size param 
     2933  var up; 
     2934  var v = [p[0]*xunitlength+origin[0],height-p[1]*yunitlength-origin[1]]; 
     2935  var w = [q[0]*xunitlength+origin[0],height-q[1]*yunitlength-origin[1]]; 
     2936  var u = [w[0]-v[0],w[1]-v[1]]; 
     2937  var d = Math.sqrt(u[0]*u[0]+u[1]*u[1]); 
     2938  if (d > 0.00000001) { 
     2939    u = [u[0]/d, u[1]/d]; 
     2940    up = [-u[1],u[0]]; 
     2941    var node = myCreateElementSVG("path"); 
     2942    node.setAttribute("d","M "+(w[0]-15*u[0]-4*up[0])+" "+ 
     2943      (w[1]-15*u[1]-4*up[1])+" L "+(w[0]-3*u[0])+" "+(w[1]-3*u[1])+" L "+ 
     2944      (w[0]-15*u[0]+4*up[0])+" "+(w[1]-15*u[1]+4*up[1])+" z"); 
     2945    node.setAttribute("stroke-width", markerstrokewidth); 
     2946    node.setAttribute("stroke", stroke); /*was markerstroke*/ 
     2947    node.setAttribute("fill", stroke); /*was arrowfill*/ 
     2948    node.setAttribute("stroke-opacity", strokeopacity); 
     2949    node.setAttribute("fill-opacity", fillopacity); 
     2950    svgpicture.appendChild(node);     
     2951  } 
     2952} 
     2953 
     2954function chopZ(st) { 
     2955  var k = st.indexOf("."); 
     2956  if (k==-1) return st; 
     2957  for (var i=st.length-1; i>k && st.charAt(i)=="0"; i--); 
     2958  if (i==k) i--; 
     2959  return st.slice(0,i+1); 
     2960} 
     2961 
     2962function grid(dx,dy) { // for backward compatibility 
     2963  axes(dx,dy,null,dx,dy) 
     2964} 
     2965 
     2966function noaxes() { 
     2967  if (!initialized) initPicture(); 
     2968} 
     2969 
     2970function axes(dx,dy,labels,gdx,gdy) { 
     2971//xscl=x is equivalent to xtick=x; xgrid=x; labels=true; 
     2972  var x, y, ldx, ldy, lx, ly, lxp, lyp, pnode, st; 
     2973  if (!initialized) initPicture(); 
     2974  if (typeof dx=="string") { labels = dx; dx = null; } 
     2975  if (typeof dy=="string") { gdx = dy; dy = null; } 
     2976  if (xscl!=null) {dx = xscl; gdx = xscl; labels = dx} 
     2977  if (yscl!=null) {dy = yscl; gdy = yscl} 
     2978  if (xtick!=null) {dx = xtick} 
     2979  if (ytick!=null) {dy = ytick} 
     2980  dx = (dx==null?xunitlength:dx*xunitlength); 
     2981  dy = (dy==null?dx:dy*yunitlength); 
     2982  fontsize = Math.min(dx/2,dy/2,16); //alert(fontsize) 
     2983  ticklength = fontsize/4; 
     2984  if (xgrid!=null) gdx = xgrid; 
     2985  if (ygrid!=null) gdy = ygrid; 
     2986  if (gdx!=null) { 
     2987    gdx = (typeof gdx=="string"?dx:gdx*xunitlength); 
     2988    gdy = (gdy==null?dy:gdy*yunitlength); 
     2989    pnode = myCreateElementSVG("path"); 
     2990    st=""; 
     2991    for (x = origin[0]; x<width; x = x+gdx) 
     2992      st += " M"+x+",0"+" "+x+","+height; 
     2993    for (x = origin[0]-gdx; x>0; x = x-gdx) 
     2994      st += " M"+x+",0"+" "+x+","+height; 
     2995    for (y = height-origin[1]; y<height; y = y+gdy) 
     2996      st += " M0,"+y+" "+width+","+y; 
     2997    for (y = height-origin[1]-gdy; y>0; y = y-gdy) 
     2998      st += " M0,"+y+" "+width+","+y; 
     2999    pnode.setAttribute("d",st); 
     3000    pnode.setAttribute("stroke-width", .5); 
     3001    pnode.setAttribute("stroke", gridstroke); 
     3002    pnode.setAttribute("fill", fill); 
     3003    svgpicture.appendChild(pnode); 
     3004  } 
     3005  pnode = myCreateElementSVG("path"); 
     3006  st="M0,"+(height-origin[1])+" "+width+","+ 
     3007    (height-origin[1])+" M"+origin[0]+",0 "+origin[0]+","+height; 
     3008  for (x = origin[0]+dx; x<width; x = x+dx) 
     3009    st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","+ 
     3010           (height-origin[1]-ticklength); 
     3011  for (x = origin[0]-dx; x>0; x = x-dx) 
     3012    st += " M"+x+","+(height-origin[1]+ticklength)+" "+x+","+ 
     3013           (height-origin[1]-ticklength); 
     3014  for (y = height-origin[1]+dy; y<height; y = y+dy) 
     3015    st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y; 
     3016  for (y = height-origin[1]-dy; y>0; y = y-dy) 
     3017    st += " M"+(origin[0]+ticklength)+","+y+" "+(origin[0]-ticklength)+","+y; 
     3018  if (labels!=null) with (Math) { 
     3019    ldx = dx/xunitlength; 
     3020    ldy = dy/yunitlength; 
     3021    lx = (xmin>0 || xmax<0?xmin:0); 
     3022    ly = (ymin>0 || ymax<0?ymin:0); 
     3023    lxp = (ly==0?"below":"above"); 
     3024    lyp = (lx==0?"left":"right"); 
     3025    var ddx = floor(1.1-log(ldx)/log(10))+1; 
     3026    var ddy = floor(1.1-log(ldy)/log(10))+1; 
     3027    for (x = ldx; x<=xmax; x = x+ldx) 
     3028      text([x,ly],chopZ(x.toFixed(ddx)),lxp); 
     3029    for (x = -ldx; xmin<=x; x = x-ldx) 
     3030      text([x,ly],chopZ(x.toFixed(ddx)),lxp); 
     3031    for (y = ldy; y<=ymax; y = y+ldy) 
     3032      text([lx,y],chopZ(y.toFixed(ddy)),lyp); 
     3033    for (y = -ldy; ymin<=y; y = y-ldy) 
     3034      text([lx,y],chopZ(y.toFixed(ddy)),lyp); 
     3035  } 
     3036  fontsize = defaultfontsize; 
     3037  pnode.setAttribute("d",st); 
     3038  pnode.setAttribute("stroke-width", .5); 
     3039  pnode.setAttribute("stroke", axesstroke); 
     3040  pnode.setAttribute("fill", fill); 
     3041  pnode.setAttribute("stroke-opacity", strokeopacity); 
     3042  pnode.setAttribute("fill-opacity", fillopacity); 
     3043  svgpicture.appendChild(pnode); 
     3044} 
     3045 
     3046function mathjs(st) { 
     3047  //translate a math formula to js function notation 
     3048  // a^b --> pow(a,b) 
     3049  // na --> n*a 
     3050  // (...)d --> (...)*d 
     3051  // n! --> factorial(n) 
     3052  // sin^-1 --> arcsin etc. 
     3053  //while ^ in string, find term on left and right 
     3054  //slice and concat new formula string 
     3055  st = st.replace(/\s/g,""); 
     3056  if (st.indexOf("^-1")!=-1) { 
     3057    st = st.replace(/sin\^-1/g,"arcsin"); 
     3058    st = st.replace(/cos\^-1/g,"arccos"); 
     3059    st = st.replace(/tan\^-1/g,"arctan"); 
     3060    st = st.replace(/sec\^-1/g,"arcsec"); 
     3061    st = st.replace(/csc\^-1/g,"arccsc"); 
     3062    st = st.replace(/cot\^-1/g,"arccot"); 
     3063    st = st.replace(/sinh\^-1/g,"arcsinh"); 
     3064    st = st.replace(/cosh\^-1/g,"arccosh"); 
     3065    st = st.replace(/tanh\^-1/g,"arctanh"); 
     3066    st = st.replace(/sech\^-1/g,"arcsech"); 
     3067    st = st.replace(/csch\^-1/g,"arccsch"); 
     3068    st = st.replace(/coth\^-1/g,"arccoth"); 
     3069  } 
     3070  st = st.replace(/^e$/g,"(Math.E)"); 
     3071  st = st.replace(/^e([^a-zA-Z])/g,"(Math.E)$1"); 
     3072  st = st.replace(/([^a-zA-Z])e/g,"$1(Math.E)"); 
     3073//  st = st.replace(/([^a-zA-Z])e([^a-zA-Z])/g,"$1(Math.E)$2"); 
     3074  st = st.replace(/([0-9])([\(a-zA-Z])/g,"$1*$2"); 
     3075  st = st.replace(/\)([\(0-9a-zA-Z])/g,"\)*$1"); 
     3076  var i,j,k, ch, nested; 
     3077  while ((i=st.indexOf("^"))!=-1) { 
     3078    //find left argument 
     3079    if (i==0) return "Error: missing argument"; 
     3080    j = i-1; 
     3081    ch = st.charAt(j); 
     3082    if (ch>="0" && ch<="9") {// look for (decimal) number 
     3083      j--; 
     3084      while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--; 
     3085      if (ch==".") { 
     3086        j--; 
     3087        while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--; 
     3088      } 
     3089    } else if (ch==")") {// look for matching opening bracket and function name 
     3090      nested = 1; 
     3091      j--; 
     3092      while (j>=0 && nested>0) { 
     3093        ch = st.charAt(j); 
     3094        if (ch=="(") nested--; 
     3095        else if (ch==")") nested++; 
     3096        j--; 
     3097      } 
     3098      while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z") 
     3099        j--; 
     3100    } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable 
     3101      j--; 
     3102      while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z") 
     3103        j--; 
     3104    } else {  
     3105      return "Error: incorrect syntax in "+st+" at position "+j; 
     3106    } 
     3107    //find right argument 
     3108    if (i==st.length-1) return "Error: missing argument"; 
     3109    k = i+1; 
     3110    ch = st.charAt(k); 
     3111    if (ch>="0" && ch<="9" || ch=="-") {// look for signed (decimal) number 
     3112      k++; 
     3113      while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++; 
     3114      if (ch==".") { 
     3115        k++; 
     3116        while (k<st.length && (ch=st.charAt(k))>="0" && ch<="9") k++; 
     3117      } 
     3118    } else if (ch=="(") {// look for matching closing bracket and function name 
     3119      nested = 1; 
     3120      k++; 
     3121      while (k<st.length && nested>0) { 
     3122        ch = st.charAt(k); 
     3123        if (ch=="(") nested++; 
     3124        else if (ch==")") nested--; 
     3125        k++; 
     3126      } 
     3127    } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable 
     3128      k++; 
     3129      while (k<st.length && (ch=st.charAt(k))>="a" && ch<="z" || 
     3130               ch>="A" && ch<="Z") k++; 
     3131    } else {  
     3132      return "Error: incorrect syntax in "+st+" at position "+k; 
     3133    } 
     3134    st = st.slice(0,j+1)+"Math.pow("+st.slice(j+1,i)+","+st.slice(i+1,k)+")"+ 
     3135           st.slice(k); 
     3136  } 
     3137  while ((i=st.indexOf("!"))!=-1) { 
     3138    //find left argument 
     3139    if (i==0) return "Error: missing argument"; 
     3140    j = i-1; 
     3141    ch = st.charAt(j); 
     3142    if (ch>="0" && ch<="9") {// look for (decimal) number 
     3143      j--; 
     3144      while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--; 
     3145      if (ch==".") { 
     3146        j--; 
     3147        while (j>=0 && (ch=st.charAt(j))>="0" && ch<="9") j--; 
     3148      } 
     3149    } else if (ch==")") {// look for matching opening bracket and function name 
     3150      nested = 1; 
     3151      j--; 
     3152      while (j>=0 && nested>0) { 
     3153        ch = st.charAt(j); 
     3154        if (ch=="(") nested--; 
     3155        else if (ch==")") nested++; 
     3156        j--; 
     3157      } 
     3158      while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z") 
     3159        j--; 
     3160    } else if (ch>="a" && ch<="z" || ch>="A" && ch<="Z") {// look for variable 
     3161      j--; 
     3162      while (j>=0 && (ch=st.charAt(j))>="a" && ch<="z" || ch>="A" && ch<="Z") 
     3163        j--; 
     3164    } else {  
     3165      return "Error: incorrect syntax in "+st+" at position "+j; 
     3166    } 
     3167    st = st.slice(0,j+1)+"factorial("+st.slice(j+1,i)+")"+st.slice(i+1); 
     3168  } 
     3169  return st; 
     3170} 
     3171 
     3172function plot(fun,x_min,x_max,points,id,endpts) { 
     3173  var pth = []; 
     3174  var f = function(x) { return x }, g = fun; 
     3175  var name = null; 
     3176  if (typeof fun=="string")  
     3177    eval("g = function(x){ with(Math) return "+mathjs(fun)+" }"); 
     3178  else if (typeof fun=="object") { 
     3179    eval("f = function(t){ with(Math) return "+mathjs(fun[0])+" }"); 
     3180    eval("g = function(t){ with(Math) return "+mathjs(fun[1])+" }"); 
     3181  } 
     3182  if (typeof x_min=="string") { name = x_min; x_min = xmin } 
     3183  else name = id; 
     3184  var min = (x_min==null?xmin:x_min); 
     3185  var max = (x_max==null?xmax:x_max); 
     3186  var inc = max-min-0.000001*(max-min); 
     3187  inc = (points==null?inc/200:inc/points); 
     3188  var gt; 
     3189//alert(typeof g(min)) 
     3190  for (var t = min; t <= max; t += inc) { 
     3191    gt = g(t); 
     3192    if (!(isNaN(gt)||Math.abs(gt)=="Infinity")) pth[pth.length] = [f(t), gt]; 
     3193  } 
     3194  path(pth,name,null,endpts); 
     3195  return pth; 
     3196} 
     3197 
     3198// make polar plot 
     3199 
     3200// make Riemann sums 
     3201 
     3202function slopefield(fun,dx,dy) { 
     3203  var g = fun; 
     3204  if (typeof fun=="string")  
     3205    eval("g = function(x,y){ with(Math) return "+mathjs(fun)+" }"); 
     3206  var gxy,x,y,u,v,dz; 
     3207  if (dx==null) dx=1; 
     3208  if (dy==null) dy=1; 
     3209  dz = Math.sqrt(dx*dx+dy*dy)/6; 
     3210  var x_min = Math.ceil(xmin/dx); 
     3211  var y_min = Math.ceil(ymin/dy); 
     3212  for (x = x_min; x <= xmax; x += dx) 
     3213    for (y = y_min; y <= ymax; y += dy) { 
     3214      gxy = g(x,y); 
     3215      if (!isNaN(gxy)) { 
     3216        if (Math.abs(gxy)=="Infinity") {u = 0; v = dz;} 
     3217        else {u = dz/Math.sqrt(1+gxy*gxy); v = gxy*u;} 
     3218        line([x-u,y-v],[x+u,y+v]); 
     3219      } 
     3220    } 
     3221} 
     3222 
     3223///////////////////////user graphics commands end here///////////////////////// 
     3224 
     3225function show_props(obj) { 
     3226  var result = ""; 
     3227  for (var i=0; i< obj.childNodes.length; i++) 
     3228    result += obj.childNodes.item(i) + "\n"; 
     3229  return result; 
     3230} 
     3231 
     3232function displayCoord(evt) { 
     3233  if (showcoordinates) { 
     3234    var svgroot = evt.target.parentNode; 
     3235    var nl = svgroot.childNodes; 
     3236    for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++); 
     3237    var cnode = nl.item(i); 
     3238    cnode.mtext = mtext; 
     3239    cnode.mtext([svgroot.getAttribute("width")-(-7),svgroot.getAttribute("height")-7],"("+getX(evt).toFixed(2)+", "+getY(evt).toFixed(2)+")", "left", "", "11"); 
     3240/*    var dnode = nl.item(i+1); 
     3241    dnode.mtext = mtext; 
     3242    dnode.mtext([0,svgroot.getAttribute("height")-6],"Try (shift/alt)-dblclick", "right", "", "8"); 
     3243*/  } 
     3244} 
     3245 
     3246function removeCoord(evt) { 
     3247    var svgroot = evt.target.parentNode; 
     3248    var nl = svgroot.childNodes; 
     3249    for (var i=0; i<nl.length && nl.item(i).nodeName!="text"; i++); 
     3250    var cnode = nl.item(i); 
     3251    cnode.mtext = mtext; 
     3252    cnode.mtext([svgroot.getAttribute("width")-0,svgroot.getAttribute("height")-0],"", "aboveleft", ""); 
     3253/*    var dnode = nl.item(i+1); 
     3254    dnode.mtext = mtext; 
     3255    dnode.mtext([0,svgroot.getAttribute("height")-0],"", "aboveright", ""); 
     3256*/} 
     3257 
     3258function initASCIIMathCalculators(li) { 
     3259  var i; 
     3260  for (i=0; i<li.length; i++) { 
     3261    li[i].innerHTML = calcstr; 
     3262    AMprocessNode(li[i]); 
     3263  } 
     3264  li = document.getElementsByTagName("textarea"); 
     3265  var st; 
     3266  for (i=0; i<li.length; i++) { 
     3267    st = li[i].getAttribute("onkeyup"); 
     3268    if (st!=null) eval(String(st).replace(/function anonymous\(\)/,"")); 
     3269  } 
     3270} 
     3271 
     3272function calculate(inputId,outputId) { 
     3273  var str = document.getElementById(inputId).value; 
     3274  var err = ""; 
     3275  var ind = str.lastIndexOf("\n"); 
     3276  if (ind==str.length-1) str = str.slice(0,ind); 
     3277  str = str.slice(str.lastIndexOf("\n")+1); 
     3278  try { 
     3279    var res = eval(mathjs(str)); 
     3280  } catch(e) { 
     3281    err = "syntax incomplete"; 
     3282  } 
     3283  if (!isNaN(res) && res!="Infinity")  
     3284    str = "`"+str+" =` "+(Math.abs(res-Math.round(res*1000000)/1000000)<1e-15?Math.round(res*1000000)/1000000:res)+err;  
     3285  else if (str!="") str = "`"+str+"` = undefined"; //debug:+mathjs(str); 
     3286  var outnode = document.getElementById(outputId); 
     3287  var n = outnode.childNodes.length; 
     3288  for (var i=0; i<n; i++) 
     3289    outnode.removeChild(outnode.firstChild); 
     3290  outnode.appendChild(document.createTextNode(str)); 
     3291  AMprocessNode(outnode); 
     3292} 
     3293 
     3294function append(st){ 
     3295  document.getElementById('in').value+=st; 
     3296  calculate('in','out'); 
     3297  document.getElementById('in').scrollTop = 1000; 
     3298  document.getElementById('in').focus(); 
     3299} 
     3300 
     3301function clearTextArea(){ 
     3302  document.getElementById('in').value=""; 
     3303  calculate('in','out'); 
     3304  document.getElementById('in').focus(); 
     3305} 
     3306 
     3307var calcstr = "<table align=\"center\">\n<tr><th>\nASCIIMath Scientific Calculator\n</th></tr>\n<tr><td>\nClick in the box to use your keyboard or use the buttons\n</td></tr>\n<tr><td>\n<textarea id=\"in\" rows=\"3\" cols=\"40\" onkeyup=\"calculate('in','out')\"></textarea></td></tr>\n<tr><td height=\"50\">Result: &nbsp; &nbsp; <span id=\"out\"></span></td></tr>\n</table>\n<table align=\"center\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody align=\"center\">\n<tr>\n<td colspan=\"4\">\n<button onclick=\"append('sin^-1(')\"><font size=2>`sin^-1`</font></button><button onclick=\"append('cos^-1(')\"><font size=2>`cos^-1`</font></button><button onclick=\"append('tan^-1(')\"><font size=2>`tan^-1`</font></button></td>\n<td><button onclick=\"clearTextArea()\">&nbsp;`C`&nbsp;</button></td>\n\n</tr>\n<tr>\n<td><button onclick=\"append('pi')\">&nbsp;`pi` &nbsp;</button></td>\n<td><button onclick=\"append('sin(')\">&nbsp;`sin`</button></td>\n<td><button onclick=\"append('cos(')\">&nbsp;`cos`</button></td>\n<td><button onclick=\"append('tan(')\">&nbsp;`tan`</button></td>\n<td><button onclick=\"append('^')\">`x^y`</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('!')\">&nbsp; `!` &nbsp;</button></td>\n\n<td><button onclick=\"append('(')\"><font size=2>&nbsp;&nbsp;`(`&nbsp;&nbsp;</font></button></td>\n<td><button onclick=\"append(')')\"><font size=2>&nbsp;&nbsp;`)`&nbsp;&nbsp;</font></button></td>\n<td><button onclick=\"append('sqrt(')\"><font size=2>`sqrt({::}^\ )`</font></button></td>\n<td><button onclick=\"append('/')\">&nbsp;`-:\ `</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('log(')\">`log`</button></td>\n<td><button onclick=\"append('7')\">&nbsp; `7` &nbsp;</button></td>\n<td><button onclick=\"append('8')\">&nbsp; `8` &nbsp;</button></td>\n\n<td><button onclick=\"append('9')\">&nbsp; `9` &nbsp;</button></td>\n<td><button onclick=\"append('*')\">&nbsp;`times`&nbsp;</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('ln(')\">&nbsp;`ln`&nbsp;</button></td>\n<td><button onclick=\"append('4')\">&nbsp; `4` &nbsp;</button></td>\n<td><button onclick=\"append('5')\">&nbsp; `5` &nbsp;</button></td>\n<td><button onclick=\"append('6')\">&nbsp; `6` &nbsp;</button></td>\n\n<td><button onclick=\"append('-')\">&nbsp;`-{::}`&nbsp;</button></td>\n</tr>\n<tr>\n<td><button onclick=\"append('e')\">&nbsp; `e` &nbsp;</button></td>\n<td><button onclick=\"append('1')\">&nbsp;&nbsp;`1` &nbsp;</button></td>\n<td><button onclick=\"append('2')\">&nbsp; `2` &nbsp;</button></td>\n<td><button onclick=\"append('3')\">&nbsp; `3` &nbsp;</button></td>\n<td><button onclick=\"append('+')\">&nbsp;`+{::}`&nbsp;</button></td>\n\n</tr>\n<tr>\n<td> <!--button onclick=\"append('pi')\">&nbsp;`pi` &nbsp;</button--></td>\n<td><button onclick=\"append('0')\">&nbsp; `0` &nbsp;</button></td>\n<td><button onclick=\"append('.')\">&nbsp; `.` &nbsp;</button></td>\n<td><button onclick=\"append('\\n')\">&nbsp;`\"ent\"`</button></td>\n</tr>\n</tbody>\n</table>"; 
     3308 
     3309// GO1.1 Generic onload by Brothercake 
    9043310// http://www.brothercake.com/ 
    9053311//onload function (replaces the onload="translate()" in the <body> tag) 
    9063312function generic() 
    9073313{ 
    908   translate(); 
     3314  if(!init()) return; 
     3315  if (translateOnLoad) { 
     3316    var nd = document.getElementById("processasciimathinmoodle"); 
     3317    if (nd!=null) dsvglocation = nd.className; 
     3318    if (nd!=null || !checkforprocessasciimathinmoodle) { 
     3319      translate(); 
     3320      if (!noSVG && translateASCIIsvg) drawPictures(); 
     3321    } 
     3322    var li = getElementsByClass(document,"div","ASCIIMathCalculator"); 
     3323    if (!noMathML && li.length>0) initASCIIMathCalculators(li); 
     3324  } 
    9093325}; 
    9103326//setup onload function 
  • trunk/plugins/Equation/Equation.js

    r1067 r1254  
    166166                var node = spans[i]; 
    167167                if (node.className.indexOf ("AM") == -1 || node.getElementsByTagName("math").length == 0) continue; 
    168                 var formula = node.getAttribute("title"); 
     168                var formula = '`' + node.getElementsByTagName('math')[0].getAttribute('title') + '`'; 
    169169                node.innerHTML = formula; 
    170170                node.setAttribute("title", null); 
  • trunk/plugins/Equation/popups/dialog.html

    r987 r1254  
    4040  <script type="text/javascript"> 
    4141 // <![CDATA[ 
     42// START - Added for compatibility with ASCIIMathML 2.0 
     43var AMtranslated = false; 
     44// Next 2 functions copied from ASCIIMathML 1.4.7 
     45function AMcreateElementXHTML(t) { 
     46  if (isIE) return document.createElement(t); 
     47  else return document.createElementNS("http://www.w3.org/1999/xhtml", t); 
     48} 
     49function AMinitSymbols() { 
     50  var texsymbols = [], i; 
     51  for (i=0; i<AMsymbols.length; i++) 
     52    if (AMsymbols[i].tex)  
     53      texsymbols[texsymbols.length] = {input:AMsymbols[i].tex,  
     54        tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype}; 
     55  AMsymbols = AMsymbols.concat(texsymbols); 
     56  AMsymbols.sort(compareNames); 
     57  for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input; 
     58} 
     59// END - Added for compatibility with ASCIIMathML 2.0 
     60 
    4261   window.resizeTo(500, 300); 
    4362var showasciiformulaonhover = false; 
     
    6786      for (var i = 0; i < n; i++) 
    6887        outnode.removeChild(outnode.firstChild); 
    69       outnode.appendChild(document.createComment("`"+str+"`")); 
     88      outnode.appendChild(document.createTextNode("`"+str+"`")); 
    7089      AMprocessNode(outnode,true); 
    7190  } 
Note: See TracChangeset for help on using the changeset viewer.