mtable.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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/HTML-CSS/autoload/mtable.js
  6. *
  7. * Implements the HTML-CSS output for <mtable> elements.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2010-2017 The MathJax Consortium
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License");
  14. * you may not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS,
  21. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. */
  25. MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () {
  26. var VERSION = "2.7.2";
  27. var MML = MathJax.ElementJax.mml,
  28. HTMLCSS = MathJax.OutputJax["HTML-CSS"];
  29. MML.mtable.Augment({
  30. toHTML: function (span) {
  31. span = this.HTMLcreateSpan(span);
  32. if (this.data.length === 0) {return span}
  33. var values = this.getValues("columnalign","rowalign","columnspacing","rowspacing",
  34. "columnwidth","equalcolumns","equalrows",
  35. "columnlines","rowlines","frame","framespacing",
  36. "align","useHeight","width","side","minlabelspacing");
  37. var hasRelativeWidth = values.width.match(/%$/);
  38. var stack = HTMLCSS.createStack(span);
  39. var scale = this.HTMLgetScale(), mu = this.HTMLgetMu(span), LABEL = -1;
  40. var H = [], D = [], W = [], A = [], C = [], i, j, J = -1,
  41. m, M, s, row, cell, mo, entries = [], HD;
  42. var LH = HTMLCSS.FONTDATA.lineH * scale * values.useHeight,
  43. LD = HTMLCSS.FONTDATA.lineD * scale * values.useHeight;
  44. //
  45. // Create cells and measure columns and rows
  46. //
  47. for (i = 0, m = this.data.length; i < m; i++) {
  48. row = this.data[i]; s = (row.type === "mlabeledtr" ? LABEL : 0);
  49. A[i] = []; H[i] = LH; D[i] = LD;
  50. for (j = s, M = row.data.length + s; j < M; j++) {
  51. if (W[j] == null) {
  52. if (j > J) {J = j}
  53. C[j] = HTMLCSS.createStack(HTMLCSS.createBox(stack));
  54. W[j] = -HTMLCSS.BIGDIMEN;
  55. }
  56. A[i][j] = HTMLCSS.createBox(C[j]);
  57. entries.push(row.data[j-s].toHTML(A[i][j]));
  58. }
  59. }
  60. HTMLCSS.MeasureSpans(entries);
  61. for (i = 0, m = this.data.length; i < m; i++) {
  62. row = this.data[i]; s = (row.type === "mlabeledtr" ? LABEL : 0);
  63. for (j = s, M = row.data.length + s; j < M; j++) {
  64. cell = row.data[j-s];
  65. if (cell.isMultiline) {A[i][j].style.width = "100%"}
  66. if (cell.isEmbellished()) {
  67. mo = cell.CoreMO();
  68. var min = mo.Get("minsize",true);
  69. if (min) {
  70. var bbox = mo.HTMLspanElement().bbox;
  71. if (mo.HTMLcanStretch("Vertical")) {
  72. HD = bbox.h + bbox.d;
  73. if (HD) {
  74. min = HTMLCSS.length2em(min,mu,HD);
  75. if (min*bbox.h/HD > H[i]) {H[i] = min*bbox.h/HD}
  76. if (min*bbox.d/HD > D[i]) {D[i] = min*bbox.d/HD}
  77. }
  78. } else if (mo.HTMLcanStretch("Horizontal")) {
  79. min = HTMLCSS.length2em(min,mu,bbox.w);
  80. if (min > W[j]) {W[j] = min}
  81. }
  82. }
  83. }
  84. if (A[i][j].bbox.h > H[i]) {H[i] = A[i][j].bbox.h}
  85. if (A[i][j].bbox.d > D[i]) {D[i] = A[i][j].bbox.d}
  86. if (A[i][j].bbox.w > W[j]) {W[j] = A[i][j].bbox.w}
  87. }
  88. }
  89. //
  90. // Determine spacing and alignment
  91. //
  92. var SPLIT = MathJax.Hub.SplitList;
  93. var CSPACE = SPLIT(values.columnspacing),
  94. RSPACE = SPLIT(values.rowspacing),
  95. CALIGN = SPLIT(values.columnalign),
  96. RALIGN = SPLIT(values.rowalign),
  97. CLINES = SPLIT(values.columnlines),
  98. RLINES = SPLIT(values.rowlines),
  99. CWIDTH = SPLIT(values.columnwidth),
  100. RCALIGN = [];
  101. for (i = 0, m = CSPACE.length; i < m; i++) {CSPACE[i] = HTMLCSS.length2em(CSPACE[i],mu)}
  102. for (i = 0, m = RSPACE.length; i < m; i++) {RSPACE[i] = HTMLCSS.length2em(RSPACE[i],mu)}
  103. while (CSPACE.length < J) {CSPACE.push(CSPACE[CSPACE.length-1])}
  104. while (CALIGN.length <= J) {CALIGN.push(CALIGN[CALIGN.length-1])}
  105. while (CLINES.length < J) {CLINES.push(CLINES[CLINES.length-1])}
  106. while (CWIDTH.length <= J) {CWIDTH.push(CWIDTH[CWIDTH.length-1])}
  107. while (RSPACE.length < A.length) {RSPACE.push(RSPACE[RSPACE.length-1])}
  108. while (RALIGN.length <= A.length) {RALIGN.push(RALIGN[RALIGN.length-1])}
  109. while (RLINES.length < A.length) {RLINES.push(RLINES[RLINES.length-1])}
  110. if (C[LABEL]) {
  111. CALIGN[LABEL] = (values.side.substr(0,1) === "l" ? "left" : "right");
  112. CSPACE[LABEL] = -W[LABEL];
  113. }
  114. //
  115. // Override row data
  116. //
  117. for (i = 0, m = A.length; i < m; i++) {
  118. row = this.data[i]; RCALIGN[i] = [];
  119. if (row.rowalign) {RALIGN[i] = row.rowalign}
  120. if (row.columnalign) {
  121. RCALIGN[i] = SPLIT(row.columnalign);
  122. while (RCALIGN[i].length <= J) {RCALIGN[i].push(RCALIGN[i][RCALIGN[i].length-1])}
  123. }
  124. }
  125. //
  126. // Handle equal heights
  127. //
  128. if (values.equalrows) {
  129. // FIXME: should really be based on row align (below is for baseline)
  130. var Hm = Math.max.apply(Math,H), Dm = Math.max.apply(Math,D);
  131. for (i = 0, m = A.length; i < m; i++)
  132. {s = ((Hm + Dm) - (H[i] + D[i])) / 2; H[i] += s; D[i] += s}
  133. }
  134. // FIXME: do background colors for entire cell (include half the intercolumn space?)
  135. //
  136. // Determine array total height
  137. //
  138. HD = H[0] + D[A.length-1];
  139. for (i = 0, m = A.length-1; i < m; i++) {HD += Math.max(0,D[i]+H[i+1]+RSPACE[i])}
  140. //
  141. // Determine frame and line sizes
  142. //
  143. var fx = 0, fy = 0, fW, fH = HD;
  144. if (values.frame !== "none" ||
  145. (values.columnlines+values.rowlines).match(/solid|dashed/)) {
  146. var frameSpacing = SPLIT(values.framespacing);
  147. if (frameSpacing.length != 2) {
  148. // invalid attribute value: use the default.
  149. frameSpacing = SPLIT(this.defaults.framespacing);
  150. }
  151. fx = HTMLCSS.length2em(frameSpacing[0],mu);
  152. fy = HTMLCSS.length2em(frameSpacing[1],mu);
  153. fH = HD + 2*fy; // fW waits until stack.bbox.w is determined
  154. }
  155. //
  156. // Compute alignment
  157. //
  158. var Y, fY, n = "";
  159. if (typeof(values.align) !== "string") {values.align = String(values.align)}
  160. if (values.align.match(/(top|bottom|center|baseline|axis)( +(-?\d+))?/))
  161. {n = RegExp.$3||""; values.align = RegExp.$1} else {values.align = this.defaults.align}
  162. if (n !== "") {
  163. //
  164. // Find the height of the given row
  165. //
  166. n = parseInt(n);
  167. if (n < 0) {n = A.length + 1 + n}
  168. if (n < 1) {n = 1} else if (n > A.length) {n = A.length}
  169. Y = 0; fY = -(HD + fy) + H[0];
  170. for (i = 0, m = n-1; i < m; i++) {
  171. // FIXME: Should handle values.align for final row
  172. var dY = Math.max(0,D[i]+H[i+1]+RSPACE[i]);
  173. Y += dY; fY += dY;
  174. }
  175. } else {
  176. Y = ({
  177. top: -(H[0] + fy),
  178. bottom: HD + fy - H[0],
  179. center: HD/2 - H[0],
  180. baseline: HD/2 - H[0],
  181. axis: HD/2 + HTMLCSS.TeX.axis_height*scale - H[0]
  182. })[values.align];
  183. fY = ({
  184. top: -(HD + 2*fy),
  185. bottom: 0,
  186. center: -(HD/2 + fy),
  187. baseline: -(HD/2 + fy),
  188. axis: HTMLCSS.TeX.axis_height*scale - HD/2 - fy
  189. })[values.align];
  190. }
  191. var WW, WP = 0, Wt = 0, Wp = 0, p = 0, f = 0, P = [], F = [], Wf = 1;
  192. //
  193. if (values.equalcolumns && values.width !== "auto") {
  194. //
  195. // Handle equalcolumns for percent-width and fixed-width tables
  196. //
  197. if (hasRelativeWidth) {
  198. // Set widths to percentages
  199. WW = (100/(J+1)).toFixed(2).replace(/\.?0+$/,"")+"%";
  200. for (i = 0, m = Math.min(J+1,CWIDTH.length); i < m; i++) {CWIDTH[i] = WW}
  201. // Get total column spacing
  202. WW = 0; WP = 1; f = J+1;
  203. for (i = 0, m = Math.min(J+1,CSPACE.length); i < m; i++) {WW += CSPACE[i]}
  204. } else {
  205. // Get total width minus column spacing
  206. WW = HTMLCSS.length2em(values.width,mu);
  207. for (i = 0, m = Math.min(J,CSPACE.length); i < m; i++) {WW -= CSPACE[i]}
  208. // Determine individual column widths
  209. WW /= J;
  210. for (i = 0, m = Math.min(J+1,CWIDTH.length); i < m; i++) {W[i] = WW}
  211. }
  212. } else {
  213. //
  214. // Get column widths for fit and percentage columns
  215. //
  216. // Calculate the natural widths and percentage widths,
  217. // while keeping track of the fit and percentage columns
  218. for(i = 0, m = Math.min(J+1,CWIDTH.length); i < m; i++) {
  219. if (CWIDTH[i] === "auto") {Wt += W[i]}
  220. else if (CWIDTH[i] === "fit") {F[f] = i; f++; Wt += W[i]}
  221. else if (CWIDTH[i].match(/%$/))
  222. {P[p] = i; p++; Wp += W[i]; WP += HTMLCSS.length2em(CWIDTH[i],mu,1)}
  223. else {W[i] = HTMLCSS.length2em(CWIDTH[i],mu); Wt += W[i]}
  224. }
  225. if (hasRelativeWidth) {
  226. // Get separation width and check percentages
  227. WW = 0; for (i = 0, m = Math.min(J,CSPACE.length); i < m; i++) {WW += CSPACE[i]}
  228. if (WP > .98) {Wf = .98/WP; WP = .98}
  229. } else {
  230. // Get the full width (excluding inter-column spacing)
  231. if (values.width === "auto") {
  232. if (WP > .98) {Wf = Wp/(Wt+Wp); WW = Wt + Wp} else {WW = Wt / (1-WP)}
  233. } else {
  234. WW = HTMLCSS.length2em(values.width,mu);
  235. for (i = 0, m = Math.min(J,CSPACE.length); i < m; i++) {WW -= CSPACE[i]}
  236. }
  237. // Determine the relative column widths
  238. for (i = 0, m = P.length; i < m; i++) {
  239. W[P[i]] = HTMLCSS.length2em(CWIDTH[P[i]],mu,WW*Wf); Wt += W[P[i]];
  240. }
  241. // Stretch fit columns, if any, otherwise stretch (or shrink) everything
  242. if (Math.abs(WW - Wt) > .01) {
  243. if (f && WW > Wt) {
  244. WW = (WW - Wt) / f; for (i = 0, m = F.length; i < m; i++) {W[F[i]] += WW}
  245. } else {WW = WW/Wt; for (j = 0; j <= J; j++) {W[j] *= WW}}
  246. }
  247. //
  248. // Handle equal columns
  249. //
  250. if (values.equalcolumns) {
  251. var Wm = Math.max.apply(Math,W);
  252. for (j = 0; j <= J; j++) {W[j] = Wm}
  253. }
  254. }
  255. }
  256. //
  257. // Lay out array columns
  258. //
  259. var y = Y, dy, line, align; s = (C[LABEL] ? LABEL : 0);
  260. for (j = s; j <= J; j++) {
  261. for (i = 0, m = A.length; i < m; i++) {
  262. if (A[i][j]) {
  263. s = (this.data[i].type === "mlabeledtr" ? LABEL : 0);
  264. cell = this.data[i].data[j-s];
  265. if (cell.HTMLcanStretch("Horizontal")) {
  266. A[i][j].bbox = cell.HTMLstretchH(C[j],W[j]).bbox;
  267. } else if (cell.HTMLcanStretch("Vertical")) {
  268. mo = cell.CoreMO();
  269. var symmetric = mo.symmetric; mo.symmetric = false;
  270. A[i][j].bbox = cell.HTMLstretchV(C[j],H[i],D[i]).bbox; A[i][j].HH = null;
  271. if (A[i][j].bbox.h > H[i]) {A[i][j].bbox.H = A[i][j].bbox.h; A[i][j].bbox.h = H[i]}
  272. if (A[i][j].bbox.d > D[i]) {A[i][j].bbox.D = A[i][j].bbox.d; A[i][j].bbox.d = D[i]}
  273. mo.symmetric = symmetric;
  274. }
  275. align = cell.rowalign||this.data[i].rowalign||RALIGN[i];
  276. dy = ({top: H[i] - A[i][j].bbox.h,
  277. bottom: A[i][j].bbox.d - D[i],
  278. center: ((H[i]-D[i]) - (A[i][j].bbox.h-A[i][j].bbox.d))/2,
  279. baseline: 0, axis: 0})[align] || 0; // FIXME: handle axis better?
  280. align = (cell.columnalign||RCALIGN[i][j]||CALIGN[j]);
  281. HTMLCSS.alignBox(A[i][j],align,y+dy);
  282. }
  283. if (i < A.length-1) {y -= Math.max(0,D[i]+H[i+1]+RSPACE[i])}
  284. }
  285. y = Y;
  286. }
  287. //
  288. // Set column widths and placement
  289. //
  290. if (hasRelativeWidth) {
  291. //
  292. // Remove column spacing to get width available for columns
  293. //
  294. var box = HTMLCSS.createBox(stack); box.style.left = box.style.top = 0;
  295. box.style.right = HTMLCSS.Em(WW+2*fx); box.style.display = "inline-block";
  296. box.style.height = "0px";
  297. if (HTMLCSS.msieRelativeWidthBug) {
  298. box = HTMLCSS.createBox(box); box.style.position = "relative";
  299. box.style.height = "1em"; box.style.width = "100%"; box.bbox = stack.bbox;
  300. }
  301. //
  302. // wp = remaining width (%) divided by the number of columns it is split over
  303. // wm = remaining width (fixed) divided by the number of columns it is split over
  304. //
  305. var xp = 0, xf = fx, wp, wm;
  306. if (f) {wp = 100*(1-WP)/f, wm = Wt/f} else {wp = 100*(1-WP)/(J+1); wm = Wt/(J+1)}
  307. for (j = 0; j <= J; j++) {
  308. HTMLCSS.placeBox(C[j].parentNode,0,0); // sets the bbox
  309. //
  310. // Convert original column to the innermost span in the mobile column
  311. //
  312. C[j].style.position = "relative";
  313. C[j].style.left = HTMLCSS.Em(xf);
  314. C[j].style.width = "100%";
  315. C[j].parentNode.parentNode.removeChild(C[j].parentNode);
  316. var Cj = HTMLCSS.createBox(box); HTMLCSS.addBox(Cj,C[j]); C[j] = Cj;
  317. var CjStyle = Cj.style; CjStyle.display = "inline-block"; CjStyle.left = xp + "%";
  318. //
  319. // Set width/position based on the type of column
  320. //
  321. if (CWIDTH[j].match(/%$/)) {
  322. var pp = parseFloat(CWIDTH[j]) * Wf;
  323. if (f === 0) {
  324. CjStyle.width = (wp + pp) + "%"; xp += wp + pp;
  325. Cj = HTMLCSS.createBox(Cj); HTMLCSS.addBox(Cj,C[j].firstChild);
  326. Cj.style.left = 0; Cj.style.right = HTMLCSS.Em(wm); xf -= wm;
  327. } else {
  328. CjStyle.width = pp + "%"; xp += pp;
  329. }
  330. } else if (CWIDTH[j] === "fit" || f === 0) {
  331. CjStyle.width = wp + "%";
  332. Cj = HTMLCSS.createBox(Cj); HTMLCSS.addBox(Cj,C[j].firstChild);
  333. Cj.style.left = 0; Cj.style.right = HTMLCSS.Em(wm-W[j]);
  334. xf += W[j] - wm; xp += wp;
  335. } else {
  336. CjStyle.width = HTMLCSS.Em(W[j]); xf += W[j];
  337. }
  338. if (HTMLCSS.msieRelativeWidthBug) {
  339. HTMLCSS.addText(Cj.firstChild,HTMLCSS.NBSP); // gets correct baseline
  340. Cj.firstChild.style.position = "relative";
  341. }
  342. xf += CSPACE[j];
  343. //
  344. // Add column lines
  345. //
  346. if (CLINES[j] !== "none" && j < J && j !== LABEL) {
  347. line = HTMLCSS.createBox(box); line.style.left = xp+"%";
  348. line = HTMLCSS.createRule(line,fH,0,1.25/HTMLCSS.em); line.style.position = "absolute";
  349. line.bbox = {h:fH, d:0, w:0, rw:1.25/HTMLCSS.em, lw:0};
  350. line.parentNode.bbox = stack.bbox; // make sure stack size is updated
  351. HTMLCSS.placeBox(line,xf-CSPACE[j]/2,fY,true); line.style.borderStyle = CLINES[j];
  352. }
  353. }
  354. } else {
  355. //
  356. // Set the column box widths and place them
  357. //
  358. var x = fx;
  359. for (j = 0; j <= J; j++) {
  360. if (!C[j].bbox.width) {HTMLCSS.setStackWidth(C[j],W[j])}
  361. if (CWIDTH[j] !== "auto" && CWIDTH[j] !== "fit")
  362. {C[j].bbox.width = W[j]; C[j].bbox.isFixed = true}
  363. HTMLCSS.placeBox(C[j].parentNode,x,0); x += W[j] + CSPACE[j];
  364. //
  365. // Add column lines
  366. //
  367. if (CLINES[j] !== "none" && j < J && j !== LABEL) {
  368. line = HTMLCSS.createRule(stack,fH,0,1.25/HTMLCSS.em); HTMLCSS.addBox(stack,line);
  369. line.bbox = {h:fH, d:0, w:0, rw:1.25/HTMLCSS.em, lw:0};
  370. HTMLCSS.placeBox(line,x-CSPACE[j]/2,fY,true); line.style.borderStyle = CLINES[j];
  371. }
  372. }
  373. }
  374. stack.bbox.d = -fY; stack.bbox.h = fH+fY;
  375. HTMLCSS.setStackWidth(stack,stack.bbox.w + fx);
  376. //
  377. // Add frame
  378. //
  379. fW = stack.bbox.w; var frame;
  380. if (values.frame !== "none") {
  381. frame = HTMLCSS.createFrame(stack,fH,0,fW,1.25/HTMLCSS.em,values.frame);
  382. HTMLCSS.addBox(stack,frame); HTMLCSS.placeBox(frame,0,fY,true);
  383. if (hasRelativeWidth) {frame.style.width = "100%"}
  384. }
  385. //
  386. // Add row lines
  387. //
  388. y = Y;
  389. for (i = 0, m = A.length-1; i < m; i++) {
  390. dy = Math.max(0,D[i]+H[i+1]+RSPACE[i]);
  391. if (RLINES[i] !== MML.LINES.NONE && RLINES[i] !== "") {
  392. line = HTMLCSS.createRule(stack,1.25/HTMLCSS.em,0,fW); HTMLCSS.addBox(stack,line);
  393. line.bbox = {h:1.25/HTMLCSS.em, d:0, w:fW, rw:fW, lw:0};
  394. HTMLCSS.placeBox(line,0,y - D[i] - (dy-D[i]-H[i+1])/2,true);
  395. if (RLINES[i] === MML.LINES.DASHED) line.style.borderTopStyle = "dashed";
  396. if (hasRelativeWidth) line.style.width = "100%"
  397. }
  398. y -= dy;
  399. }
  400. //
  401. // Set relative width
  402. //
  403. if (hasRelativeWidth) {span.bbox.width = values.width; stack.style.width = "100%"}
  404. //
  405. // Place the labels, if any
  406. //
  407. if (C[LABEL]) {
  408. var mw = stack.bbox.w;
  409. var indent = this.getValues("indentalignfirst","indentshiftfirst","indentalign","indentshift");
  410. if (indent.indentalignfirst !== MML.INDENTALIGN.INDENTALIGN) {indent.indentalign = indent.indentalignfirst}
  411. if (indent.indentalign === MML.INDENTALIGN.AUTO) {indent.indentalign = this.displayAlign}
  412. if (indent.indentshiftfirst !== MML.INDENTSHIFT.INDENTSHIFT) {indent.indentshift = indent.indentshiftfirst}
  413. if (indent.indentshift === "auto") {indent.indentshift = "0"}
  414. var shift = HTMLCSS.length2em(indent.indentshift,mu,HTMLCSS.cwidth);
  415. var labelspace = HTMLCSS.length2em(values.minlabelspacing,mu,HTMLCSS.cwidth);
  416. var labelW = labelspace + C[LABEL].bbox.w, labelshift = 0, tw = mw;
  417. var dIndent = HTMLCSS.length2em(this.displayIndent,mu,HTMLCSS.cwidth);
  418. s = (CALIGN[LABEL] === MML.INDENTALIGN.RIGHT ? -1 : 1);
  419. if (indent.indentalign === MML.INDENTALIGN.CENTER) {
  420. tw += 2 * (labelW - s*(shift + dIndent));
  421. shift += dIndent;
  422. } else if (CALIGN[LABEL] === indent.indentalign) {
  423. if (dIndent < 0) {labelshift = s*dIndent; dIndent = 0}
  424. shift += s*dIndent; if (labelW > s*shift) shift = s*labelW; shift += labelshift;
  425. tw += s*shift;
  426. } else {
  427. tw += labelW - s*shift + dIndent;
  428. shift -= s*dIndent;
  429. }
  430. var eqn = HTMLCSS.createStack(span,false,"100%");
  431. HTMLCSS.addBox(eqn,stack); HTMLCSS.alignBox(stack,indent.indentalign,0,shift);
  432. C[LABEL].parentNode.parentNode.removeChild(C[LABEL].parentNode);
  433. HTMLCSS.addBox(eqn,C[LABEL]); HTMLCSS.alignBox(C[LABEL],CALIGN[LABEL],0);
  434. if (HTMLCSS.msieRelativeWidthBug) {stack.style.top = C[LABEL].style.top = ""}
  435. if (hasRelativeWidth) {stack.style.width = values.width; span.bbox.width = "100%"}
  436. C[LABEL].style[s === 1 ? "marginLeft" : "marginRight"] = HTMLCSS.Em(s*labelshift);
  437. span.bbox.tw = tw;
  438. span.style.minWidth = span.bbox.minWidth = HTMLCSS.Em(tw);
  439. eqn.style.minWidth = eqn.bbox.minWidth = HTMLCSS.Em(tw/scale);
  440. }
  441. //
  442. // Finish the table
  443. //
  444. if (!hasRelativeWidth) {this.HTMLhandleSpace(span)}
  445. var color = this.HTMLhandleColor(span);
  446. //
  447. // Handle relative-sized background color
  448. //
  449. if (color && hasRelativeWidth) {
  450. if (!frame) {
  451. frame = HTMLCSS.createFrame(stack,fH,0,fW,0,"none");
  452. HTMLCSS.addBox(stack,frame); HTMLCSS.placeBox(frame,0,fY,true);
  453. frame.style.width = "100%";
  454. }
  455. frame.style.backgroundColor = color.style.backgroundColor;
  456. frame.parentNode.insertBefore(frame,frame.parentNode.firstChild);
  457. color.parentNode.removeChild(color);
  458. }
  459. return span;
  460. },
  461. HTMLhandleSpace: function (span) {
  462. span.bbox.keepPadding = true; span.bbox.exact = true;
  463. if (!this.hasFrame && span.bbox.width == null)
  464. {span.style.paddingLeft = span.style.paddingRight = HTMLCSS.Em(1/6)}
  465. this.SUPER(arguments).HTMLhandleSpace.call(this,span);
  466. }
  467. });
  468. MML.mtd.Augment({
  469. toHTML: function (span,HW,D) {
  470. span = this.HTMLcreateSpan(span);
  471. if (this.data[0]) {
  472. var box = this.data[0].toHTML(span);
  473. if (D != null) {box = this.data[0].HTMLstretchV(span,HW,D)}
  474. else if (HW != null) {box = this.data[0].HTMLstretchH(span,HW)}
  475. span.bbox = box.bbox;
  476. }
  477. this.HTMLhandleSpace(span);
  478. this.HTMLhandleColor(span);
  479. return span;
  480. },
  481. HTMLstretchH: MML.mbase.HTMLstretchH,
  482. HTMLstretchV: MML.mbase.HTMLstretchV
  483. });
  484. MathJax.Hub.Startup.signal.Post("HTML-CSS mtable Ready");
  485. MathJax.Ajax.loadComplete(HTMLCSS.autoloadDir+"/mtable.js");
  486. });