www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

jax.js (42695B)


      1 /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 
      4 /*************************************************************
      5  *
      6  *  MathJax/jax/output/PreviewHTML/jax.js
      7  *
      8  *  Implements the PreviewHTML OutputJax that displays mathematics
      9  *  using HTML to position the characters from math fonts
     10  *  in their proper locations.
     11  *  
     12  *  ---------------------------------------------------------------------
     13  *  
     14  *  Copyright (c) 2013-2015 The MathJax Consortium
     15  * 
     16  *  Licensed under the Apache License, Version 2.0 (the "License");
     17  *  you may not use this file except in compliance with the License.
     18  *  You may obtain a copy of the License at
     19  * 
     20  *      http://www.apache.org/licenses/LICENSE-2.0
     21  * 
     22  *  Unless required by applicable law or agreed to in writing, software
     23  *  distributed under the License is distributed on an "AS IS" BASIS,
     24  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     25  *  See the License for the specific language governing permissions and
     26  *  limitations under the License.
     27  */
     28 
     29 
     30 (function (AJAX,HUB,HTML,PHTML) {
     31   var MML;
     32 
     33   var EVENT, TOUCH, HOVER; // filled in later
     34 
     35   var FONTS = "'Times New Roman',Times,STIXGeneral,serif";
     36   var STYLES = {
     37     ".MJXp-script": {"font-size":".8em"},
     38 
     39     ".MJXp-right": {
     40       "-webkit-transform-origin":"right",
     41       "-moz-transform-origin":"right",
     42       "-ms-transform-origin":"right",
     43       "-o-transform-origin":"right",
     44       "transform-origin":"right"
     45     },
     46 
     47     ".MJXp-bold": {"font-weight":"bold"},
     48     ".MJXp-italic": {"font-style":"italic"},
     49     ".MJXp-scr": {"font-family":"MathJax_Script,"+FONTS},
     50     ".MJXp-frak": {"font-family":"MathJax_Fraktur,"+FONTS},
     51     ".MJXp-sf": {"font-family":"MathJax_SansSerif,"+FONTS},
     52     ".MJXp-cal": {"font-family":"MathJax_Caligraphic,"+FONTS},
     53     ".MJXp-mono": {"font-family":"MathJax_Typewriter,"+FONTS},
     54     ".MJXp-largeop": {"font-size":"150%"},
     55     ".MJXp-largeop.MJXp-int": {"vertical-align":"-.2em"},
     56 
     57     ".MJXp-math": {
     58       "display": "inline-block",
     59       "line-height": "1.2",
     60       "text-indent": "0",
     61       "font-family": FONTS,
     62       "white-space":"nowrap",
     63       "border-collapse":"collapse"
     64     },
     65     ".MJXp-display": {
     66       "display": "block",
     67       "text-align": "center",
     68       "margin": "1em 0"
     69     },
     70     ".MJXp-math span": {"display": "inline-block"},
     71     ".MJXp-box":  {"display":"block!important", "text-align": "center"},
     72     ".MJXp-box:after": {"content": '" "'},  // needed for when there is no DOCTYPE
     73     ".MJXp-rule": {"display":"block!important", "margin-top":".1em"},
     74     ".MJXp-char": {"display":"block!important"},
     75 
     76     ".MJXp-mo": {"margin": "0 .15em"},
     77 
     78     ".MJXp-mfrac": {"margin": "0 .125em", "vertical-align":".25em"},
     79     ".MJXp-denom": {"display": "inline-table!important", "width":"100%"},
     80     ".MJXp-denom > *": {"display": "table-row!important"},
     81 
     82     ".MJXp-surd": {"vertical-align":"top"},
     83     ".MJXp-surd > *": {"display":"block!important"},
     84 
     85     ".MJXp-script-box > * ": {"display":"table!important", "height":"50%"},
     86     ".MJXp-script-box > * > *": {"display":"table-cell!important","vertical-align":"top"},
     87     ".MJXp-script-box > *:last-child > *": {"vertical-align":"bottom"},
     88     ".MJXp-script-box > * > * > *": {"display":"block!important"},
     89 
     90     ".MJXp-mphantom": {"visibility": "hidden"},
     91 
     92     ".MJXp-munderover": {"display":"inline-table!important"},
     93     ".MJXp-over": {"display":"inline-block!important","text-align":"center"},
     94     ".MJXp-over > *": {"display":"block!important"},
     95     ".MJXp-munderover > *": {"display":"table-row!important"},
     96 
     97     ".MJXp-mtable": {"vertical-align":".25em", "margin":"0 .125em"},
     98     ".MJXp-mtable > *": {"display":"inline-table!important", "vertical-align":"middle"},
     99     ".MJXp-mtr": {"display":"table-row!important"},
    100     ".MJXp-mtd": {"display":"table-cell!important","text-align":"center","padding":".5em 0 0 .5em"},
    101     ".MJXp-mtr > .MJXp-mtd:first-child": {"padding-left":0},
    102     ".MJXp-mtr:first-child > .MJXp-mtd": {"padding-top":0},
    103     ".MJXp-mlabeledtr": {"display":"table-row!important"},
    104     ".MJXp-mlabeledtr > .MJXp-mtd:first-child": {"padding-left":0},
    105     ".MJXp-mlabeledtr:first-child > .MJXp-mtd": {"padding-top":0},
    106     
    107     ".MJXp-merror": {
    108       "background-color": "#FFFF88",
    109       color:   "#CC0000",
    110       border:  "1px solid #CC0000",
    111       padding: "1px 3px",
    112       "font-style": "normal",
    113       "font-size":  "90%"
    114     }
    115   };
    116   
    117   (function () {
    118     for (var i = 0; i < 10; i++) {
    119       var scale = "scaleX(."+i+")";
    120       STYLES[".MJXp-scale"+i] = {
    121         "-webkit-transform":scale,
    122         "-moz-transform":scale,
    123         "-ms-transform":scale,
    124         "-o-transform":scale,
    125         "transform":scale
    126       }
    127     }
    128   })();
    129   
    130   var BIGDIMEN = 1000000;
    131   var V = "V", H = "H";
    132 
    133   PHTML.Augment({
    134     settings: HUB.config.menuSettings,
    135     config: {styles: STYLES},
    136 
    137     hideProcessedMath: false,           // use display:none until all math is processed
    138 
    139     maxStretchyParts: 1000,            // limit the number of parts allowed for
    140                                        // stretchy operators. See issue 366.
    141 
    142     Config: function () {
    143       if (!this.require) {this.require = []}
    144       this.SUPER(arguments).Config.call(this); var settings = this.settings;
    145       if (settings.scale) {this.config.scale = settings.scale}
    146       this.require.push(MathJax.OutputJax.extensionDir+"/MathEvents.js");
    147     },
    148 
    149     Startup: function () {
    150       //
    151       //  Set up event handling
    152       //
    153       EVENT = MathJax.Extension.MathEvents.Event;
    154       TOUCH = MathJax.Extension.MathEvents.Touch;
    155       HOVER = MathJax.Extension.MathEvents.Hover;
    156       this.ContextMenu = EVENT.ContextMenu;
    157       this.Mousedown   = EVENT.AltContextMenu;
    158       this.Mouseover   = HOVER.Mouseover;
    159       this.Mouseout    = HOVER.Mouseout;
    160       this.Mousemove   = HOVER.Mousemove;
    161 
    162       //
    163       //  Determine pixels per inch
    164       //
    165       var div = HTML.addElement(document.body,"div",{style:{width:"5in"}});
    166       this.pxPerInch = div.offsetWidth/5; div.parentNode.removeChild(div);
    167 
    168       //
    169       //  Set up styles and preload web fonts
    170       //
    171       return AJAX.Styles(this.config.styles,["InitializePHTML",this]);
    172     },
    173     InitializePHTML: function () {
    174     },
    175     
    176     preTranslate: function (state) {
    177       var scripts = state.jax[this.id], i, m = scripts.length,
    178           script, prev, span, div, jax;
    179       //
    180       //  Loop through the scripts
    181       //
    182       for (i = 0; i < m; i++) {
    183         script = scripts[i]; if (!script.parentNode) continue;
    184         //
    185         //  Remove any existing output
    186         //
    187         prev = script.previousSibling;
    188         if (prev && String(prev.className).match(/^MathJax_PHTML(_Display)?( MathJax_Processing)?$/))
    189           {prev.parentNode.removeChild(prev)}
    190         //
    191         //  Add the span, and a div if in display mode,
    192         //  then set the role and mark it as being processed
    193         //
    194         jax = script.MathJax.elementJax; if (!jax) continue;
    195         jax.PHTML = {display: (jax.root.Get("display") === "block")}
    196         span = div = HTML.Element("span",{
    197 	  className:"MathJax_PHTML", id:jax.inputID+"-Frame", isMathJax:true, jaxID:this.id,
    198           oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown,
    199           onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove,
    200 	  onclick:EVENT.Click, ondblclick:EVENT.DblClick,
    201           // Added for keyboard accessible menu.
    202           onkeydown: EVENT.Keydown, tabIndex: HUB.getTabOrder(jax)
    203         });
    204 	if (HUB.Browser.noContextMenu) {
    205 	  span.ontouchstart = TOUCH.start;
    206 	  span.ontouchend = TOUCH.end;
    207 	}
    208         if (jax.PHTML.display) {
    209           div = HTML.Element("div",{className:"MathJax_PHTML_Display"});
    210           div.appendChild(span);
    211         }
    212         //
    213         div.className += " MathJax_Processing";
    214         script.parentNode.insertBefore(div,script);
    215       }
    216     },
    217 
    218     Translate: function (script,state) {
    219       if (!script.parentNode) return;
    220 
    221       //
    222       //  Get the data about the math
    223       //
    224       var jax = script.MathJax.elementJax, math = jax.root,
    225           span = document.getElementById(jax.inputID+"-Frame"),
    226           div = (jax.PHTML.display ? span.parentNode : span);
    227       //
    228       //  Typeset the math
    229       //
    230       this.initPHTML(math,span);
    231 //      math.setTeXclass();
    232       try {math.toPreviewHTML(span)} catch (err) {
    233         if (err.restart) {while (span.firstChild) {span.removeChild(span.firstChild)}}
    234         throw err;
    235       }
    236       //
    237       //  Put it in place, and remove the processing marker
    238       //
    239       div.className = div.className.split(/ /)[0];
    240       //
    241       //  Check if we are hiding the math until more is processed
    242       //
    243       if (this.hideProcessedMath) {
    244         //
    245         //  Hide the math and don't let its preview be removed
    246         //
    247         div.className += " MathJax_Processed";
    248         if (script.MathJax.preview) {
    249           jax.PHTML.preview = script.MathJax.preview;
    250           delete script.MathJax.preview;
    251         }
    252       }
    253     },
    254 
    255     postTranslate: function (state) {
    256       var scripts = state.jax[this.id];
    257       if (!this.hideProcessedMath) return;
    258       for (var i = 0, m = scripts.length; i < m; i++) {
    259         var script = scripts[i];
    260         if (script && script.MathJax.elementJax) {
    261           //
    262           //  Remove the processed marker
    263           //
    264           script.previousSibling.className = script.previousSibling.className.split(/ /)[0];
    265           var data = script.MathJax.elementJax.PHTML;
    266           //
    267           //  Remove the preview, if any
    268           //
    269           if (data.preview) {
    270             data.preview.innerHTML = "";
    271             script.MathJax.preview = data.preview;
    272             delete data.preview;
    273           }
    274         }
    275       }
    276     },
    277 
    278     getJaxFromMath: function (math) {
    279       if (math.parentNode.className === "MathJax_PHTML_Display") {math = math.parentNode}
    280       do {math = math.nextSibling} while (math && math.nodeName.toLowerCase() !== "script");
    281       return HUB.getJaxFor(math);
    282     },
    283     getHoverSpan: function (jax,math) {return jax.root.PHTMLspanElement()},
    284     getHoverBBox: function (jax,span,math) {
    285       var bbox = jax.root.PHTML, em = jax.PHTML.outerEm;
    286       var BBOX = {w:bbox.w*em, h:bbox.h*em, d:bbox.d*em};
    287       if (bbox.width) {BBOX.width = bbox.width}
    288       return BBOX;
    289     },
    290     
    291     Zoom: function (jax,span,math,Mw,Mh) {
    292       //
    293       //  Re-render at larger size
    294       //
    295       span.className = "MathJax";
    296       this.idPostfix = "-zoom"; jax.root.toPHTML(span,span); this.idPostfix = "";
    297       //
    298       //  Get height and width of zoomed math and original math
    299       //
    300       span.style.position = "absolute";
    301       if (!width) {math.style.position = "absolute"}
    302       var zW = span.offsetWidth, zH = span.offsetHeight,
    303           mH = math.offsetHeight, mW = math.offsetWidth;
    304       if (mW === 0) {mW = math.parentNode.offsetWidth}; // IE7 gets mW == 0?
    305       span.style.position = math.style.position = "";
    306       //
    307       return {Y:-EVENT.getBBox(span).h, mW:mW, mH:mH, zW:zW, zH:zH};
    308     },
    309 
    310     initPHTML: function (math,span) {},
    311 
    312     Remove: function (jax) {
    313       var span = document.getElementById(jax.inputID+"-Frame");
    314       if (span) {
    315         if (jax.PHTML.display) {span = span.parentNode}
    316         span.parentNode.removeChild(span);
    317       }
    318       delete jax.PHTML;
    319     },
    320     
    321     ID: 0, idPostfix: "",
    322     GetID: function () {this.ID++; return this.ID},
    323 
    324     VARIANT: {
    325       "bold": "MJXp-bold",
    326       "italic": "MJXp-italic",
    327       "bold-italic": "MJXp-bold MJXp-italic",
    328       "script": "MJXp-scr",
    329       "bold-script": "MJXp-scr MJXp-bold",
    330       "fraktur": "MJXp-frak",
    331       "bold-fraktur": "MJXp-frak MJXp-bold",
    332       "monospace": "MJXp-mono",
    333       "sans-serif": "MJXp-sf",
    334       "-tex-caligraphic": "MJXp-cal"
    335     },
    336     MATHSPACE: {
    337       veryverythinmathspace:  1/18,
    338       verythinmathspace:      2/18,
    339       thinmathspace:          3/18,
    340       mediummathspace:        4/18,
    341       thickmathspace:         5/18,
    342       verythickmathspace:     6/18,
    343       veryverythickmathspace: 7/18,
    344       negativeveryverythinmathspace:  -1/18,
    345       negativeverythinmathspace:      -2/18,
    346       negativethinmathspace:          -3/18,
    347       negativemediummathspace:        -4/18,
    348       negativethickmathspace:         -5/18,
    349       negativeverythickmathspace:     -6/18,
    350       negativeveryverythickmathspace: -7/18,
    351 
    352       thin: .08,
    353       medium: .1,
    354       thick: .15,
    355 
    356       infinity: BIGDIMEN
    357     },
    358     TeX: {
    359       x_height:         .430554
    360     },
    361     pxPerInch: 72,
    362     em: 16,
    363 
    364     // ### FIXME:  add more here
    365 
    366     DELIMITERS: {
    367       "(": {dir:V},
    368       "{": {dir:V, w:.58},
    369       "[": {dir:V},
    370       "|": {dir:V, w:.275},
    371       ")": {dir:V},
    372       "}": {dir:V, w:.58},
    373       "]": {dir:V},
    374       "/": {dir:V},
    375       "\\": {dir:V},
    376       "\u2223": {dir:V, w:.275},
    377       "\u2225": {dir:V, w:.55},
    378       "\u230A": {dir:V, w:.5},
    379       "\u230B": {dir:V, w:.5},
    380       "\u2308": {dir:V, w:.5},
    381       "\u2309": {dir:V, w:.5},
    382       "\u27E8": {dir:V, w:.5},
    383       "\u27E9": {dir:V, w:.5},
    384       "\u2191": {dir:V, w:.65},
    385       "\u2193": {dir:V, w:.65},
    386       "\u21D1": {dir:V, w:.75},
    387       "\u21D3": {dir:V, w:.75},
    388       "\u2195": {dir:V, w:.65},
    389       "\u21D5": {dir:V, w:.75},
    390       "\u27EE": {dir:V, w:.275},
    391       "\u27EF": {dir:V, w:.275},
    392       "\u23B0": {dir:V, w:.6},
    393       "\u23B1": {dir:V, w:.6}
    394     },
    395 
    396     REMAPACCENT: {
    397       "\u20D7":"\u2192",  // vector arrow
    398       "'": "\u02CB",
    399       "`": "\u02CA",
    400       ".": "\u02D9",
    401       "^": "\u02C6",
    402       "-": "\u02C9",
    403       "~": "\u02DC",
    404       "\u00AF": "\u02C9",  // macron
    405       "\u00B0": "\u02DA",  // degree sign
    406       "\u00B4": "\u02CA",  // acute accent
    407       "\u0300": "\u02CB",  // combining grave
    408       "\u0301": "\u02CA",  // combining acute
    409       "\u0302": "\u02C6",  // combining circumflex
    410       "\u0303": "\u02DC",  // combinig tilde
    411       "\u0304": "\u02C9",  // combining macron
    412       "\u0305": "\u02C9",  // combining overline
    413       "\u0306": "\u02D8",  // combining breve 
    414       "\u0307": "\u02D9",  // combining dot
    415       "\u0308": "\u00A8",  // combining double dot
    416       "\u030C": "\u02C7"   // combining caron
    417     },
    418     REMAPACCENTUNDER: {
    419     },
    420     
    421     length2em: function (length,size) {
    422       if (typeof(length) !== "string") {length = length.toString()}
    423       if (length === "") {return ""}
    424       if (length === MML.SIZE.NORMAL) {return 1}
    425       if (length === MML.SIZE.BIG)    {return 2}
    426       if (length === MML.SIZE.SMALL)  {return .71}
    427       if (this.MATHSPACE[length])     {return this.MATHSPACE[length]}
    428       var match = length.match(/^\s*([-+]?(?:\.\d+|\d+(?:\.\d*)?))?(pt|em|ex|mu|px|pc|in|mm|cm|%)?/);
    429       var m = parseFloat(match[1]||"1"), unit = match[2];
    430       if (size == null) {size = 1}
    431       if (unit === "em") {return m}
    432       if (unit === "ex") {return m * this.TeX.x_height}
    433       if (unit === "%")  {return m / 100 * size}
    434       if (unit === "px") {return m / this.em}
    435       if (unit === "pt") {return m / 10}                      // 10 pt to an em
    436       if (unit === "pc") {return m * 1.2}                     // 12 pt to a pc
    437       if (unit === "in") {return m * this.pxPerInch / this.em}
    438       if (unit === "cm") {return m * this.pxPerInch / this.em / 2.54}  // 2.54 cm to an inch
    439       if (unit === "mm") {return m * this.pxPerInch / this.em / 25.4}  // 10 mm to a cm
    440       if (unit === "mu") {return m / 18}                     // 18mu to an em for the scriptlevel
    441       return m*size;  // relative to given size (or 1em as default)
    442     },
    443 
    444     Em: function (m) {
    445       if (Math.abs(m) < .001) return "0em";
    446       return (m.toFixed(3).replace(/\.?0+$/,""))+"em";
    447     },
    448 
    449     arrayEntry: function (a,i) {return a[Math.max(0,Math.min(i,a.length-1))]}
    450 
    451   });
    452 
    453   MathJax.Hub.Register.StartupHook("mml Jax Ready",function () {
    454     MML = MathJax.ElementJax.mml;
    455 
    456     MML.mbase.Augment({
    457       toPreviewHTML: function (span,options) {
    458         return this.PHTMLdefaultSpan(span,options);
    459       },
    460 
    461       PHTMLdefaultSpan: function (span,options) {
    462         if (!options) options = {};
    463         span = this.PHTMLcreateSpan(span);
    464         this.PHTMLhandleStyle(span);
    465         this.PHTMLhandleColor(span);
    466         if (this.isToken) this.PHTMLhandleToken(span);
    467         for (var i = 0, m = this.data.length; i < m; i++) this.PHTMLaddChild(span,i,options);
    468         return span;
    469       },
    470       PHTMLaddChild: function (span,i,options) {
    471         var child = this.data[i];
    472         if (child) {
    473           if (options.childSpans)
    474             span = HTML.addElement(span,"span",{className:options.className});
    475           child.toPreviewHTML(span);
    476           if (!options.noBBox) {
    477             this.PHTML.w += child.PHTML.w + child.PHTML.l + child.PHTML.r;
    478             if (child.PHTML.h > this.PHTML.h) this.PHTML.h = child.PHTML.h;
    479             if (child.PHTML.d > this.PHTML.d) this.PHTML.d = child.PHTML.d;
    480             if (child.PHTML.t > this.PHTML.t) this.PHTML.t = child.PHTML.t;
    481             if (child.PHTML.b > this.PHTML.b) this.PHTML.b = child.PHTML.b;
    482           }
    483         } else if (options.forceChild) {HTML.addElement(span,"span")}
    484       },
    485       PHTMLstretchChild: function (i,H,D) {
    486         var data = this.data[i];
    487         if (data && data.PHTMLcanStretch("Vertical",H,D)) {
    488           var bbox = this.PHTML, dbox = data.PHTML, w = dbox.w;
    489           data.PHTMLstretchV(H,D);
    490           bbox.w += dbox.w - w;
    491           if (dbox.h > bbox.h) bbox.h = dbox.h;
    492           if (dbox.d > bbox.d) bbox.d = dbox.d;
    493         }
    494       },
    495 
    496       PHTMLcreateSpan: function (span) {
    497         if (!this.PHTML) this.PHTML = {};
    498         this.PHTML = {w:0, h:0, d:0, l:0, r:0, t:0, b:0};
    499         if (this.inferred) return span;
    500         //  ### FIXME:  This is a hack to handle the different spacing of the
    501         //  ### integral sign in Times compared to CM fonts
    502         if (this.type === "mo" && this.data.join("") === "\u222B") {PHTML.lastIsInt = true}
    503         else if (this.type !== "mspace" || this.width !== "negativethinmathspace") {PHTML.lastIsInt = false}
    504         //  ###
    505         if (!this.PHTMLspanID) {this.PHTMLspanID = PHTML.GetID()};
    506         var id = (this.id || "MJXp-Span-"+this.PHTMLspanID);
    507         return HTML.addElement(span,"span",{className:"MJXp-"+this.type, id:id});
    508       },
    509       PHTMLspanElement: function () {
    510         if (!this.PHTMLspanID) {return null}
    511         return document.getElementById(this.id||"MJXp-Span-"+this.PHTMLspanID);
    512       },
    513 
    514       PHTMLhandleToken: function (span) {
    515         var values = this.getValues("mathvariant");
    516         if (values.mathvariant !== MML.VARIANT.NORMAL) {
    517           span.className += " "+PHTML.VARIANT[values.mathvariant];
    518         }
    519       },
    520 
    521       PHTMLhandleStyle: function (span) {
    522         if (this.style) span.style.cssText = this.style;
    523       },
    524 
    525       PHTMLhandleColor: function (span) {
    526         if (this.mathcolor) {span.style.color = this.mathcolor}
    527         if (this.mathbackground) {span.style.backgroundColor = this.mathbackground}
    528       },
    529 
    530       PHTMLhandleScriptlevel: function (span) {
    531         // ### FIXME:  Need to prevent getting too small
    532         // ### and should keep track of scaling so it can be compensated for
    533         var level = this.Get("scriptlevel");
    534         if (level) span.className += " MJXp-script";
    535       },
    536 
    537       PHTMLhandleText: function (span,text) {
    538         var c, n;
    539         var H = 0, D = 0, W = 0;
    540         for (var i = 0, m = text.length; i < m; i++) {
    541           n = text.charCodeAt(i); c = text.charAt(i);
    542           if (n >= 0xD800 && n < 0xDBFF) {
    543             i++; n = (((n-0xD800)<<10)+(text.charCodeAt(i)-0xDC00))+0x10000;
    544           }
    545           var h = .7, d = .22, w = .5;
    546           if (n < 127) {
    547             if (c.match(/[A-Za-ehik-or-xz0-9]/)) d = 0;
    548             if (c.match(/[A-HK-Z]/)) {w = .67} else if (c.match(/[IJ]/)) {w = .36}
    549             if (c.match(/[acegm-su-z]/)) {h = .45} else if (c.match(/[ij]/)) {h = .75}
    550             if (c.match(/[ijlt]/)) w = .28;
    551           }
    552           if (PHTML.DELIMITERS[c]) {w = PHTML.DELIMITERS[c].w || .4}
    553           // ### FIXME:  handle Greek
    554           // ### Combining diacriticals (all sets), spacing modifiers
    555           // ### arrows (all sets), widths of braces
    556           if (h > H) H = h; if (d > D) D = d; W += w;
    557         }
    558         if (!this.CHML) this.PHTML = {};
    559         this.PHTML = {h:.9, d:.3, w:W, l:0, r:0, t:H, b:D};
    560         HTML.addText(span,text);
    561       },
    562 
    563       PHTMLbboxFor: function (n) {
    564         if (this.data[n] && this.data[n].PHTML) return this.data[n].PHTML;
    565         return {w:0, h:0, d:0, l:0, r:0, t:0, b:0};
    566       },
    567 
    568       PHTMLcanStretch: function (direction,H,D) {
    569         if (this.isEmbellished()) {
    570           var core = this.Core();
    571           if (core && core !== this) {return core.PHTMLcanStretch(direction,H,D)}
    572         }
    573         return false;
    574       },
    575       PHTMLstretchV: function (h,d) {},
    576       PHTMLstretchH: function (w) {},
    577 
    578       CoreParent: function () {
    579         var parent = this;
    580         while (parent && parent.isEmbellished() &&
    581                parent.CoreMO() === this && !parent.isa(MML.math)) {parent = parent.Parent()}
    582         return parent;
    583       },
    584       CoreText: function (parent) {
    585         if (!parent) {return ""}
    586         if (parent.isEmbellished()) {return parent.CoreMO().data.join("")}
    587         while ((parent.isa(MML.mrow) || parent.isa(MML.TeXAtom) ||
    588                 parent.isa(MML.mstyle) || parent.isa(MML.mphantom)) &&
    589                 parent.data.length === 1 && parent.data[0]) {parent = parent.data[0]}
    590         if (!parent.isToken) {return ""} else {return parent.data.join("")}
    591       }
    592 
    593     });
    594 
    595     MML.chars.Augment({
    596       toPreviewHTML: function (span) {
    597         var text = this.toString().replace(/[\u2061-\u2064]/g,"");
    598         this.PHTMLhandleText(span,text);
    599       }
    600     });
    601     MML.entity.Augment({
    602       toPreviewHTML: function (span) {
    603         var text = this.toString().replace(/[\u2061-\u2064]/g,"");
    604         this.PHTMLhandleText(span,text);
    605       }
    606     });
    607 
    608     MML.math.Augment({
    609       toPreviewHTML: function (span) {
    610         span = this.PHTMLdefaultSpan(span);
    611         if (this.Get("display") === "block") {span.className += " MJXp-display"}
    612         return span;
    613       }
    614     });
    615 
    616     MML.mo.Augment({
    617       toPreviewHTML: function (span) {
    618         span = this.PHTMLdefaultSpan(span);
    619         this.PHTMLadjustAccent(span);
    620         var values = this.getValues("lspace","rspace","scriptlevel","displaystyle","largeop");
    621         if (values.scriptlevel === 0) {
    622           this.PHTML.l = PHTML.length2em(values.lspace);
    623           this.PHTML.r = PHTML.length2em(values.rspace);
    624           span.style.marginLeft = PHTML.Em(this.PHTML.l);
    625           span.style.marginRight = PHTML.Em(this.PHTML.r);
    626         } else {
    627           this.PHTML.l = .15;
    628           this.PHTML.r = .1;
    629         }
    630         if (values.displaystyle && values.largeop) {
    631           var box = HTML.Element("span",{className:"MJXp-largeop"});
    632           box.appendChild(span.firstChild); span.appendChild(box);
    633           this.PHTML.h *= 1.2; this.PHTML.d *= 1.2;
    634           if (this.data.join("") === "\u222B") box.className += " MJXp-int";
    635         }
    636         // ### FIXME:  Handle embellished op spacing
    637         // ### FIXME:  Remap minus signs
    638         return span;
    639       },
    640       PHTMLadjustAccent: function (span) {
    641         var parent = this.CoreParent();
    642         if (parent && parent.isa(MML.munderover) && 
    643             this.CoreText(parent.data[parent.base]).length === 1) {
    644           var over = parent.data[parent.over], under = parent.data[parent.under];
    645           var c = this.data.join(""), C;
    646           if (over && this === over.CoreMO() && parent.Get("accent")) {C = PHTML.REMAPACCENT[c]}
    647           else if (under && this === under.CoreMO() && parent.Get("accentunder")) {C = PHTML.REMAPACCENTUNDER[c]}
    648           if (C) c = span.innerHTML = C;
    649           if (c.match(/[\u02C6-\u02DC\u00A8]/)) {this.PHTML.acc = -.52}
    650           else if (c === "\u2192") {this.PHTML.acc = -.15; this.PHTML.vec = true}
    651         }
    652       },
    653       PHTMLcanStretch: function (direction,H,D) {
    654         if (!this.Get("stretchy")) {return false}
    655         var c = this.data.join("");
    656         if (c.length > 1) {return false}
    657         c = PHTML.DELIMITERS[c];
    658         var stretch = (c && c.dir === direction.substr(0,1));
    659         if (stretch) {
    660           stretch = (this.PHTML.h !== H || this.PHTML.d !== D ||
    661             (this.Get("minsize",true) || this.Get("maxsize",true)));
    662         }
    663         return stretch;
    664       },
    665       PHTMLstretchV: function (h,d) {
    666         var span = this.PHTMLspanElement(), bbox = this.PHTML; //bbox.w = .4; // ## adjust width
    667         var values = this.getValues("symmetric","maxsize","minsize");
    668         if (values.symmetric) {H = 2*Math.max(h-.25,d+.25)} else {H = h + d}
    669         values.maxsize = PHTML.length2em(values.maxsize,bbox.h+bbox.d);
    670         values.minsize = PHTML.length2em(values.minsize,bbox.h+bbox.d);
    671         H = Math.max(values.minsize,Math.min(values.maxsize,H));
    672         var scale = H/(bbox.h+bbox.d-.3);  // ### adjusted for extra tall bbox
    673         var box = HTML.Element("span",{style:{"font-size":PHTML.Em(scale)}});
    674         if (scale > 1.25) {
    675           var sX = Math.ceil(1.25/scale * 10);
    676           box.className = "MJXp-right MJXp-scale"+sX;
    677           box.style.marginLeft = PHTML.Em(bbox.w*(sX/10-1)+.07);
    678           bbox.w *= scale*sX/10;
    679         }
    680         box.appendChild(span.firstChild); span.appendChild(box);
    681         if (values.symmetric) span.style.verticalAlign = PHTML.Em(.25*(1-scale));
    682       }
    683     });
    684 
    685     MML.mspace.Augment({
    686       toPreviewHTML: function (span) {
    687         span = this.PHTMLdefaultSpan(span);
    688         var values = this.getValues("height","depth","width");
    689         var w = PHTML.length2em(values.width),
    690             h = PHTML.length2em(values.height),
    691             d = PHTML.length2em(values.depth);
    692         var bbox = this.PHTML;
    693         bbox.w = w; bbox.h = h; bbox.d = d;
    694         if (w < 0) {
    695           //  ### FIXME:  lastIsInt hack
    696           if (!PHTML.lastIsInt) span.style.marginLeft = PHTML.Em(w);
    697           w = 0;
    698         }
    699         span.style.width = PHTML.Em(w);
    700         span.style.height = PHTML.Em(h+d);
    701         if (d) span.style.verticalAlign = PHTML.Em(-d);
    702         return span;
    703       }
    704     });
    705 
    706     MML.mpadded.Augment({
    707       toPreviewHTML: function (span) {
    708         span = this.PHTMLdefaultSpan(span,{
    709           childSpans:true, className:"MJXp-box", forceChild:true
    710         });
    711         var child = span.firstChild;
    712         var values = this.getValues("width","height","depth","lspace","voffset");
    713         var dimen = this.PHTMLdimen(values.lspace);
    714         var T = 0, B = 0, L = dimen.len, R = -dimen.len, V = 0;
    715         if (values.width !== "") {
    716           dimen = this.PHTMLdimen(values.width,"w",0);
    717           if (dimen.pm) {R += dimen.len} else {span.style.width = PHTML.Em(dimen.len)}
    718         }
    719         if (values.height !== "") {
    720           dimen = this.PHTMLdimen(values.height,"h",0);
    721           if (!dimen.pm) T += -this.PHTMLbboxFor(0).h;
    722           T += dimen.len;
    723         }
    724         if (values.depth !== "")  {
    725           dimen = this.PHTMLdimen(values.depth,"d",0);
    726           if (!dimen.pm) {B += -this.PHTMLbboxFor(0).d; V += -dimen.len}
    727           B += dimen.len;
    728         }
    729         if (values.voffset !== "") {
    730           dimen = this.PHTMLdimen(values.voffset);
    731           T -= dimen.len; B += dimen.len;
    732           V += dimen.len;
    733         }
    734         if (T) child.style.marginTop = PHTML.Em(T);
    735         if (B) child.style.marginBottom = PHTML.Em(B);
    736         if (L) child.style.marginLeft = PHTML.Em(L);
    737         if (R) child.style.marginRight = PHTML.Em(R);
    738         if (V) span.style.verticalAlign = PHTML.Em(V);
    739         return span;
    740       },
    741       PHTMLdimen: function (length,d,m) {
    742         if (m == null) {m = -BIGDIMEN}
    743         length = String(length);
    744         var match = length.match(/width|height|depth/);
    745         var size = (match ? this.PHTML[match[0].charAt(0)] : (d ? this.PHTML[d] : 0));
    746         return {len: PHTML.length2em(length,size)||0, pm: !!length.match(/^[-+]/)};
    747       }
    748     });
    749 
    750     MML.munderover.Augment({
    751       toPreviewHTML: function (span) {
    752 	var values = this.getValues("displaystyle","accent","accentunder","align");
    753         var base = this.data[this.base];
    754 	if (!values.displaystyle && base != null &&
    755 	    (base.movablelimits || base.CoreMO().Get("movablelimits"))) {
    756           span = MML.msubsup.prototype.toPreviewHTML.call(this,span);
    757           //
    758           //  Change class to msubsup for CSS rules.
    759           //  ### FIXME: should this be handled via adding another class instead?
    760           //
    761           span.className = span.className.replace(/munderover/,"msubsup");
    762           return span;
    763         }
    764         span = this.PHTMLdefaultSpan(span,{childSpans:true, className:"", noBBox:true});
    765         var obox = this.PHTMLbboxFor(this.over),
    766             ubox = this.PHTMLbboxFor(this.under),
    767             bbox = this.PHTMLbboxFor(this.base),
    768             BBOX = this.PHTML, acc = obox.acc;
    769         if (this.data[this.over]) {
    770           span.lastChild.firstChild.style.marginLeft = obox.l =
    771             span.lastChild.firstChild.style.marginRight = obox.r = 0;
    772           var over = HTML.Element("span",{},[["span",{className:"MJXp-over"}]]);
    773           over.firstChild.appendChild(span.lastChild);
    774           if (span.childNodes.length > (this.data[this.under] ? 1 : 0))
    775             over.firstChild.appendChild(span.firstChild);
    776           this.data[this.over].PHTMLhandleScriptlevel(over.firstChild.firstChild);
    777           if (acc != null) {
    778             if (obox.vec) {
    779               over.firstChild.firstChild.firstChild.style.fontSize = "60%";
    780               obox.h *= .6; obox.d *= .6; obox.w *= .6;
    781             }
    782             acc = acc - obox.d + .1; if (bbox.t != null) {acc += bbox.t - bbox.h}
    783             over.firstChild.firstChild.style.marginBottom = PHTML.Em(acc);
    784           }
    785           if (span.firstChild) {span.insertBefore(over,span.firstChild)}
    786             else {span.appendChild(over)}
    787         }
    788         if (this.data[this.under]) {
    789           span.lastChild.firstChild.style.marginLeft = ubox.l =
    790             span.lastChild.firstChild.marginRight = ubox.r = 0;
    791           this.data[this.under].PHTMLhandleScriptlevel(span.lastChild);
    792         }
    793         BBOX.w = Math.max(.8*obox.w,.8*ubox.w,bbox.w);
    794         BBOX.h = .8*(obox.h+obox.d+(acc||0)) + bbox.h;
    795         BBOX.d = bbox.d + .8*(ubox.h+ubox.d);
    796         return span;
    797       }
    798     });
    799 
    800     MML.msubsup.Augment({
    801       toPreviewHTML: function (span) {
    802         span = this.PHTMLdefaultSpan(span,{noBBox:true});
    803         if (!this.data[this.base]) {
    804           if (span.firstChild) {span.insertBefore(HTML.Element("span"),span.firstChild)}
    805             else {span.appendChild(HTML.Element("span"))}
    806         }
    807         var base = this.data[this.base], sub = this.data[this.sub], sup = this.data[this.sup];
    808         if (!base) base = {bbox: {h:.8, d:.2}};
    809         span.firstChild.style.marginRight = ".05em";
    810         var h = Math.max(.4,base.PHTML.h-.4),
    811             d = Math.max(.2,base.PHTML.d+.1);
    812         var bbox = this.PHTML;
    813         if (sup && sub) {
    814           var box = HTML.Element("span",{className:"MJXp-script-box", style:{
    815             height: PHTML.Em(h+sup.PHTML.h*.8 + d+sub.PHTML.d*.8),
    816             "vertical-align": PHTML.Em(-d-sub.PHTML.d*.8)
    817           }},[
    818             ["span",{},[["span",{},[["span",{
    819               style:{"margin-bottom":PHTML.Em(-(sup.PHTML.d-.05))}
    820             }]]]]],
    821             ["span",{},[["span",{},[["span",{
    822               style:{"margin-top":PHTML.Em(-(sup.PHTML.h-.05))}
    823             }]]]]]
    824           ]);
    825           sub.PHTMLhandleScriptlevel(box.firstChild);
    826           sup.PHTMLhandleScriptlevel(box.lastChild);
    827           box.firstChild.firstChild.firstChild.appendChild(span.lastChild);
    828           box.lastChild.firstChild.firstChild.appendChild(span.lastChild);
    829           span.appendChild(box);
    830           bbox.h = Math.max(base.PHTML.h,sup.PHTML.h*.8+h);
    831           bbox.d = Math.max(base.PHTML.d,sub.PHTML.d*.8+d);
    832           bbox.w = base.PHTML.w + Math.max(sup.PHTML.w,sub.PHTML.w) + .07;
    833         } else if (sup) {
    834           span.lastChild.style.verticalAlign = PHTML.Em(h);
    835           sup.PHTMLhandleScriptlevel(span.lastChild);
    836           bbox.h = Math.max(base.PHTML.h,sup.PHTML.h*.8+h);
    837           bbox.d = Math.max(base.PHTML.d,sup.PHTML.d*.8-h);
    838           bbox.w = base.PHTML.w + sup.PHTML.w + .07;
    839         } else if (sub) {
    840           span.lastChild.style.verticalAlign = PHTML.Em(-d);
    841           sub.PHTMLhandleScriptlevel(span.lastChild);
    842           bbox.h = Math.max(base.PHTML.h,sub.PHTML.h*.8-d);
    843           bbox.d = Math.max(base.PHTML.d,sub.PHTML.d*.8+d);
    844           bbox.w = base.PHTML.w + sub.PHTML.w + .07;
    845         }
    846         return span;
    847       }
    848     });
    849 
    850     MML.mfrac.Augment({
    851       toPreviewHTML: function (span) {
    852         span = this.PHTMLdefaultSpan(span,{
    853           childSpans:true, className:"MJXp-box", forceChild:true, noBBox:true
    854         });
    855         var values = this.getValues("linethickness","displaystyle");
    856         if (!values.displaystyle) {
    857           if (this.data[0]) this.data[0].PHTMLhandleScriptlevel(span.firstChild);
    858           if (this.data[1]) this.data[1].PHTMLhandleScriptlevel(span.lastChild);
    859         }
    860         var denom = HTML.Element("span",{className:"MJXp-box"},[
    861           ["span",{className:"MJXp-denom"},[                        // inline-table
    862             ["span",{},[["span",{className:"MJXp-rule",style:{height:"1em"}}]]],
    863             ["span"]                                                // spans are table-row
    864           ]]
    865         ]);
    866         denom.firstChild.lastChild.appendChild(span.lastChild);
    867         span.appendChild(denom);
    868         var nbox = this.PHTMLbboxFor(0), dbox = this.PHTMLbboxFor(1), bbox = this.PHTML;
    869         bbox.w = Math.max(nbox.w,dbox.w) * .8;
    870         bbox.h = nbox.h+nbox.d + .1 + .25;
    871         bbox.d = dbox.h+dbox.d - .25;
    872         bbox.l = bbox.r = .125;
    873         values.linethickness = Math.max(0,PHTML.length2em(values.linethickness||"0",0));
    874         if (values.linethickness) {
    875           var rule = denom.firstChild.firstChild.firstChild;
    876           var t = PHTML.Em(values.linethickness);
    877           rule.style.borderTop = "none";
    878           rule.style.borderBottom = (values.linethickness < .15 ? "1px" : t)+" solid";
    879           rule.style.margin = t+" 0";
    880           t = values.linethickness;
    881           denom.style.marginTop = PHTML.Em(3*t-1.2);
    882           span.style.verticalAlign = PHTML.Em(1.5*t + .1);
    883           bbox.h += 1.5*t - .1; bbox.d += 1.5*t;
    884         } else {
    885           denom.style.marginTop = "-.7em";
    886         }
    887         return span;
    888       }
    889     });
    890 
    891     MML.msqrt.Augment({
    892       toPreviewHTML: function (span) {
    893         span = this.PHTMLdefaultSpan(span,{
    894           childSpans:true, className:"MJXp-box", forceChild:true, noBBox:true
    895         });
    896         this.PHTMLlayoutRoot(span,span.firstChild);
    897         return span;
    898       },
    899       PHTMLlayoutRoot: function (span,base) {
    900         var bbox = this.PHTMLbboxFor(0);
    901         var scale = Math.ceil((bbox.h+bbox.d+.14)*100), t = PHTML.Em(14/scale);
    902         var surd = HTML.Element("span",{className:"MJXp-surd"},[
    903           ["span",{style:{"font-size":scale+"%","margin-top":t}},["\u221A"]]
    904         ]);
    905         var root = HTML.Element("span",{className:"MJXp-root"},[
    906           ["span",{className:"MJXp-rule",style:{"border-top":".08em solid"}}]
    907         ]);
    908         var W = (1.2/2.2)*scale/100; // width-of-surd = (height/H-to-W-ratio)
    909         if (scale > 150) {
    910           var sX = Math.ceil(150/scale * 10);
    911           surd.firstChild.className = "MJXp-right MJXp-scale"+sX;
    912           surd.firstChild.style.marginLeft = PHTML.Em(W*(sX/10-1)/scale*100);
    913           W = W*sX/10;
    914           root.firstChild.style.borderTopWidth = PHTML.Em(.08/Math.sqrt(sX/10));
    915         }
    916         root.appendChild(base);
    917         span.appendChild(surd);
    918         span.appendChild(root);
    919         this.PHTML.h = bbox.h + .18; this.PHTML.d = bbox.d;
    920         this.PHTML.w = bbox.w + W; 
    921         return span;
    922       }
    923     });
    924 
    925     MML.mroot.Augment({
    926       toPreviewHTML: function (span) {
    927         span = this.PHTMLdefaultSpan(span,{
    928           childSpans:true, className:"MJXp-box", forceChild:true, noBBox:true
    929         });
    930         var rbox = this.PHTMLbboxFor(1), root = span.removeChild(span.lastChild);
    931         var sqrt = this.PHTMLlayoutRoot(HTML.Element("span"),span.firstChild);
    932         root.className = "MJXp-script";  // ### FIXME: should be scriptscript
    933         var scale = parseInt(sqrt.firstChild.firstChild.style.fontSize);
    934         var v = .55*(scale/120) + rbox.d*.8, r = -.6*(scale/120);
    935         if (scale > 150) {r *= .95*Math.ceil(150/scale*10)/10}
    936         root.style.marginRight = PHTML.Em(r); root.style.verticalAlign = PHTML.Em(v);
    937         if (-r > rbox.w*.8) root.style.marginLeft = PHTML.Em(-r-rbox.w*.8); // ### depends on rbox.w
    938         span.appendChild(root); span.appendChild(sqrt);
    939         this.PHTML.w += Math.max(0,rbox.w*.8+r);
    940         this.PHTML.h = Math.max(this.PHTML.h,rbox.h*.8+v);
    941         return span;
    942       },
    943       PHTMLlayoutRoot: MML.msqrt.prototype.PHTMLlayoutRoot
    944     });
    945     
    946     MML.mfenced.Augment({
    947       toPreviewHTML: function (span) {
    948         span = this.PHTMLcreateSpan(span);
    949         this.PHTMLhandleStyle(span);
    950         this.PHTMLhandleColor(span);
    951         //
    952         //  Make row of open, data, sep, ... data, close
    953         //
    954         this.addFakeNodes();
    955         this.PHTMLaddChild(span,"open",{});
    956         for (var i = 0, m = this.data.length; i < m; i++) {
    957           this.PHTMLaddChild(span,"sep"+i,{});
    958           this.PHTMLaddChild(span,i,{});
    959         }
    960         this.PHTMLaddChild(span,"close",{});
    961         //
    962         //  Check for streching the elements
    963         //
    964         var H = this.PHTML.h, D = this.PHTML.d;
    965         this.PHTMLstretchChild("open",H,D);
    966         for (i = 0, m = this.data.length; i < m; i++) {
    967           this.PHTMLstretchChild("sep"+i,H,D);
    968           this.PHTMLstretchChild(i,H,D);
    969         }
    970         this.PHTMLstretchChild("close",H,D);
    971         return span;
    972       }
    973     });
    974 
    975     MML.mrow.Augment({
    976       toPreviewHTML: function (span) {
    977         span = this.PHTMLdefaultSpan(span);
    978         var H = this.PHTML.h, D = this.PHTML.d;
    979         for (var i = 0, m = this.data.length; i < m; i++) this.PHTMLstretchChild(i,H,D);
    980         return span;
    981       }
    982     });
    983 
    984     MML.mstyle.Augment({
    985       toPreviewHTML: function (span) {
    986         span = this.PHTMLdefaultSpan(span);
    987         this.PHTMLhandleScriptlevel(span);
    988         return span;
    989       }
    990     });
    991 
    992     MML.TeXAtom.Augment({
    993       toPreviewHTML: function (span) {
    994         span = this.PHTMLdefaultSpan(span);
    995         // ### FIXME: handle TeX class?
    996         span.className = "MJXp-mrow";
    997         return span;
    998       }
    999     });
   1000 
   1001     MML.mtable.Augment({
   1002       toPreviewHTML: function (span) {
   1003         span = this.PHTMLdefaultSpan(span,{noBBox:true});
   1004         var values = this.getValues("columnalign","rowalign","columnspacing","rowspacing",
   1005                                     "columnwidth","equalcolumns","equalrows",
   1006                                     "columnlines","rowlines","frame","framespacing",
   1007                                     "align","width");
   1008         var SPLIT = MathJax.Hub.SplitList, i, m, j, n;
   1009         var CSPACE = SPLIT(values.columnspacing),
   1010             RSPACE = SPLIT(values.rowspacing),
   1011             CALIGN = SPLIT(values.columnalign),
   1012             RALIGN = SPLIT(values.rowalign);
   1013         for (i = 0, m = CSPACE.length; i < m; i++) {CSPACE[i] = PHTML.length2em(CSPACE[i])}
   1014         for (i = 0, m = RSPACE.length; i < m; i++) {RSPACE[i] = PHTML.length2em(RSPACE[i])}
   1015 
   1016         var table = HTML.Element("span");
   1017         while (span.firstChild) table.appendChild(span.firstChild);
   1018         span.appendChild(table);
   1019         var H = 0, W = 0;
   1020         for (i = 0, m = this.data.length; i < m; i++) {
   1021           var row = this.data[i];
   1022           if (row) {
   1023             var rspace = PHTML.arrayEntry(RSPACE,i-1), ralign = PHTML.arrayEntry(RALIGN,i);
   1024             var rbox = row.PHTML, rspan = row.PHTMLspanElement();
   1025             rspan.style.verticalAlign = ralign;
   1026             var k = (row.type === "mlabeledtr" ? 1 : 0);
   1027             for (j = 0, n = row.data.length; j < n-k; j++) {
   1028               var cell = row.data[j+k];
   1029               if (cell) {
   1030                 var cspace = PHTML.arrayEntry(CSPACE,j-1), calign = PHTML.arrayEntry(CALIGN,j);
   1031                 var cspan = cell.PHTMLspanElement();
   1032                 if (j) {rbox.w += cspace; cspan.style.paddingLeft = PHTML.Em(cspace)}
   1033                 if (i) cspan.style.paddingTop = PHTML.Em(rspace);
   1034                 cspan.style.textAlign = calign;
   1035               }
   1036             }
   1037             H += rbox.h + rbox.d; if (i) {H += rspace}
   1038             if (rbox.w > W) W = rbox.w;
   1039           }
   1040         }
   1041         var bbox = this.PHTML;
   1042         bbox.w = W; bbox.h = H/2 + .25; bbox.d = H/2 - .25;
   1043         bbox.l = bbox.r = .125;
   1044         return span;
   1045       }
   1046     });
   1047     MML.mlabeledtr.Augment({
   1048       PHTMLdefaultSpan: function (span,options) {
   1049         if (!options) options = {};
   1050         span = this.PHTMLcreateSpan(span);
   1051         this.PHTMLhandleStyle(span);
   1052         this.PHTMLhandleColor(span);
   1053         if (this.isToken) this.PHTMLhandleToken(span);
   1054         // skip label for now
   1055         for (var i = 1, m = this.data.length; i < m; i++) this.PHTMLaddChild(span,i,options);
   1056         return span;
   1057       }
   1058     });
   1059 
   1060     MML.semantics.Augment({
   1061       toPreviewHTML: function (span) {
   1062         span = this.PHTMLcreateSpan(span);
   1063         if (this.data[0]) {
   1064           this.data[0].toPreviewHTML(span);
   1065           MathJax.Hub.Insert(this.data[0].PHTML||{},this.PHTML);
   1066         }
   1067         return span;
   1068       }
   1069     });
   1070     MML.annotation.Augment({toPreviewHTML: function(span) {}});
   1071     MML["annotation-xml"].Augment({toPreviewHTML: function(span) {}});
   1072 
   1073     //
   1074     //  Loading isn't complete until the element jax is modified,
   1075     //  but can't call loadComplete within the callback for "mml Jax Ready"
   1076     //  (it would call PreviewHTML's Require routine, asking for the mml jax again)
   1077     //  so wait until after the mml jax has finished processing.
   1078     //  
   1079     //  We also need to wait for the onload handler to run, since the loadComplete
   1080     //  will call Config and Startup, which need to modify the body.
   1081     //
   1082     MathJax.Hub.Register.StartupHook("onLoad",function () {
   1083       setTimeout(MathJax.Callback(["loadComplete",PHTML,"jax.js"]),0);
   1084     });
   1085   });
   1086 
   1087   MathJax.Hub.Register.StartupHook("End Cookie", function () {  
   1088     if (HUB.config.menuSettings.zoom !== "None")
   1089       {AJAX.Require("[MathJax]/extensions/MathZoom.js")}
   1090   });
   1091     
   1092 })(MathJax.Ajax,MathJax.Hub,MathJax.HTML,MathJax.OutputJax.PreviewHTML);