www

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

mtable.js (21524B)


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