mtable.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  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/CommonHTML/autoload/mtable.js
  6. *
  7. * Implements the CommonHTML output for <mtable> elements.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2015-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("CommonHTML Jax Ready",function () {
  26. var VERSION = "2.7.2";
  27. var MML = MathJax.ElementJax.mml,
  28. CONFIG = MathJax.Hub.config,
  29. CHTML = MathJax.OutputJax.CommonHTML,
  30. SPLIT = MathJax.Hub.SplitList;
  31. var LABEL = -1,
  32. BIGDIMEN = 1000000;
  33. MML.mtable.Augment({
  34. toCommonHTML: function (node) {
  35. //
  36. // Create the table nodes and put them in a table
  37. // (so that its bottom is on the baseline, rather than aligned on the top row)
  38. //
  39. var state = {rows:[], labels:[], labeled: false};
  40. node = this.CHTMLdefaultNode(node,{noBBox:true, childOptions:state});
  41. var table = CHTML.Element("mjx-table");
  42. while (node.firstChild) table.appendChild(node.firstChild);
  43. node.appendChild(table);
  44. //
  45. // Get the table attributes
  46. //
  47. var values = this.getValues("columnalign","rowalign","columnspacing","rowspacing",
  48. "columnwidth","equalcolumns","equalrows",
  49. "columnlines","rowlines","frame","framespacing",
  50. "align","width","side","minlabelspacing","useHeight");
  51. var t = CHTML.TEX.min_rule_thickness/CHTML.em;
  52. state.t = CHTML.Px(t*this.CHTML.scale,1);
  53. //
  54. // Create the table
  55. //
  56. this.CHTMLgetBoxSizes(values,state);
  57. this.CHTMLgetAttributes(values,state);
  58. this.CHTMLadjustCells(values,state);
  59. if (values.frame) table.style.border = state.t+" "+values.frame;
  60. this.CHTMLalignV(values,state,node);
  61. this.CHTMLcolumnWidths(values,state,node);
  62. this.CHTMLstretchCells(values,state);
  63. if (state.labeled) this.CHTMLaddLabels(values,state,node,table);
  64. //
  65. // Set the bounding box (ignores overlapping outside of the table)
  66. //
  67. var BBOX = this.CHTML;
  68. BBOX.w = BBOX.r = state.R;
  69. BBOX.h = BBOX.t = state.T-state.B;
  70. BBOX.d = BBOX.b = state.B;
  71. if (!values.frame && !BBOX.pwidth) {
  72. node.style.padding = "0 "+CHTML.Em(1/6);
  73. BBOX.L = BBOX.R = 1/6;
  74. }
  75. //
  76. // Add any needed space and color
  77. //
  78. this.CHTMLhandleSpace(node);
  79. this.CHTMLhandleBBox(node);
  80. this.CHTMLhandleColor(node);
  81. //
  82. // Return the completed node
  83. //
  84. return node;
  85. },
  86. //
  87. // Get the natural height, depth, and widths of the rows and columns
  88. //
  89. CHTMLgetBoxSizes: function (values,state) {
  90. var LH = CHTML.FONTDATA.lineH * values.useHeight,
  91. LD = CHTML.FONTDATA.lineD * values.useHeight;
  92. var H = [], D = [], W = [], J = -1, i, m;
  93. for (i = 0, m = this.data.length; i < m; i++) {
  94. var row = this.data[i], s = (row.type === "mtr" ? 0 : LABEL);
  95. H[i] = LH; D[i] = LD;
  96. for (var j = s, M = row.data.length + s; j < M; j++) {
  97. if (W[j] == null) {W[j] = -BIGDIMEN; if (j > J) J = j}
  98. var cbox = row.data[j-s].CHTML;
  99. if (cbox.h > H[i]) H[i] = cbox.h;
  100. if (cbox.d > D[i]) D[i] = cbox.d;
  101. if (cbox.w > W[j]) W[j] = cbox.w;
  102. }
  103. }
  104. if (values.equalrows) {
  105. state.HD = true;
  106. var HH = Math.max.apply(Math,H);
  107. var DD = Math.max.apply(Math,D);
  108. for (i = 0, m = H.length; i < m; i++) {H[i] = HH; D[i] = DD}
  109. }
  110. state.H = H; state.D = D; state.W = W, state.J = J;
  111. },
  112. //
  113. // Pad the spacing and alignment attributes to match the size of the table
  114. //
  115. CHTMLgetAttributes: function (values,state) {
  116. var CSPACE = SPLIT(values.columnspacing),
  117. RSPACE = SPLIT(values.rowspacing),
  118. CALIGN = SPLIT(values.columnalign),
  119. RALIGN = SPLIT(values.rowalign),
  120. CLINES = SPLIT(values.columnlines),
  121. RLINES = SPLIT(values.rowlines),
  122. CWIDTH = SPLIT(values.columnwidth),
  123. RCALIGN = [], i, m, J = state.J, M = state.rows.length-1;
  124. for (i = 0, m = CSPACE.length; i < m; i++) CSPACE[i] = this.CHTMLlength2em(CSPACE[i]);
  125. for (i = 0, m = RSPACE.length; i < m; i++) RSPACE[i] = this.CHTMLlength2em(RSPACE[i]);
  126. while (CSPACE.length < J) CSPACE.push(CSPACE[CSPACE.length-1]);
  127. while (CALIGN.length <= J) CALIGN.push(CALIGN[CALIGN.length-1]);
  128. while (CLINES.length < J) CLINES.push(CLINES[CLINES.length-1]);
  129. while (CWIDTH.length <= J) CWIDTH.push(CWIDTH[CWIDTH.length-1]);
  130. while (RSPACE.length < M) RSPACE.push(RSPACE[RSPACE.length-1]);
  131. while (RALIGN.length <= M) RALIGN.push(RALIGN[RALIGN.length-1]);
  132. while (RLINES.length < M) RLINES.push(RLINES[RLINES.length-1]);
  133. CALIGN[LABEL] = (values.side.substr(0,1) === "l" ? "left" : "right");
  134. //
  135. // Override aligment data based on row-specific attributes
  136. //
  137. for (i = 0; i <= M; i++) {
  138. var row = this.data[i]; RCALIGN[i] = [];
  139. if (row.rowalign) RALIGN[i] = row.rowalign;
  140. if (row.columnalign) {
  141. RCALIGN[i] = SPLIT(row.columnalign);
  142. while (RCALIGN[i].length <= J) RCALIGN[i].push(RCALIGN[i][RCALIGN[i].length-1]);
  143. }
  144. }
  145. //
  146. // Handle framespacing
  147. //
  148. var FSPACE = SPLIT(values.framespacing);
  149. if (FSPACE.length != 2) FSPACE = SPLIT(this.defaults.framespacing);
  150. FSPACE[0] = Math.max(0,this.CHTMLlength2em(FSPACE[0]));
  151. FSPACE[1] = Math.max(0,this.CHTMLlength2em(FSPACE[1]));
  152. if (values.columnlines.replace(/none/g,"").replace(/ /g,"") !== "" ||
  153. values.rowlines.replace(/none/g,"").replace(/ /g,"") !== "") values.fspace = true;
  154. //
  155. // Pad arrays so that final column can be treated as all the others
  156. //
  157. if (values.frame === MML.LINES.NONE) delete values.frame; else values.fspace = true;
  158. if (values.frame) {
  159. FSPACE[0] = Math.max(0,FSPACE[0]);
  160. FSPACE[1] = Math.max(0,FSPACE[1]);
  161. }
  162. if (values.fspace) {
  163. CSPACE[J] = FSPACE[0]; RSPACE[M] = FSPACE[1];
  164. } else {
  165. CSPACE[J] = RSPACE[M] = 0;
  166. }
  167. CLINES[J] = RLINES[M] = MML.LINES.NONE;
  168. //
  169. // Save everything in the state
  170. //
  171. state.CSPACE = CSPACE; state.RSPACE = RSPACE;
  172. state.CALIGN = CALIGN; state.RALIGN = RALIGN;
  173. state.CLINES = CLINES; state.RLINES = RLINES;
  174. state.CWIDTH = CWIDTH; state.RCALIGN = RCALIGN;
  175. state.FSPACE = FSPACE;
  176. },
  177. //
  178. // Add styles to cells to handle borders, spacing, alignment, etc.
  179. //
  180. CHTMLadjustCells: function(values,state) {
  181. var ROWS = state.rows,
  182. CSPACE = state.CSPACE, CLINES = state.CLINES,
  183. RSPACE = state.RSPACE, RLINES = state.RLINES,
  184. CALIGN = state.CALIGN, RALIGN = state.RALIGN,
  185. RCALIGN = state.RCALIGN;
  186. CSPACE[state.J] *= 2; RSPACE[ROWS.length-1] *= 2; // since halved below
  187. var T = "0", B, R, L, border, cbox, align, lastB = 0;
  188. if (values.fspace) {
  189. lastB = state.FSPACE[1];
  190. T = CHTML.Em(state.FSPACE[1]);
  191. }
  192. state.RHD = []; state.RH = [];
  193. for (var i = 0, m = ROWS.length; i < m; i++) {
  194. var row = ROWS[i], rdata = this.data[i];
  195. //
  196. // Space and borders between rows
  197. //
  198. B = RSPACE[i]/2; border = null; L = "0";
  199. if (RLINES[i] !== MML.LINES.NONE && RLINES[i] !== "") border = state.t+" "+RLINES[i];
  200. if (border || (CLINES[j] !== MML.LINES.NONE && CLINES[j] !== "")) {
  201. while (row.length <= state.J) {
  202. row.push(CHTML.addElement(row.node,"mjx-mtd",null,[['span']]));
  203. }
  204. }
  205. state.RH[i] = lastB + state.H[i]; // distance to baseline in row
  206. lastB = Math.max(0,B);
  207. state.RHD[i] = state.RH[i] + lastB + state.D[i]; // total height of row
  208. B = CHTML.Em(lastB);
  209. //
  210. // Frame space for initial cell
  211. //
  212. if (values.fspace) L = CHTML.Em(state.FSPACE[0]);
  213. //
  214. // The cells in the row
  215. //
  216. for (var j = 0, M = row.length; j < M; j++) {
  217. var s = (rdata.type === "mtr" ? 0 : LABEL);
  218. var mtd = rdata.data[j-s] || {CHTML: CHTML.BBOX.zero()};
  219. var cell = row[j].style; cbox = mtd.CHTML;
  220. //
  221. // Space and borders between columns
  222. //
  223. R = CSPACE[j]/2;
  224. if (CLINES[j] !== MML.LINES.NONE) {
  225. cell.borderRight = state.t+" "+CLINES[j];
  226. R -= 1/CHTML.em/2;
  227. }
  228. R = CHTML.Em(Math.max(0,R));
  229. cell.padding = T+" "+R+" 0px "+L;
  230. if (border) cell.borderBottom = border;
  231. L = R;
  232. //
  233. // Handle vertical alignment
  234. //
  235. align = (mtd.rowalign||(this.data[i]||{}).rowalign||RALIGN[i]);
  236. var H = Math.max(1,cbox.h), D = Math.max(.2,cbox.d),
  237. HD = (state.H[i]+state.D[i]) - (H+D),
  238. child = row[j].firstChild.style;
  239. if (align === MML.ALIGN.TOP) {
  240. if (HD) child.marginBottom = CHTML.Em(HD);
  241. cell.verticalAlign = "top";
  242. } else if (align === MML.ALIGN.BOTTOM) {
  243. cell.verticalAlign = "bottom";
  244. if (HD) child.marginTop = CHTML.Em(HD);
  245. } else if (align === MML.ALIGN.CENTER) {
  246. if (HD) child.marginTop = child.marginBottom = CHTML.Em(HD/2);
  247. cell.verticalAlign = "middle";
  248. } else {
  249. if (H !== state.H[i]) child.marginTop = CHTML.Em(state.H[i]-H);
  250. }
  251. //
  252. // Handle horizontal alignment
  253. //
  254. align = (mtd.columnalign||RCALIGN[i][j]||CALIGN[j]);
  255. if (align !== MML.ALIGN.CENTER) cell.textAlign = align;
  256. }
  257. row.node.style.height = CHTML.Em(state.RHD[i]);
  258. T = B;
  259. }
  260. CSPACE[state.J] /= 2; RSPACE[ROWS.length-1] /= 2; // back to normal
  261. },
  262. //
  263. // Align the table vertically according to the align attribute
  264. //
  265. CHTMLalignV: function (values,state,node) {
  266. var n, M = state.rows.length, H = state.H, D = state.D, RSPACE = state.RSPACE;
  267. //
  268. // Get alignment type and row number
  269. //
  270. if (typeof(values.align) !== "string") values.align = String(values.align);
  271. if (values.align.match(/(top|bottom|center|baseline|axis)( +(-?\d+))?/)) {
  272. n = parseInt(RegExp.$3||"0");
  273. values.align = RegExp.$1
  274. if (n < 0) n += state.rows.length + 1;
  275. if (n > M || n <= 0) n = null;
  276. } else {
  277. values.align = this.defaults.align;
  278. }
  279. //
  280. // Get table height and baseline offset
  281. //
  282. var T = 0, B = 0, a = CHTML.TEX.axis_height;
  283. if (values.fspace) T += state.FSPACE[1];
  284. if (values.frame) {T += 2/CHTML.em; B += 1/CHTML.em}
  285. for (var i = 0; i < M; i++) {
  286. var h = H[i], d = D[i];
  287. T += h + d + RSPACE[i];
  288. if (n) {
  289. if (i === n-1) {
  290. B += ({top:h+d, bottom:0, center:(h+d)/2,
  291. baseline:d, axis:a+d})[values.align] + RSPACE[i];
  292. }
  293. if (i >= n) B += h + d + RSPACE[i];
  294. }
  295. }
  296. if (!n) B = ({top:T, bottom:0, center:T/2, baseline:T/2, axis:T/2-a})[values.align];
  297. //
  298. // Place the node and save the values
  299. //
  300. if (B) node.style.verticalAlign = CHTML.Em(-B);
  301. state.T = T; state.B = B;
  302. },
  303. //
  304. // Determine column widths and set the styles for the columns
  305. //
  306. CHTMLcolumnWidths: function (values,state,node) {
  307. var CWIDTH = state.CWIDTH, CSPACE = state.CSPACE, J = state.J, j;
  308. var WW = 0, setWidths = false, relWidth = values.width.match(/%$/);
  309. var i, m, w;
  310. //
  311. // Handle equal columns by adjusting the CWIDTH array
  312. //
  313. if (values.width !== "auto" && !relWidth) {
  314. WW = Math.max(0,this.CHTMLlength2em(values.width,state.R));
  315. setWidths = true;
  316. }
  317. if (values.equalcolumns) {
  318. if (relWidth) {
  319. //
  320. // Use percent of total (not perfect, but best we can do)
  321. //
  322. var p = CHTML.Percent(1/(J+1));
  323. for (j = 0; j <= J; j++) CWIDTH[j] = p;
  324. } else {
  325. //
  326. // For width = auto, make all widths equal the widest,
  327. // otherwise, for specific width, remove intercolumn space
  328. // and divide by number of columns to get widest space.
  329. //
  330. w = Math.max.apply(Math,state.W);
  331. if (values.width !== "auto") {
  332. var S = (values.fspace ? state.FSPACE[0] + (values.frame ? 2/CHTML.em : 0) : 0);
  333. for (j = 0; j <= J; j++) S += CSPACE[j];
  334. w = Math.max((WW-S)/(J+1),w);
  335. }
  336. w = CHTML.Em(w);
  337. for (j = 0; j <= J; j++) CWIDTH[j] = w;
  338. }
  339. setWidths = true;
  340. }
  341. //
  342. // Compute natural table width
  343. //
  344. var TW = 0; if (values.fspace) TW = state.FSPACE[0];
  345. var auto = [], fit = [], percent = [], W = [];
  346. var row = state.rows[0];
  347. for (j = 0; j <= J; j++) {
  348. W[j] = state.W[j];
  349. if (CWIDTH[j] === "auto") auto.push(j)
  350. else if (CWIDTH[j] === "fit") fit.push(j)
  351. else if (CWIDTH[j].match(/%$/)) percent.push(j)
  352. else W[j] = this.CHTMLlength2em(CWIDTH[j],W[j]);
  353. TW += W[j] + CSPACE[j];
  354. if (row[j]) row[j].style.width = CHTML.Em(W[j]);
  355. }
  356. if (values.frame) TW += 2/CHTML.em;
  357. var hasFit = (fit.length > 0);
  358. //
  359. // Adjust widths of columns
  360. //
  361. if (setWidths) {
  362. if (relWidth) {
  363. //
  364. // Attach appropriate widths to the columns
  365. //
  366. for (j = 0; j <= J; j++) {
  367. cell = row[j].style;
  368. if (CWIDTH[j] === "auto" && !hasFit) cell.width = "";
  369. else if (CWIDTH[j] === "fit") cell.width = "";
  370. else if (CWIDTH[j].match(/%$/)) cell.width = CWIDTH[j];
  371. else cell.minWidth = cell.maxWidth = cell.width;
  372. }
  373. } else {
  374. //
  375. // Compute percentage widths
  376. //
  377. if (WW > TW) {
  378. var extra = 0;
  379. for (i = 0, m = percent.length; i < m; i++) {
  380. j = percent[i];
  381. w = Math.max(W[j],this.CHTMLlength2em(CWIDTH[j],WW));
  382. extra += w-W[j]; W[j] = w;
  383. row[j].style.width = CHTML.Em(w);
  384. }
  385. TW += extra;
  386. }
  387. //
  388. // Compute "fit" widths
  389. //
  390. if (!hasFit) fit = auto;
  391. if (WW > TW && fit.length) {
  392. var dw = (WW - TW) / fit.length;
  393. for (i = 0, m = fit.length; i < m; i++) {
  394. j = fit[i]; W[j] += dw;
  395. row[j].style.width = CHTML.Em(W[j]);
  396. }
  397. TW = WW;
  398. }
  399. }
  400. }
  401. W[LABEL] = state.W[LABEL];
  402. state.W = W;
  403. state.R = TW;
  404. //
  405. // Set variable width on DOM nodes
  406. //
  407. if (relWidth) {
  408. this.CHTML.pwidth = values.width; this.CHTML.mwidth = CHTML.Em(TW);
  409. node.style.width = node.firstChild.style.width = "100%";
  410. }
  411. },
  412. //
  413. // Stretch any cells that can be stretched
  414. //
  415. CHTMLstretchCells: function (values,state) {
  416. var ROWS = state.rows, H = state.H, D = state.D, W = state.W,
  417. J = state.J, M = ROWS.length-1;
  418. for (var i = 0; i <= M; i++) {
  419. var row = ROWS[i], rdata = this.data[i];
  420. var h = H[i], d = D[i];
  421. for (var j = 0; j <= J; j++) {
  422. var cell = row[j], cdata = rdata.data[j];
  423. if (!cdata) continue;
  424. if (cdata.CHTML.stretch === "V") cdata.CHTMLstretchV(h,d);
  425. else if (cdata.CHTML.stretch === "H") cdata.CHTMLstretchH(cell,W[j]);
  426. }
  427. }
  428. },
  429. //
  430. // Add labels to a table
  431. //
  432. CHTMLaddLabels: function (values,state,node,table) {
  433. //
  434. // Get indentation and alignment
  435. //
  436. var indent = this.getValues("indentalignfirst","indentshiftfirst","indentalign","indentshift");
  437. if (indent.indentalignfirst !== MML.INDENTALIGN.INDENTALIGN) indent.indentalign = indent.indentalignfirst;
  438. if (indent.indentalign === MML.INDENTALIGN.AUTO) indent.indentalign = CONFIG.displayAlign;
  439. if (indent.indentshiftfirst !== MML.INDENTSHIFT.INDENTSHIFT) indent.indentshift = indent.indentshiftfirst;
  440. if (indent.indentshift === "auto") indent.indentshift = "0";
  441. var shift = this.CHTMLlength2em(indent.indentshift,CHTML.cwidth);
  442. var labelspace = this.CHTMLlength2em(values.minlabelspacing,.8);
  443. var labelW = labelspace + state.W[LABEL], labelshift = 0, tw = state.R;
  444. var dIndent = this.CHTMLlength2em(CONFIG.displayIndent,CHTML.cwidth);
  445. var s = (state.CALIGN[LABEL] === MML.INDENTALIGN.RIGHT ? -1 : 1);
  446. if (indent.indentalign === MML.INDENTALIGN.CENTER) {
  447. tw += 2 * (labelW - s*(shift + dIndent));
  448. shift += dIndent;
  449. } else if (state.CALIGN[LABEL] === indent.indentalign) {
  450. if (dIndent < 0) {labelshift = s*dIndent; dIndent = 0}
  451. shift += s*dIndent; if (labelW > s*shift) shift = s*labelW; shift += labelshift;
  452. shift *= s; tw += shift;
  453. } else {
  454. tw += labelW - s*shift + dIndent;
  455. shift -= s*dIndent; shift *= -s;
  456. }
  457. //
  458. // Create boxes for table and labels
  459. //
  460. var box = CHTML.addElement(node,"mjx-box",{
  461. style:{width:"100%","text-align":indent.indentalign}
  462. }); box.appendChild(table);
  463. var labels = CHTML.Element("mjx-itable");
  464. table.style.display = "inline-table"; if (!table.style.width) table.style.width = "auto";
  465. labels.style.verticalAlign = "top";
  466. table.style.verticalAlign = CHTML.Em(state.T-state.B-state.H[0]);
  467. node.style.verticalAlign = "";
  468. if (shift) {
  469. if (indent.indentalign === MML.INDENTALIGN.CENTER) {
  470. table.style.marginLeft = CHTML.Em(shift);
  471. table.style.marginRight = CHTML.Em(-shift);
  472. } else {
  473. var margin = "margin" + (indent.indentalign === MML.INDENTALIGN.RIGHT ? "Right" : "Left");
  474. table.style[margin] = CHTML.Em(shift);
  475. }
  476. }
  477. //
  478. // Add labels on correct side
  479. //
  480. if (state.CALIGN[LABEL] === "left") {
  481. node.insertBefore(labels,box);
  482. labels.style.marginRight = CHTML.Em(-state.W[LABEL]-labelshift);
  483. if (labelshift) labels.style.marginLeft = CHTML.Em(labelshift);
  484. } else {
  485. node.appendChild(labels);
  486. labels.style.marginLeft = CHTML.Em(-state.W[LABEL]+labelshift);
  487. }
  488. //
  489. // Vertically align the labels with their rows
  490. //
  491. var LABELS = state.labels, T = 0;
  492. if (values.fspace) T = state.FSPACE[0] + (values.frame ? 1/CHTML.em : 0);
  493. for (var i = 0, m = LABELS.length; i < m; i++) {
  494. if (LABELS[i] && this.data[i].data[0]) {
  495. labels.appendChild(LABELS[i]);
  496. var lbox = this.data[i].data[0].CHTML;
  497. T = state.RH[i] - Math.max(1,lbox.h);
  498. if (T) LABELS[i].firstChild.firstChild.style.marginTop = CHTML.Em(T);
  499. LABELS[i].style.height = CHTML.Em(state.RHD[i]);
  500. } else {
  501. CHTML.addElement(labels,"mjx-label",{style:{height:CHTML.Em(state.RHD[i])}});
  502. }
  503. }
  504. //
  505. // Propagate full-width equations, and reserve room for equation plus label
  506. //
  507. node.style.width = this.CHTML.pwidth = "100%";
  508. node.style.minWidth = this.CHTML.mwidth = CHTML.Em(Math.max(0,tw));
  509. }
  510. });
  511. MML.mtr.Augment({
  512. toCommonHTML: function (node,options) {
  513. //
  514. // Create the row node
  515. //
  516. node = this.CHTMLcreateNode(node);
  517. this.CHTMLhandleStyle(node);
  518. this.CHTMLhandleScale(node);
  519. //
  520. // Add a new row with no label
  521. //
  522. if (!options) options = {rows:[],labels:[]};
  523. var row = []; options.rows.push(row); row.node = node;
  524. options.labels.push(null);
  525. //
  526. // Add the cells to the row
  527. //
  528. for (var i = 0, m = this.data.length; i < m; i++)
  529. row.push(this.CHTMLaddChild(node,i,options));
  530. //
  531. this.CHTMLhandleColor(node);
  532. return node;
  533. }
  534. });
  535. MML.mlabeledtr.Augment({
  536. toCommonHTML: function (node,options) {
  537. //
  538. // Create the row node
  539. //
  540. node = this.CHTMLcreateNode(node);
  541. this.CHTMLhandleStyle(node);
  542. this.CHTMLhandleScale(node);
  543. //
  544. // Add a new row, and get the label
  545. //
  546. if (!options) options = {rows:[],labels:[]};
  547. var row = []; options.rows.push(row); row.node = node;
  548. var label = CHTML.Element("mjx-label"); options.labels.push(label);
  549. this.CHTMLaddChild(label,0,options);
  550. if (this.data[0]) options.labeled = true;
  551. //
  552. // Add the cells to the row
  553. //
  554. for (var i = 1, m = this.data.length; i < m; i++)
  555. row.push(this.CHTMLaddChild(node,i,options));
  556. //
  557. this.CHTMLhandleColor(node);
  558. return node;
  559. }
  560. });
  561. MML.mtd.Augment({
  562. toCommonHTML: function (node,options) {
  563. node = this.CHTMLdefaultNode(node,options);
  564. CHTML.addElement(node.firstChild,"mjx-strut"); // forces height to 1em (we adjust later)
  565. //
  566. // Determine if this is stretchy or not
  567. //
  568. if (this.isEmbellished()) {
  569. var mo = this.CoreMO(), BBOX = this.CHTML;
  570. if (mo.CHTMLcanStretch("Vertical")) BBOX.stretch = "V";
  571. else if (mo.CHTMLcanStretch("Horizontal")) BBOX.stretch = "H";
  572. if (BBOX.stretch) {
  573. var min = mo.Get("minsize",true);
  574. if (min) {
  575. if (BBOX.stretch === "V") {
  576. var HD = BBOX.h + BBOX.d;
  577. if (HD) {
  578. var r = this.CHTMLlength2em(min,HD)/HD;
  579. if (r > 1) {BBOX.h *= r; BBOX.d *= r}
  580. }
  581. } else {
  582. BBOX.w = Math.max(BBOX.w,this.CHTMLlength2em(min,BBOX.w));
  583. }
  584. }
  585. }
  586. }
  587. return node;
  588. }
  589. });
  590. MathJax.Hub.Startup.signal.Post("CommonHTML mtable Ready");
  591. MathJax.Ajax.loadComplete(CHTML.autoloadDir+"/mtable.js");
  592. });