jax.js 42 KB

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