mtable.js 21 KB

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