Bug 1163374 - Basic MathML Accessibility support in AccessFu. r=yzen

This commit is contained in:
Frédéric Wang 2015-07-13 11:53:00 +02:00
parent a0830685a4
commit 3f8610c96e
8 changed files with 602 additions and 19 deletions

View File

@ -191,6 +191,82 @@ let OutputGenerator = {
});
},
/**
* Adds math roles to the output, for a MathML accessible.
* @param {Array} aOutput Output array.
* @param {nsIAccessible} aAccessible current accessible object.
* @param {String} aRoleStr aAccessible's role string.
*/
_addMathRoles: function _addMathRoles(aOutput, aAccessible, aRoleStr) {
// First, determine the actual role to use (e.g. mathmlfraction).
let roleStr = aRoleStr;
switch(aAccessible.role) {
case Roles.MATHML_CELL:
case Roles.MATHML_ENCLOSED:
case Roles.MATHML_LABELED_ROW:
case Roles.MATHML_ROOT:
case Roles.MATHML_SQUARE_ROOT:
case Roles.MATHML_TABLE:
case Roles.MATHML_TABLE_ROW:
// Use the default role string.
break;
case Roles.MATHML_MULTISCRIPTS:
case Roles.MATHML_OVER:
case Roles.MATHML_SUB:
case Roles.MATHML_SUB_SUP:
case Roles.MATHML_SUP:
case Roles.MATHML_UNDER:
case Roles.MATHML_UNDER_OVER:
// For scripted accessibles, use the string 'mathmlscripted'.
roleStr = 'mathmlscripted';
break;
case Roles.MATHML_FRACTION:
// From a semantic point of view, the only important point is to
// distinguish between fractions that have a bar and those that do not.
// Per the MathML 3 spec, the latter happens iff the linethickness
// attribute is of the form [zero-float][optional-unit]. In that case,
// we use the string 'mathmlfractionwithoutbar'.
let linethickness = Utils.getAttributes(aAccessible).linethickness;
if (linethickness) {
let numberMatch = linethickness.match(/^(?:\d|\.)+/);
if (numberMatch && !parseFloat(numberMatch[0])) {
roleStr += 'withoutbar';
}
}
break;
default:
// Otherwise, do not output the actual role.
roleStr = null;
break;
}
// Get the math role based on the position in the parent accessible
// (e.g. numerator for the first child of a mathmlfraction).
let mathRole = Utils.getMathRole(aAccessible);
if (mathRole) {
aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']
({string: this._getOutputName(mathRole)});
}
if (roleStr) {
aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']
({string: this._getOutputName(roleStr)});
}
},
/**
* Adds MathML menclose notations to the output.
* @param {Array} aOutput Output array.
* @param {nsIAccessible} aAccessible current accessible object.
*/
_addMencloseNotations: function _addMencloseNotations(aOutput, aAccessible) {
let notations = Utils.getAttributes(aAccessible).notation || 'longdiv';
aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift'].apply(
aOutput, [for (notation of notations.split(' '))
{string: this._getOutputName('notation-' + notation)}
]
);
},
/**
* Adds an entry type attribute to the description if available.
* @param {Array} aOutput Output array.
@ -212,7 +288,7 @@ let OutputGenerator = {
_addState: function _addState(aOutput, aState, aRoleStr) {}, // jshint ignore:line
_addRole: function _addRole(aOutput, aRoleStr) {}, // jshint ignore:line
_addRole: function _addRole(aOutput, aAccessible, aRoleStr) {}, // jshint ignore:line
get outputOrder() {
if (!this._utteranceOrder) {
@ -301,7 +377,67 @@ let OutputGenerator = {
'dialog': INCLUDE_DESC | INCLUDE_NAME,
'chrome window': IGNORE_EXPLICIT_NAME,
'app root': IGNORE_EXPLICIT_NAME,
'statusbar': NAME_FROM_SUBTREE_RULE },
'statusbar': NAME_FROM_SUBTREE_RULE,
'mathml table': INCLUDE_DESC | INCLUDE_NAME,
'mathml labeled row': NAME_FROM_SUBTREE_RULE,
'mathml table row': NAME_FROM_SUBTREE_RULE,
'mathml cell': INCLUDE_DESC | INCLUDE_NAME,
'mathml fraction': INCLUDE_DESC,
'mathml square root': INCLUDE_DESC,
'mathml root': INCLUDE_DESC,
'mathml enclosed': INCLUDE_DESC,
'mathml sub': INCLUDE_DESC,
'mathml sup': INCLUDE_DESC,
'mathml sub sup': INCLUDE_DESC,
'mathml under': INCLUDE_DESC,
'mathml over': INCLUDE_DESC,
'mathml under over': INCLUDE_DESC,
'mathml multiscripts': INCLUDE_DESC,
'mathml identifier': INCLUDE_DESC,
'mathml number': INCLUDE_DESC,
'mathml operator': INCLUDE_DESC,
'mathml text': INCLUDE_DESC,
'mathml string literal': INCLUDE_DESC,
'mathml row': INCLUDE_DESC,
'mathml style': INCLUDE_DESC,
'mathml error': INCLUDE_DESC },
mathmlRolesSet: new Set([
Roles.MATHML_MATH,
Roles.MATHML_IDENTIFIER,
Roles.MATHML_NUMBER,
Roles.MATHML_OPERATOR,
Roles.MATHML_TEXT,
Roles.MATHML_STRING_LITERAL,
Roles.MATHML_GLYPH,
Roles.MATHML_ROW,
Roles.MATHML_FRACTION,
Roles.MATHML_SQUARE_ROOT,
Roles.MATHML_ROOT,
Roles.MATHML_FENCED,
Roles.MATHML_ENCLOSED,
Roles.MATHML_STYLE,
Roles.MATHML_SUB,
Roles.MATHML_SUP,
Roles.MATHML_SUB_SUP,
Roles.MATHML_UNDER,
Roles.MATHML_OVER,
Roles.MATHML_UNDER_OVER,
Roles.MATHML_MULTISCRIPTS,
Roles.MATHML_TABLE,
Roles.LABELED_ROW,
Roles.MATHML_TABLE_ROW,
Roles.MATHML_CELL,
Roles.MATHML_ACTION,
Roles.MATHML_ERROR,
Roles.MATHML_STACK,
Roles.MATHML_LONG_DIVISION,
Roles.MATHML_STACK_GROUP,
Roles.MATHML_STACK_ROW,
Roles.MATHML_STACK_CARRIES,
Roles.MATHML_STACK_CARRY,
Roles.MATHML_STACK_LINE
]),
objectOutputFunctions: {
_generateBaseOutput:
@ -311,7 +447,7 @@ let OutputGenerator = {
if (aFlags & INCLUDE_DESC) {
this._addState(output, aState, aRoleStr);
this._addType(output, aAccessible, aRoleStr);
this._addRole(output, aRoleStr);
this._addRole(output, aAccessible, aRoleStr);
}
if (aFlags & INCLUDE_VALUE && aAccessible.value.trim()) {
@ -348,7 +484,7 @@ let OutputGenerator = {
aAccessible.groupPosition({}, itemof, itemno);
let output = [];
this._addState(output, aState);
this._addRole(output, aRoleStr);
this._addRole(output, aAccessible, aRoleStr);
output.push({
string: 'objItemOfN',
args: [itemno.value, itemof.value]
@ -374,7 +510,7 @@ let OutputGenerator = {
if (table.isProbablyForLayout()) {
return output;
}
this._addRole(output, aRoleStr);
this._addRole(output, aAccessible, aRoleStr);
output.push.call(output, {
string: this._getOutputName('tblColumnInfo'),
count: table.columnCount
@ -394,6 +530,23 @@ let OutputGenerator = {
this._addName(output, aAccessible, aFlags);
this._addLandmark(output, aAccessible);
return output;
},
// Use the table output functions for MathML tabular elements.
mathmltable: function mathmltable() {
return this.objectOutputFunctions.table.apply(this, arguments);
},
mathmlcell: function mathmlcell() {
return this.objectOutputFunctions.cell.apply(this, arguments);
},
mathmlenclosed: function mathmlenclosed(aAccessible, aRoleStr, aState,
aFlags, aContext) {
let output = this.objectOutputFunctions.defaultFunc.
apply(this, [aAccessible, aRoleStr, aState, aFlags, aContext]);
this._addMencloseNotations(output, aAccessible);
return output;
}
}
};
@ -597,8 +750,12 @@ this.UtteranceGenerator = { // jshint ignore:line
return aContext.newAncestry;
},
_addRole: function _addRole(aOutput, aRoleStr) {
aOutput.push({string: this._getOutputName(aRoleStr)});
_addRole: function _addRole(aOutput, aAccessible, aRoleStr) {
if (this.mathmlRolesSet.has(aAccessible.role)) {
this._addMathRoles(aOutput, aAccessible, aRoleStr);
} else {
aOutput.push({string: this._getOutputName(aRoleStr)});
}
},
_addState: function _addState(aOutput, aState, aRoleStr) {
@ -657,7 +814,7 @@ this.UtteranceGenerator = { // jshint ignore:line
_getListUtterance:
function _getListUtterance(aAccessible, aRoleStr, aFlags, aItemCount) {
let utterance = [];
this._addRole(utterance, aRoleStr);
this._addRole(utterance, aAccessible, aRoleStr);
utterance.push({
string: this._getOutputName('listItemsCount'),
count: aItemCount
@ -805,8 +962,12 @@ this.BrailleGenerator = { // jshint ignore:line
return OutputGenerator._getOutputName(aName) + 'Abbr';
},
_addRole: function _addRole(aBraille, aRoleStr) {
aBraille.push({string: this._getOutputName(aRoleStr)});
_addRole: function _addRole(aBraille, aAccessible, aRoleStr) {
if (this.mathmlRolesSet.has(aAccessible.role)) {
this._addMathRoles(aBraille, aAccessible, aRoleStr);
} else {
aBraille.push({string: this._getOutputName(aRoleStr)});
}
},
_addState: function _addState(aBraille, aState, aRoleStr) {

View File

@ -102,7 +102,8 @@ var gSimpleTraversalRoles =
Roles.COLUMNHEADER,
Roles.ROWHEADER,
Roles.STATUSBAR,
Roles.SWITCH];
Roles.SWITCH,
Roles.MATHML_MATH];
var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
// An object is simple, if it either has a single child lineage,

View File

@ -415,21 +415,41 @@ this.Utils = { // jshint ignore:line
},
getLandmarkName: function getLandmarkName(aAccessible) {
const landmarks = [
return this.matchRoles(aAccessible, [
'banner',
'complementary',
'contentinfo',
'main',
'navigation',
'search'
];
]);
},
getMathRole: function getMathRole(aAccessible) {
return this.matchRoles(aAccessible, [
'base',
'close-fence',
'denominator',
'numerator',
'open-fence',
'overscript',
'presubscript',
'presuperscript',
'root-index',
'subscript',
'superscript',
'underscript'
]);
},
matchRoles: function matchRoles(aAccessible, aRoles) {
let roles = this.getAttributes(aAccessible)['xml-roles'];
if (!roles) {
return;
}
// Looking up a role that would match a landmark.
return this.matchAttributeValue(roles, landmarks);
// Looking up a role that would match any in the provided roles.
return this.matchAttributeValue(roles, aRoles);
},
getEmbeddedControl: function getEmbeddedControl(aLabel) {
@ -884,8 +904,12 @@ PivotContext.prototype = {
if (!aAccessible) {
return null;
}
if ([Roles.CELL, Roles.COLUMNHEADER, Roles.ROWHEADER].indexOf(
aAccessible.role) < 0) {
if ([
Roles.CELL,
Roles.COLUMNHEADER,
Roles.ROWHEADER,
Roles.MATHML_CELL
].indexOf(aAccessible.role) < 0) {
return null;
}
try {
@ -950,7 +974,9 @@ PivotContext.prototype = {
cellInfo.current.columnHeaderCells))];
}
cellInfo.rowHeaders = [];
if (cellInfo.rowChanged && cellInfo.current.role === Roles.CELL) {
if (cellInfo.rowChanged &&
(cellInfo.current.role === Roles.CELL ||
cellInfo.current.role === Roles.MATHML_CELL)) {
cellInfo.rowHeaders = [headers for (headers of getHeaders( // jshint ignore:line
cellInfo.current.rowHeaderCells))];
}

View File

@ -18,6 +18,7 @@ skip-if = buildapp == 'mulet'
[test_hints.html]
[test_landmarks.html]
[test_live_regions.html]
[test_output_mathml.html]
[test_output.html]
[test_quicknav_modes.html]
[test_tables.html]

View File

@ -145,5 +145,11 @@
<div aria-label="Last sync: 30min ago" id="statusbar-2" role="status"></div>
<span id="switch-1" role="switch" aria-checked="false" aria-label="Light switch"></span>
<p>This is a MathML formula <math id="math-1" display="block">
<mfrac>
<mrow><mi>x</mi><mo>+</mo><mn>1</mn></mrow>
<msqrt><mn>3</mn><mo>/</mo><mn>4</mn></msqrt>
</mfrac>
</math> with some text after.</p>
</body>
</html>

View File

@ -0,0 +1,305 @@
<html>
<head>
<title>[AccessFu] MathML Accessibility Support</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="output.js"></script>
<script type="application/javascript">
function doTest() {
// Test the following accOrElmOrID.
var tests = [{
accOrElmOrID: "math-1",
expectedUtterance: [
[{"string":"open-fence"},"(","x",",","y",{"string":"close-fence"},")"],
["(",{"string":"open-fence"},"x",",","y",")",{"string":"close-fence"}]
],
expectedBraille: [
[{"string":"open-fenceAbbr"},"(","x",",","y",{"string":"close-fenceAbbr"},")"],
["(",{"string":"open-fenceAbbr"},"x",",","y",")",{"string":"close-fenceAbbr"}]
]
}, {
accOrElmOrID: "mfrac-1",
expectedUtterance: [
[{"string":"mathmlfraction"},{"string":"numerator"},"a",{"string":"denominator"},"b"],
["a",{"string":"numerator"},"b",{"string":"denominator"},{"string":"mathmlfraction"}]
],
expectedBraille: [
[{"string":"mathmlfractionAbbr"},{"string":"numeratorAbbr"},"a",{"string":"denominatorAbbr"},"b"],
["a",{"string":"numeratorAbbr"},"b",{"string":"denominatorAbbr"},{"string":"mathmlfractionAbbr"}]
]
}, {
accOrElmOrID: "mfrac-2",
expectedUtterance: [
[{"string":"mathmlfractionwithoutbar"},{"string":"numerator"},"a",{"string":"denominator"},"b"],
["a",{"string":"numerator"},"b",{"string":"denominator"},{"string":"mathmlfractionwithoutbar"}]
],
expectedBraille: [
[{"string":"mathmlfractionwithoutbarAbbr"},{"string":"numeratorAbbr"},"a",{"string":"denominatorAbbr"},"b"],
["a",{"string":"numeratorAbbr"},"b",{"string":"denominatorAbbr"},{"string":"mathmlfractionwithoutbarAbbr"}]
]
}, {
accOrElmOrID: "msub-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"subscript"},"b"],
["a",{"string":"base"},"b",{"string":"subscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"subscriptAbbr"},"b"],
["a",{"string":"baseAbbr"},"b",{"string":"subscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "msup-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"superscript"},"b"],
["a",{"string":"base"},"b",{"string":"superscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"superscriptAbbr"},"b"],
["a",{"string":"baseAbbr"},"b",{"string":"superscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "msubsup-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"subscript"},"b",{"string":"superscript"},"c"],
["a",{"string":"base"},"b",{"string":"subscript"},"c",{"string":"superscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"subscriptAbbr"},"b",{"string":"superscriptAbbr"},"c"],
["a",{"string":"baseAbbr"},"b",{"string":"subscriptAbbr"},"c",{"string":"superscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "mmultiscripts-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"subscript"},"b",{"string":"superscript"},"c",{"string":"superscript"},"d",{"string":"presubscript"},"e",{"string":"presubscript"},"f",{"string":"presuperscript"},"g"],
["a",{"string":"base"},"b",{"string":"subscript"},"c",{"string":"superscript"},"d",{"string":"superscript"},"e",{"string":"presubscript"},"f",{"string":"presubscript"},"g",{"string":"presuperscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"subscriptAbbr"},"b",{"string":"superscriptAbbr"},"c",{"string":"superscriptAbbr"},"d",{"string":"presubscriptAbbr"},"e",{"string":"presubscriptAbbr"},"f",{"string":"presuperscriptAbbr"},"g"],
["a",{"string":"baseAbbr"},"b",{"string":"subscriptAbbr"},"c",{"string":"superscriptAbbr"},"d",{"string":"superscriptAbbr"},"e",{"string":"presubscriptAbbr"},"f",{"string":"presubscriptAbbr"},"g",{"string":"presuperscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "munder-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"underscript"},"b"],
["a",{"string":"base"},"b",{"string":"underscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"underscriptAbbr"},"b"],
["a",{"string":"baseAbbr"},"b",{"string":"underscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "mover-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"overscript"},"b"],
["a",{"string":"base"},"b",{"string":"overscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"overscriptAbbr"},"b"],
["a",{"string":"baseAbbr"},"b",{"string":"overscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "munderover-1",
expectedUtterance: [
[{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"underscript"},"b",{"string":"overscript"},"c"],
["a",{"string":"base"},"b",{"string":"underscript"},"c",{"string":"overscript"},{"string":"mathmlscripted"}]
],
expectedBraille: [
[{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"underscriptAbbr"},"b",{"string":"overscriptAbbr"},"c"],
["a",{"string":"baseAbbr"},"b",{"string":"underscriptAbbr"},"c",{"string":"overscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
]
}, {
accOrElmOrID: "mroot-1",
expectedUtterance: [
[{"string":"mathmlroot"},{"string":"base"},"a",{"string":"root-index"},"b"],
["a",{"string":"base"},"b",{"string":"root-index"},{"string":"mathmlroot"}]
],
expectedBraille: [
[{"string":"mathmlrootAbbr"},{"string":"baseAbbr"},"a",{"string":"root-indexAbbr"},"b"],
["a",{"string":"baseAbbr"},"b",{"string":"root-indexAbbr"},{"string":"mathmlrootAbbr"}]
]
}, {
accOrElmOrID: "mtable-1",
expectedUtterance: [
[{"string":"mathmltable"},{"string":"tblColumnInfo","count":3},{"string":"tblRowInfo","count":2},{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[1]},"a",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[1]},"b",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[1]},"c",{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[2]},"d",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[2]},"e",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[2]},"f"],
["a",{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[1]},"b",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[1]},"c",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[1]},"d",{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[2]},"e",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[2]},"f",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[2]},{"string":"mathmltable"},{"string":"tblColumnInfo","count":3},{"string":"tblRowInfo","count":2}]
],
expectedBraille: [
[{"string":"mathmltableAbbr"},{"string":"tblColumnInfoAbbr","count":3},{"string":"tblRowInfoAbbr","count":2},{"string":"cellInfoAbbr","args":[1,1]},"a",{"string":"cellInfoAbbr","args":[2,1]},"b",{"string":"cellInfoAbbr","args":[3,1]},"c",{"string":"cellInfoAbbr","args":[1,2]},"d",{"string":"cellInfoAbbr","args":[2,2]},"e",{"string":"cellInfoAbbr","args":[3,2]},"f"],
["a",{"string":"cellInfoAbbr","args":[1,1]},"b",{"string":"cellInfoAbbr","args":[2,1]},"c",{"string":"cellInfoAbbr","args":[3,1]},"d",{"string":"cellInfoAbbr","args":[1,2]},"e",{"string":"cellInfoAbbr","args":[2,2]},"f",{"string":"cellInfoAbbr","args":[3,2]},{"string":"mathmltableAbbr"},{"string":"tblColumnInfoAbbr","count":3},{"string":"tblRowInfoAbbr","count":2}]
]
}, {
accOrElmOrID: "menclose-1",
expectedUtterance: [
[{"string":"mathmlenclosed"},{"string":"notation-longdiv"},"a"],
["a",{"string":"notation-longdiv"},{"string":"mathmlenclosed"}]
],
expectedBraille: [
[{"string":"mathmlenclosedAbbr"},{"string":"notation-longdivAbbr"},"a"],
["a",{"string":"notation-longdivAbbr"},{"string":"mathmlenclosedAbbr"}]
]
}, {
accOrElmOrID: "menclose-2",
expectedUtterance: [
[{"string":"mathmlenclosed"},{"string":"notation-circle"},"a"],
["a",{"string":"notation-circle"},{"string":"mathmlenclosed"}]
],
expectedBraille: [
[{"string":"mathmlenclosedAbbr"},{"string":"notation-circleAbbr"},"a"],
["a",{"string":"notation-circleAbbr"},{"string":"mathmlenclosedAbbr"}]
]
}, {
accOrElmOrID: "menclose-3",
expectedUtterance: [
[{"string":"mathmlenclosed"},{"string":"notation-left"},{"string":"notation-top"},{"string":"notation-bottom"},"a"],
["a",{"string":"notation-left"},{"string":"notation-top"},{"string":"notation-bottom"},{"string":"mathmlenclosed"}]
],
expectedBraille: [
[{"string":"mathmlenclosedAbbr"},{"string":"notation-leftAbbr"},{"string":"notation-topAbbr"},{"string":"notation-bottomAbbr"},"a"],
["a",{"string":"notation-leftAbbr"},{"string":"notation-topAbbr"},{"string":"notation-bottomAbbr"},{"string":"mathmlenclosedAbbr"}]
]
}];
// Test all possible utterance order preference values.
tests.forEach(function run(test) {
var outputOrderValues = [0, 1];
outputOrderValues.forEach(function testOutputOrder(outputOrder) {
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, outputOrder);
testOutput(test.expectedUtterance[outputOrder], test.accOrElmOrID,
test.oldAccOrElmOrID, 1);
testOutput(test.expectedBraille[outputOrder], test.accOrElmOrID,
test.oldAccOrElmOrID, 0);
});
});
// If there was an original utterance order preference, revert to it.
SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<div id="root">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163374"
title="[AccessFu] MathML Accessibility Support">
Mozilla Bug 1163374
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<math id="math-1"><mo>(</mo><mi>x</mi><mo>,</mo><mi>y</mi><mo>)</mo></math>
<math>
<mfrac id="mfrac-1">
<mi>a</mi>
<mi>b</mi>
</mfrac>
</math>
<math>
<mfrac id="mfrac-2" linethickness="0px">
<mi>a</mi>
<mi>b</mi>
</mfrac>
</math>
<math>
<msub id="msub-1">
<mi>a</mi>
<mi>b</mi>
</msub>
</math>
<math>
<msup id="msup-1">
<mi>a</mi>
<mi>b</mi>
</msup>
</math>
<math>
<msubsup id="msubsup-1">
<mi>a</mi>
<mi>b</mi>
<mi>c</mi>
</msubsup>
</math>
<math>
<mmultiscripts id="mmultiscripts-1">
<mi>a</mi>
<mi>b</mi>
<mi>c</mi>
<none/>
<mi>d</mi>
<mprescripts/>
<mi>e</mi>
<none/>
<mi>f</mi>
<mi>g</mi>
</mmultiscripts>
</math>
<math>
<munder id="munder-1">
<mi>a</mi>
<mi>b</mi>
</munder>
</math>
<math>
<mover id="mover-1">
<mi>a</mi>
<mi>b</mi>
</mover>
</math>
<math>
<munderover id="munderover-1">
<mi>a</mi>
<mi>b</mi>
<mi>c</mi>
</munderover>
</math>
<math>
<mroot id="mroot-1">
<mi>a</mi>
<mi>b</mi>
</mroot>
</math>
<math>
<mtable id="mtable-1">
<mtr>
<mtd><mi>a</mi></mtd>
<mtd><mi>b</mi></mtd>
<mtd><mi>c</mi></mtd>
</mtr>
<mtr>
<mtd><mi>d</mi></mtd>
<mtd><mi>e</mi></mtd>
<mtd><mi>f</mi></mtd>
</mtr>
</mtable>
</math>
<math>
<menclose id="menclose-1"><mi>a</mi></menclose>
</math>
<math>
<menclose id="menclose-2" notation="circle"><mi>a</mi></menclose>
</math>
<math>
<menclose id="menclose-3" notation="left top bottom"><mi>a</mi></menclose>
</math>
</div>
</body>
</html>

View File

@ -124,7 +124,8 @@
'5 8', 'gridcell4', 'Just an innocuous separator',
'Dirty Words', 'Meaning', 'Mud', 'Wet Dirt',
'Dirt', 'Messy Stuff', 'statusbar-1', 'statusbar-2',
'switch-1']);
'switch-1', 'This is a MathML formula ', 'math-1',
'with some text after.']);
gQueue.invoke();
}

View File

@ -75,9 +75,31 @@ definitionlist = definition list
term = term
definition = definition
mathmltable = math table
mathmlcell = cell
mathmlenclosed = enclosed
mathmlfraction = fraction
mathmlfractionwithoutbar = fraction without bar
mathmlroot = root
mathmlscripted = scripted
mathmlsquareroot = square root
# More sophisticated roles which are not actual numeric roles
textarea = text area
base = base
close-fence = closing fence
denominator = denominator
numerator = numerator
open-fence = opening fence
overscript = overscript
presubscript = presubscript
presuperscript = presuperscript
root-index = root index
subscript = subscript
superscript = superscript
underscript = underscript
# Text input types
textInputType_date = date
textInputType_email = e-mail
@ -191,6 +213,26 @@ quicknav_Separator = Separators
quicknav_Table = Tables
quicknav_Checkbox = Check boxes
# MathML menclose notations.
# See developer.mozilla.org/docs/Web/MathML/Element/menclose#attr-notation
notation-longdiv = long division
notation-actuarial = actuarial
notation-phasorangle = phasor angle
notation-radical = radical
notation-box = box
notation-roundedbox = rounded box
notation-circle = circle
notation-left = left
notation-right = right
notation-top = top
notation-bottom = bottom
notation-updiagonalstrike = up diagonal strike
notation-downdiagonalstrike = down diagonal strike
notation-verticalstrike = vertical strike
notation-horizontalstrike = horizontal strike
notation-updiagonalarrow = up diagonal arrow
notation-madruwb = madruwb
# Shortened role names for braille
menubarAbbr = menu bar
scrollbarAbbr = scroll bar
@ -274,3 +316,43 @@ stateCheckedAbbr = (x)
stateUncheckedAbbr = ( )
statePressedAbbr = (x)
stateUnpressedAbbr = ( )
mathmlenclosedAbbr = enclosed
mathmltableAbbr = tbl
mathmlcellAbbr = cell
mathmlfractionAbbr = frac
mathmlfractionwithoutbarAbbr = frac no bar
mathmlrootAbbr = root
mathmlscriptedAbbr = scripted
mathmlsquarerootAbbr = sqrt
baseAbbr = base
close-fenceAbbr = close
denominatorAbbr = den
numeratorAbbr = num
open-fenceAbbr = open
overscriptAbbr = over
presubscriptAbbr = presub
presuperscriptAbbr = presup
root-indexAbbr = index
subscriptAbbr = sub
superscriptAbbr = sup
underscriptAbbr = under
notation-longdivAbbr = longdiv
notation-actuarialAbbr = act
notation-phasorangleAbbr = phasang
notation-radicalAbbr = rad
notation-boxAbbr = box
notation-roundedboxAbbr = rndbox
notation-circleAbbr = circ
notation-leftAbbr = lft
notation-rightAbbr = rght
notation-topAbbr = top
notation-bottomAbbr = bot
notation-updiagonalstrikeAbbr = updiagstrike
notation-downdiagonalstrikeAbbr = dwndiagstrike
notation-verticalstrikeAbbr = vstrike
notation-horizontalstrikeAbbr = hstrike
notation-updiagonalarrowAbbr = updiagarrow
notation-madruwbAbbr = madruwb