commit 0891402b888237944e451de2c9e7e6307e3ebf31
parent 63c8bd4d838a88dd3cd3c848f04835c291b3e7bf
Author: Davide P. Cervone <dpvc@union.edu>
Date: Mon, 29 Apr 2013 15:57:29 -0400
Merge branch 'issue359' into develop. Improves MathML rendering for mfenced and mlabeldtr elements.
Diffstat:
6 files changed, 505 insertions(+), 48 deletions(-)
diff --git a/unpacked/extensions/TeX/AMSmath.js b/unpacked/extensions/TeX/AMSmath.js
@@ -1,3 +1,6 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
/*************************************************************
*
* MathJax/extensions/TeX/AMSmath.js
@@ -22,7 +25,7 @@
*/
MathJax.Extension["TeX/AMSmath"] = {
- version: "2.1",
+ version: "2.1.1",
number: 0, // current equation number
startNumber: 0, // current starting equation number (for when equation is restarted)
@@ -252,7 +255,7 @@ MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
var den = this.ParseArg(name);
var frac = MML.mfrac(num,den);
if (thick !== "") {frac.linethickness = thick}
- if (left || right) {frac = MML.mfenced(frac).With({open: left, close: right})}
+ if (left || right) {frac = TEX.mfenced(left,frac,right)}
if (style !== "") {
var STYLE = (["D","T","S","SS"])[style];
if (STYLE == null) {TEX.Error("Bad math style for "+name)}
diff --git a/unpacked/jax/input/MathML/config.js b/unpacked/jax/input/MathML/config.js
@@ -24,7 +24,7 @@
MathJax.InputJax.MathML = MathJax.InputJax({
id: "MathML",
- version: "2.1",
+ version: "2.1.1",
directory: MathJax.InputJax.directory + "/MathML",
extensionDir: MathJax.InputJax.extensionDir + "/MathML",
entityDir: MathJax.InputJax.directory + "/MathML/entities",
diff --git a/unpacked/jax/input/MathML/jax.js b/unpacked/jax/input/MathML/jax.js
@@ -1,5 +1,6 @@
/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
+
/*************************************************************
*
* MathJax/jax/input/MathML/jax.js
@@ -151,6 +152,14 @@
{mml.Append.apply(mml,cmml.data); cmml.data = []}
}
}
+ if (mml.type === "mrow" && mml.data.length >= 2) {
+ var first = mml.data[0], last = mml.data[mml.data.length-1];
+ if (first.type === "mo" && first.Get("fence") &&
+ last.type === "mo" && last.Get("fence")) {
+ if (first.data[0]) {mml.open = first.data.join("")}
+ if (last.data[0]) {mml.close = last.data.join("")}
+ }
+ }
},
//
diff --git a/unpacked/jax/input/TeX/jax.js b/unpacked/jax/input/TeX/jax.js
@@ -1,3 +1,6 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
/*************************************************************
*
* MathJax/jax/input/TeX/jax.js
@@ -175,7 +178,7 @@
if (this.open || this.close) {
mml.texClass = MML.TEXCLASS.INNER;
mml.texWithDelims = true;
- mml = MML.mfenced(mml).With({open: this.open, close: this.close});
+ mml = TEX.mfenced(this.open,mml,this.close);
}
return [STACKITEM.mml(mml), item];
}
@@ -188,10 +191,8 @@
type: "left", isOpen: true, delim: '(',
stopError: "Extra \\left or missing \\right",
checkItem: function (item) {
- if (item.type === "right") {
- var mml = MML.mfenced(this.data.length === 1 ? this.data[0] : MML.mrow.apply(MML,this.data));
- return STACKITEM.mml(mml.With({open: this.delim, close: item.delim}));
- }
+ if (item.type === "right")
+ {return STACKITEM.mml(TEX.mfenced(this.delim,this.mmlData(),item.delim))}
return this.SUPER(arguments).checkItem.call(this,item);
}
});
@@ -266,9 +267,7 @@
if ((this.arraydef.columnlines||"none") != "none" ||
(this.arraydef.rowlines||"none") != "none") {mml.padding = 0} // HTML-CSS jax implements this
}
- if (this.open || this.close) {
- mml = MML.mfenced(mml).With({open: this.open, close: this.close});
- }
+ if (this.open || this.close) {mml = TEX.mfenced(this.open,mml,this.close)}
mml = STACKITEM.mml(mml);
if (this.requireClose) {
if (item.type === 'close') {return mml}
@@ -1052,7 +1051,7 @@
return this.stack.Top().data[0];
},
mmlToken: function (token) {return token}, // used by boldsymbol extension
-
+
/************************************************************************/
/*
* Handle various token classes
@@ -2054,6 +2053,18 @@
TEXDEF.macros[name].isUser = true;
},
+ /*
+ * Create an mrow that represents the equivalent of an mfenced
+ */
+ mfenced: function (open,mml,close) {
+ var mrow = MML.mrow();
+ mrow.open = open; mrow.close = close;
+ if (open) {mrow.Append(MML.mo(open).With({fence:true, texClass:MML.TEXCLASS.OPEN}))}
+ if (mml.type === "mrow") {mrow.Append.apply(mrow,mml.data)} else {mrow.Append(mml)}
+ if (close) {mrow.Append(MML.mo(close).With({fence:true, texClass:MML.TEXCLASS.CLOSE}))}
+ return mrow;
+ },
+
//
// Combine adjacent <mo> elements that are relations
// (since MathML treats the spacing very differently)
diff --git a/unpacked/jax/output/NativeMML/config.js b/unpacked/jax/output/NativeMML/config.js
@@ -24,7 +24,7 @@
MathJax.OutputJax.NativeMML = MathJax.OutputJax({
id: "NativeMML",
- version: "2.1.1",
+ version: "2.1.2",
directory: MathJax.OutputJax.directory + "/NativeMML",
extensionDir: MathJax.OutputJax.extensionDir + "/NativeMML",
diff --git a/unpacked/jax/output/NativeMML/jax.js b/unpacked/jax/output/NativeMML/jax.js
@@ -1,3 +1,6 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
/*************************************************************
*
* MathJax/jax/output/NativeMML/jax.js
@@ -29,6 +32,54 @@
HUB.Register.StartupHook("MathZoom Ready",function () {ZOOM = MathJax.Extension.MathZoom});
+ var NOPADDING = function (side,obj) {
+ var span = HTML.Element("span"); side = "padding"+side;
+ if (obj) {
+ span.style.cssText = (obj.getAttribute("style")||"");
+ if (span.style.padding === "" && (span.style[side]||"") === "") {
+ span.style[side] = "0px"; obj.setAttribute("style",span.style.cssText)
+ }
+ }
+ };
+
+ var CELLSPACING = function (obj,rowSpacing,columnSpacing) {
+ //
+ // Webkit default padding on mtd cells is simply
+ //
+ // mtd {padding: 0.5ex;}
+ //
+ // Gecko default padding on mtd cells is
+ //
+ // mtd {padding-right: 0.4em;
+ // padding-left: 0.4em;
+ // padding-bottom: 0.5ex;
+ // padding-top: 0.5ex;}
+ // mtr:first-child > mtd {padding-top: 0ex;}
+ // mtr:last-child > mtd {padding-bottom: 0ex;}
+ // mtd:first-child {padding-left: 0em;}
+ // mtd:last-child {padding-right: 0em;}
+ //
+ // that is the columnspacing/rowspacing is split into two adjacent cells,
+ // and the periphery of boundary cells is set to zero.
+ //
+ // Here, we will set the left/top padding of each cell to
+ // rowSpacing/columnSpacing (or 0px for the leftmost/topmost cells) and
+ // reset the right/bottom padding to zero.
+ //
+ if (obj) {
+ var span = HTML.Element("span");
+ span.style.cssText = (obj.getAttribute("style")||"");
+ if (span.style.padding === "") {
+ var padding = { paddingLeft: columnSpacing, paddingTop: rowSpacing,
+ paddingRight: "0px", paddingBottom: "0px" };
+ for (var side in padding) {if (padding.hasOwnProperty(side)) {
+ if ((span.style[side]||"") === "") {span.style[side] = padding[side];}
+ }}
+ }
+ obj.setAttribute("style",span.style.cssText);
+ }
+ };
+
nMML.Augment({
//
// User can configure styles
@@ -80,7 +131,7 @@
if (HUB.config.displayAlign !== "center") {
var align = HUB.config.displayAlign, indent = HUB.config.displayIndent;
var def = {"text-align": align+"!important"}; def["margin-"+align] = indent+"!important";
- MathJax.Hub.Insert(this.config.styles,{
+ HUB.Insert(this.config.styles,{
"div.MathJax_MathML": def,
"div.MathJax_MathML math": {"text-align": align},
"div.MathJax_MathContainer > span": {"text-align": align+"!important"}
@@ -272,8 +323,10 @@
postTranslate: function (state) {
if (this.forceReflow) {
+ //
// Firefox messes up some mtable's when they are dynamically created
// but gets them right on a reflow, so force reflow by toggling a stylesheet
+ //
var sheet = (document.styleSheets||[])[0]||{};
sheet.disabled = true; sheet.disabled = false;
}
@@ -330,8 +383,10 @@
if (nMML[type] && nMML[type](event,this) === false) {return false}
if (ZOOM && ZOOM.HandleEvent(event,type,this) === false) {return false}
if (event.srcElement.className === "MathJax_MathPlayer_Overlay" && this.msieMath.fireEvent) {
- // for now, ignore all other events. This will disable MathPlayer's zoom
- // feature, but also its <maction> support.
+ //
+ // For now, ignore all other events. This will disable MathPlayer's zoom
+ // feature, but also its <maction> support.
+ //
if (type === "ContextMenu" || type === "Mouseover" || type === "Mouseout")
{this.msieMath.fireEvent("on"+event.type,event)}
}
@@ -470,7 +525,32 @@
if (this.data[i]) {this.data[i].toNativeMML(parent)}
else {parent.appendChild(this.NativeMMLelement("mrow"))}
}
- } else {
+ } else if (nMML.stretchyMoBug && (this.open || this.close)) {
+ //
+ // This element contains opening and/or closing fences. Opera is not
+ // able to stretch <mo> operators, so let's use an <mfenced> element
+ // instead.
+ //
+ var mfenced = this.NativeMMLelement("mfenced");
+ this.NativeMMLattributes(mfenced);
+ var i = 0, m = this.data.length;
+ if (this.open) { mfenced.setAttribute("open", this.open); i++; }
+ if (this.close) { mfenced.setAttribute("close", this.close); m--; }
+ var tag = mfenced;
+ if (m - i + 1 > 1) {
+ //
+ // If there are several children, put them in an <mrow>
+ //
+ tag = this.NativeMMLelement("mrow");
+ parent.appendChild(mfenced);
+ parent = mfenced;
+ }
+ for (; i < m; i++) {
+ if (this.data[i]) {this.data[i].toNativeMML(tag)}
+ else {tag.appendChild(this.NativeMMLelement("mrow"))}
+ }
+ parent.appendChild(tag);
+ } else {
this.SUPER(arguments).toNativeMML.call(this,parent);
}
}
@@ -512,39 +592,239 @@
}
});
- if (HUB.Browser.isFirefox) {
- if (!HUB.Browser.versionAtLeast("13.0")) {
- MML.mtable.Augment({
- toNativeMML: function (parent) {
+ if (!isMSIE) {
+ var SPLIT = MathJax.Hub.SplitList;
+ MML.mtable.Augment({
+ toNativeMML: function (parent) {
+ var i, m;
+ if (nMML.tableSpacingBug) {
+ //
+ // Parse the rowspacing/columnspacing. For convenience, we convert
+ // them to a left/top padding value that will be applied to each
+ // cell. The leftmost/topmost cells will use "0px".
+ //
+ var values = this.getValues("rowspacing", "columnspacing");
+ this.nMMLtopPadding = SPLIT("0px "+values.rowspacing);
+ this.nMMLleftPadding = SPLIT("0px "+values.columnspacing);
//
- // Firefox < 13 doesn't handle width, so put it in styles instead
+ // Transmit the top padding to each row.
+ // If this.parent.nMML.topPadding does not contain enough value,
+ // repeat the last one.
//
- if (this.width) {
- var styles = (this.style||"").replace(/;\s*$/,"").split(";");
- if (styles[0] === "") {styles.shift()}
- styles.push("width:"+this.width);
- this.style = styles.join(";");
+ var tp = this.nMMLtopPadding, M = tp.length;
+ for (i = 0, m = this.data.length; i < m; i++) {
+ if (this.data[i])
+ {this.data[i].nMMLtopPadding = tp[i < M ? i : M-1]}
}
- this.SUPER(arguments).toNativeMML.call(this,parent);
}
- });
- }
- if (!HUB.Browser.versionAtLeast("9.0")) {
- MML.mlabeledtr.Augment({
- toNativeMML: function (parent) {
+ if (nMML.tableLabelBug) {
//
- // FF doesn't handle mlabeledtr, so remove the label
+ // Look for labeled rows so we know how to handle them
//
- var tag = this.NativeMMLelement("mtr");
- this.NativeMMLattributes(tag);
- for (var i = 1, m = this.data.length; i < m; i++) {
- if (this.data[i]) {this.data[i].toNativeMML(tag)}
- else {tag.appendChild(this.NativeMMLelement("mrow"))}
+ for (i = 0, m = this.data.length; i < m; i++) {
+ if (this.data[i] && this.data[i].isa(MML.mlabeledtr)) {
+ var align = HUB.config.displayAlign.charAt(0),
+ side = this.Get("side").charAt(0);
+ this.nMMLhasLabels = true;
+ this.nMMLlaMatch = (align === side);
+ this.nMMLforceWidth =
+ (align === "c" || !!((this.width||"").match("%")));
+ break;
+ }
}
- parent.appendChild(tag);
}
- });
- }
+ //
+ // Firefox < 13 doesn't handle width, so put it in styles instead
+ //
+ if (this.width && this.ffTableWidthBug) {
+ var styles = (this.style||"").replace(/;\s*$/,"").split(";");
+ if (styles[0] === "") {styles.shift()}
+ styles.push("width:"+this.width);
+ this.style = styles.join(";");
+ }
+ this.SUPER(arguments).toNativeMML.call(this,parent);
+ //
+ if (this.nMMLhasLabels) {
+ var mtable = parent.firstChild;
+ //
+ // Add column attributes on the left when extra columns where inserted
+ //
+ if (this.nMMLforceWidth || side !== "r") {
+ var n = (align !== "l" ? 1 : 0) + (side === "l" ? 1 : 0);
+ if (n) {
+ var attr = {columnalign:"left", columnwidth:"auto",
+ columnspacing:"0px", columnlines:"none"};
+ for (var id in attr) {if (attr.hasOwnProperty(id) && this[id]) {
+ var cols = [attr[id],attr[id]].slice(2-n).join(" ")+" ";
+ mtable.setAttribute(id,cols+mtable.getAttribute(id));
+ }}
+ }
+ }
+ //
+ // Force the table width to 100% when needed
+ //
+ if (this.nMMLforceWidth || !this.nMMLlaMatch)
+ {mtable.setAttribute("width","100%")}
+ }
+ }
+ });
+ MML.mtr.Augment({
+ toNativeMML: function (parent) {
+ this.SUPER(arguments).toNativeMML.call(this,parent);
+ var mtr = parent.lastChild;
+ if (nMML.tableSpacingBug) {
+ //
+ // Set the row/column spacing. If this.parent.nMMLleftPadding does
+ // not contain enough value, repeat the last one.
+ //
+ var lp = this.parent.nMMLleftPadding, M = lp.length;
+ for (var mtd = mtr.firstChild, i = 0; mtd; mtd = mtd.nextSibling, i++) {
+ CELLSPACING(mtd,this.nMMLtopPadding,lp[i < M ? i : M-1]);
+ }
+ }
+
+ if (nMML.tableLabelBug) {
+ var forceWidth = this.parent.nMMLforceWidth,
+ side = this.parent.Get("side").charAt(0),
+ align = HUB.config.displayAlign.charAt(0);
+
+ if (this.parent.nMMLhasLabels && mtr.firstChild) {
+ //
+ // If we add a label or padding column on the left of mlabeledtr,
+ // mirror that here and remove padding from first table mtd
+ // so the spacing is consistent with unlabeled equations
+ //
+ if (forceWidth || side !== "r") {
+ NOPADDING("Left",mtr.firstChild);
+ if (align !== "l") {
+ mtr.insertBefore(this.NativeMMLelement("mtd"),mtr.firstChild)
+ .setAttribute("style","padding:0");
+ }
+ if (side === "l") {
+ mtr.insertBefore(this.NativeMMLelement("mtd"),mtr.firstChild)
+ .setAttribute("style","padding:0");
+ }
+ }
+ //
+ // If columns were added on the right, remove mtd padding
+ // so that spacing is consistent with unlabled equations
+ //
+ if (forceWidth || side !== "l") {NOPADDING("Right",mtr.lastChild)}
+ }
+ }
+ }
+ });
+ MML.mlabeledtr.Augment({
+ toNativeMML: function (parent) {
+ var mtr = this.NativeMMLelement("mtr");
+ this.NativeMMLattributes(mtr);
+ //
+ // Add row data
+ //
+ for (var i = 1, m = this.data.length; i < m; i++) {
+ if (this.data[i]) {this.data[i].toNativeMML(mtr)}
+ else {mtr.appendChild(this.NativeMMLelement("mtd"))}
+ }
+
+ if (nMML.tableSpacingBug) {
+ //
+ // Set the row/column spacing. If this.parent.nMMLleftPadding does
+ // not contain enough value, repeat the last one.
+ //
+ var lp = this.parent.nMMLleftPadding, M = lp.length;
+ for (var mtd = mtr.firstChild, i = 0; mtd; mtd = mtd.nextSibling, i++) {
+ CELLSPACING(mtd,this.nMMLtopPadding,lp[i < M ? i : M-1]);
+ }
+ }
+
+ if (nMML.tableLabelBug) {
+ var side = this.parent.Get("side").charAt(0),
+ align = HUB.config.displayAlign.charAt(0),
+ indent = HUB.config.displayIndent;
+ //
+ // Create label and either set the column width (if label is on the
+ // same side as the alignment), or use mpadded to hide the label
+ // width
+ //
+ this.data[0].toNativeMML(mtr);
+ var label = mtr.lastChild, pad = label;
+ if (side === align) {
+ label.setAttribute("style","width:"+indent);
+ label.setAttribute("columnalign",HUB.config.displayAlign);
+ } else {
+ pad = this.NativeMMLelement("mpadded");
+ pad.setAttribute("style","width:0");
+ pad.setAttribute("width","0px");
+ pad.appendChild(label.firstChild);
+ label.appendChild(pad);
+ }
+ NOPADDING("",label); mtr.removeChild(label);
+ //
+ // Get spacing to use for separation of label from main table
+ //
+ var width = 100, forceWidth = this.parent.nMMLforceWidth;
+ if ((this.parent.width||"").match(/%/)) {
+ width -= parseFloat(this.parent.width)
+ };
+ var w = width;
+ //
+ // Add spacing (and possibly label) at the left if needed
+ //
+ if (forceWidth || side !== "r") {
+ NOPADDING("Left",mtr.firstChild);
+ if (align !== "l") {
+ if (align === "c") {w /= 2}; width -= w;
+ mtr.insertBefore(this.NativeMMLelement("mtd"),mtr.firstChild)
+ .setAttribute("style","padding:0;width:"+w+"%");
+ }
+ if (side === "l") {mtr.insertBefore(label,mtr.firstChild)}
+ }
+ //
+ // Add spacing (and possibly label) at the right if needed
+ //
+ if (forceWidth || side !== "l") {
+ NOPADDING("Right",mtr.lastChild);
+ if (align !== "r") {
+ mtr.appendChild(this.NativeMMLelement("mtd"))
+ .setAttribute("style","padding:0;width:"+width+"%");
+ }
+ if (side === "r") {
+ if (side !== align) {pad.setAttribute("lspace","-1width")}
+ mtr.appendChild(label);
+ }
+ }
+ }
+ //
+ // Add row to table
+ //
+ parent.appendChild(mtr);
+ }
+ });
+
+ MML.mtd.Augment({
+ toNativeMML: function (parent) {
+ var tag = parent.appendChild(this.NativeMMLelement(this.type));
+ this.NativeMMLattributes(tag);
+ if (nMML.widthBug) {tag = tag.appendChild(this.NativeMMLelement("mrow"))}
+ for (var i = 0, m = this.data.length; i < m; i++) {
+ if (this.data[i]) {this.data[i].toNativeMML(tag)}
+ else {tag.appendChild(this.NativeMMLelement("mrow"))}
+ }
+ }
+ });
+
+ MML.mspace.Augment({
+ toNativeMML: function (parent) {
+ this.SUPER(arguments).toNativeMML.call(this,parent);
+ if (nMML.spaceWidthBug && this.width) {
+ var mspace = parent.lastChild;
+ var width = mspace.getAttribute("width");
+ var style = mspace.getAttribute("style") || "";
+ if (style != "") {style += ";"}
+ mspace.setAttribute("style",style+"width:"+width);
+ }
+ }
+ });
var fontDir = MathJax.Ajax.fileURL(MathJax.OutputJax.fontDir+"/HTML-CSS/TeX/otf");
@@ -599,18 +879,47 @@
}
MML.math.Augment({
- //
- // Some browsers don't seem to add the xmlns attribute, so do it by hand.
- //
toNativeMML: function (parent) {
var tag = this.NativeMMLelement(this.type), math = tag;
+ //
+ // Some browsers don't seem to add the xmlns attribute, so do it by hand.
+ //
tag.setAttribute("xmlns",nMML.MMLnamespace);
this.NativeMMLattributes(tag);
+ //
+ // Use an extra <mrow> in FF so that we can get the correct width
+ // (the math element doesn't always have an accurate one, see below)
+ //
if (nMML.widthBug) {tag = tag.appendChild(this.NativeMMLelement("mrow"))}
+ //
+ // Add the children
+ //
for (var i = 0, m = this.data.length; i < m; i++) {
if (this.data[i]) {this.data[i].toNativeMML(tag)}
else {tag.appendChild(this.NativeMMLelement("mrow"))}
}
+ //
+ // Look for a top-level mtable and if it has labels
+ // Make sure the containers have 100% width, when needed
+ // If the label is on the same side as alignment,
+ // override the margin set by the stylesheet.
+ //
+ var mtable = ((this.data[0]||[]).data[0]||{});
+ if (mtable.nMMLhasLabels) {
+ if (mtable.nMMLforceWidth || !mtable.nMMLlaMatch) {
+ tag.setAttribute("style","width:100%")
+ parent.style.width = parent.parentNode.style.width="100%";
+ };
+ if (mtable.nMMLlaMatch) {
+ if (parent.parentNode.parentNode.nodeName.toLowerCase() === "div") {
+ parent.parentNode.parentNode.style
+ .setProperty("margin-"+HUB.config.displayAlign,"0px","important");
+ }
+ }
+ }
+ //
+ // Add the math to the page
+ //
parent.appendChild(math);
//
// Firefox can't seem to get the width of <math> elements right, so
@@ -618,7 +927,7 @@
// parent element to match. Even if we set the <math> width properly,
// it doesn't seem to propagate up to the <span> correctly.
//
- if (nMML.widthBug) {
+ if (nMML.widthBug && !mtable.nMMLforceWidth && mtable.nMMLlaMatch) {
//
// Convert size to ex's so that it scales properly if the print media
// has a different font size.
@@ -628,6 +937,108 @@
}
});
+ MML.mfenced.Augment({
+ toNativeMML: function (parent) {
+ if (!nMML.mfencedBug) {
+ this.SUPER(arguments).toNativeMML.call(this,parent);
+ return;
+ }
+
+ //
+ // Some browsers do not handle <mfenced> very well. The MathML spec
+ // suggests this equivalent construction instead, so let's use it:
+ // <mrow> open, child1, sep1, child2, ... sep(N-1), childN, close</mrow>
+ // Opera is a bit special: it does not support stretchy <mo>, does not
+ // parse mfenced@open/mfenced@close very well, does not support
+ // mfenced@separators and only displays the first child of the <mfenced>
+ // element... For this browser, we will use this construction:
+ // <mfenced open="open" close="close">
+ // <mrow>child1, sep1, child2, sep2, ..., sep(N-1), childN</mrow>
+ // </mfenced>
+ //
+ var isOpera = HUB.Browser.isOpera;
+ var i, m, operator;
+
+ //
+ // parse the open, close and separators attributes.
+ //
+ var values = this.getValues("open","close","separators");
+ values.open = values.open.replace(/^\s+/,"").replace(/\s+$/,"");
+ values.close = values.close.replace(/^\s+/,"").replace(/\s+$/,"");
+ values.separators = values.separators.replace(/\s+/g,"").split("");
+ if (values.separators.length == 0) {
+ //
+ // No separators specified, do not use separators at all.
+ //
+ values.separators = null;
+ } else if (values.separators.length < this.data.length-1) {
+ //
+ // There are not enough separators, repeat the last one.
+ //
+ var s = values.separators[values.separators.length-1];
+ for (i = this.data.length-1-values.separators.length; i > 0; i--)
+ {values.separators.push(s)}
+ }
+
+ //
+ // Create an <mrow> container and attach the attributes of the
+ // <mfenced> element to it. Note: removeAttribute does not raise any
+ // exception when the attributes is absent.
+ //
+ var tag = this.NativeMMLelement(isOpera ? this.type : "mrow");
+ this.NativeMMLattributes(tag);
+ tag.removeAttribute("separators");
+ if (isOpera) {
+ tag.setAttribute("open", values.open);
+ tag.setAttribute("close", values.close);
+ if (this.data.length > 1) {
+ parent.appendChild(tag); parent = tag;
+ tag = this.NativeMMLelement("mrow");
+ }
+ } else {
+ tag.removeAttribute("open");
+ tag.removeAttribute("close");
+ }
+
+ if (!isOpera) {
+ //
+ // Append the opening fence
+ //
+ operator = this.NativeMMLelement("mo");
+ operator.setAttribute("fence", "true");
+ operator.textContent = values.open;
+ tag.appendChild(operator);
+ }
+
+ //
+ // Append the content of the <mfenced>
+ //
+ for (i = 0, m = this.data.length; i < m; i++) {
+ if (values.separators && i > 0) {
+ operator = this.NativeMMLelement("mo");
+ operator.setAttribute("separator", "true");
+ operator.textContent = values.separators[i-1];
+ tag.appendChild(operator);
+ }
+ if (this.data[i]) {this.data[i].toNativeMML(tag)}
+ else {tag.appendChild(this.NativeMMLelement("mrow"))}
+ }
+
+ if (!isOpera) {
+ //
+ // Append the closing fence
+ //
+ operator = this.NativeMMLelement("mo");
+ operator.setAttribute("fence", "true");
+ operator.textContent = values.close;
+ tag.appendChild(operator);
+ }
+
+ // finally, append the new element to the parent.
+ parent.appendChild(tag);
+ }
+ });
+
MML.TeXAtom.Augment({
//
// Convert TeXatom to an mrow
@@ -698,10 +1109,33 @@
},
Opera: function (browser) {
nMML.operaPositionBug = true;
+ nMML.stretchyMoBug = true;
+ nMML.tableLabelBug = true;
+ nMML.mfencedBug = true;
},
Firefox: function (browser) {
- nMML.forceReflow = true;
- nMML.widthBug = true;
+ nMML.ffTableWidthBug = !browser.versionAtLeast("13.0"); // <mtable width="xx"> not implemented
+ nMML.forceReflow = true; // <mtable> with alignments set don't display properly without a reflow
+ nMML.widthBug = true; // <math> elements don't always get the correct width
+
+ // In Firefox < 20, the intrinsic width of <mspace> is not computed
+ // correctly and thus the element is displayed incorrectly in <mtable>.
+ nMML.spaceWidthBug = !browser.versionAtLeast("20.0");
+
+ nMML.tableSpacingBug = true; // mtable@rowspacing/mtable@columnspacing not
+ // supported.
+ nMML.tableLabelBug = true; // mlabeledtr is not implemented.
+ nMML.mfencedBug = true; // mfenced not displayed correctly
+ },
+ Chrome: function (browser) {
+ nMML.tableSpacingBug = true;
+ nMML.tableLabelBug = true;
+ nMML.mfencedBug = true;
+ },
+ Safari: function (browser) {
+ nMML.tableSpacingBug = true;
+ nMML.tableLabelBug = true;
+ nMML.mfencedBug = true;
}
});