зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1732280 - Implement mappings for sub, sup elements and subscript, superscript roles, r=Jamie
This commit adds mappings for HTML sub and sup elements, as well as ARIA role mappings for subscript, superscript roles, with the goal of properly exposing this information to the accessibility tree. This commit also updates text attribute code to account for the attributes implied by those roles. Finally, this commit updates tests to verify that the role and attribute information is working properly. Differential Revision: https://phabricator.services.mozilla.com/D155523
This commit is contained in:
Родитель
088c86b28a
Коммит
982410361d
|
@ -1152,6 +1152,15 @@ static const nsRoleMapEntry sWAIRoleMaps[] = {
|
||||||
kGenericAccType,
|
kGenericAccType,
|
||||||
kNoReqStates
|
kNoReqStates
|
||||||
},
|
},
|
||||||
|
{ // subscript
|
||||||
|
nsGkAtoms::subscript,
|
||||||
|
roles::SUBSCRIPT,
|
||||||
|
kUseMapRole,
|
||||||
|
eNoValue,
|
||||||
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
|
kGenericAccType
|
||||||
|
},
|
||||||
{ // suggestion
|
{ // suggestion
|
||||||
nsGkAtoms::suggestion,
|
nsGkAtoms::suggestion,
|
||||||
roles::SUGGESTION,
|
roles::SUGGESTION,
|
||||||
|
@ -1161,6 +1170,15 @@ static const nsRoleMapEntry sWAIRoleMaps[] = {
|
||||||
eNoLiveAttr,
|
eNoLiveAttr,
|
||||||
kGenericAccType,
|
kGenericAccType,
|
||||||
},
|
},
|
||||||
|
{ // superscript
|
||||||
|
nsGkAtoms::superscript,
|
||||||
|
roles::SUPERSCRIPT,
|
||||||
|
kUseMapRole,
|
||||||
|
eNoValue,
|
||||||
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
|
kGenericAccType
|
||||||
|
},
|
||||||
{ // switch
|
{ // switch
|
||||||
nsGkAtoms::svgSwitch,
|
nsGkAtoms::svgSwitch,
|
||||||
roles::SWITCH,
|
roles::SWITCH,
|
||||||
|
|
|
@ -333,6 +333,8 @@ MARKUPMAP(
|
||||||
},
|
},
|
||||||
0)
|
0)
|
||||||
|
|
||||||
|
MARKUPMAP(sub, New_HyperText, roles::SUBSCRIPT)
|
||||||
|
|
||||||
MARKUPMAP(
|
MARKUPMAP(
|
||||||
summary,
|
summary,
|
||||||
[](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
|
[](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
|
||||||
|
@ -340,6 +342,8 @@ MARKUPMAP(
|
||||||
},
|
},
|
||||||
roles::SUMMARY)
|
roles::SUMMARY)
|
||||||
|
|
||||||
|
MARKUPMAP(sup, New_HyperText, roles::SUPERSCRIPT)
|
||||||
|
|
||||||
MARKUPMAP(
|
MARKUPMAP(
|
||||||
table,
|
table,
|
||||||
[](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
|
[](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace roles {
|
||||||
|
|
||||||
enum Role {
|
enum Role {
|
||||||
/**
|
/**
|
||||||
* Used when accessible hans't strong defined role.
|
* Used when the accessible has no strongly-defined role.
|
||||||
*/
|
*/
|
||||||
NOTHING = 0,
|
NOTHING = 0,
|
||||||
|
|
||||||
|
@ -1083,7 +1083,21 @@ enum Role {
|
||||||
*/
|
*/
|
||||||
METER = 185,
|
METER = 185,
|
||||||
|
|
||||||
LAST_ROLE = METER
|
/**
|
||||||
|
* Represents phrasing content that is presented with vertical alignment
|
||||||
|
* lower than the baseline and a smaller font size. For example, the "2" in
|
||||||
|
* the chemical formula H2O.
|
||||||
|
*/
|
||||||
|
SUBSCRIPT = 186,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents phrasing content that is presented with vertical alignment
|
||||||
|
* higher than the baseline and a smaller font size. For example, the
|
||||||
|
* exponent in a math expression.
|
||||||
|
*/
|
||||||
|
SUPERSCRIPT = 187,
|
||||||
|
|
||||||
|
LAST_ROLE = SUPERSCRIPT
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace roles
|
} // namespace roles
|
||||||
|
|
|
@ -1886,4 +1886,24 @@ ROLE(METER,
|
||||||
ROLE_SYSTEM_PROGRESSBAR,
|
ROLE_SYSTEM_PROGRESSBAR,
|
||||||
java::SessionAccessibility::CLASSNAME_VIEW,
|
java::SessionAccessibility::CLASSNAME_VIEW,
|
||||||
eNameFromValueRule)
|
eNameFromValueRule)
|
||||||
|
|
||||||
|
ROLE(SUBSCRIPT,
|
||||||
|
"subscript",
|
||||||
|
ATK_ROLE_SUBSCRIPT,
|
||||||
|
NSAccessibilityGroupRole,
|
||||||
|
@"AXSubscriptStyleGroup",
|
||||||
|
ROLE_SYSTEM_GROUPING,
|
||||||
|
IA2_ROLE_TEXT_FRAME,
|
||||||
|
java::SessionAccessibility::CLASSNAME_VIEW,
|
||||||
|
eNoNameRule)
|
||||||
|
|
||||||
|
ROLE(SUPERSCRIPT,
|
||||||
|
"superscript",
|
||||||
|
ATK_ROLE_SUPERSCRIPT,
|
||||||
|
NSAccessibilityGroupRole,
|
||||||
|
@"AXSuperscriptStyleGroup",
|
||||||
|
ROLE_SYSTEM_GROUPING,
|
||||||
|
IA2_ROLE_TEXT_FRAME,
|
||||||
|
java::SessionAccessibility::CLASSNAME_VIEW,
|
||||||
|
eNoNameRule)
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -120,7 +120,7 @@ void TextAttrsMgr::GetAttributes(AccAttributes* aAttributes,
|
||||||
TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
|
TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
|
||||||
|
|
||||||
// "text-position" text attribute
|
// "text-position" text attribute
|
||||||
TextPosTextAttr textPosTextAttr(rootFrame, frame);
|
TextPosTextAttr textPosTextAttr(rootFrame, frame, hyperTextElm, offsetNode);
|
||||||
|
|
||||||
TextAttr* attrArray[] = {
|
TextAttr* attrArray[] = {
|
||||||
&langTextAttr, &invalidTextAttr, &bgColorTextAttr,
|
&langTextAttr, &invalidTextAttr, &bgColorTextAttr,
|
||||||
|
@ -664,34 +664,67 @@ void TextAttrsMgr::TextDecorTextAttr::ExposeValue(
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TextAttrsMgr::TextPosTextAttr::TextPosTextAttr(nsIFrame* aRootFrame,
|
TextAttrsMgr::TextPosTextAttr::TextPosTextAttr(nsIFrame* aRootFrame,
|
||||||
nsIFrame* aFrame)
|
nsIFrame* aFrame,
|
||||||
: TTextAttr<TextPosValue>(!aFrame) {
|
nsIContent* aRootElm,
|
||||||
mRootNativeValue = GetTextPosValue(aRootFrame);
|
nsIContent* aElm)
|
||||||
mIsRootDefined = mRootNativeValue != eTextPosNone;
|
: TTextAttr<Maybe<TextPosValue>>(!aFrame && !aElm), mRootElm(aRootElm) {
|
||||||
|
// Get the text-position values for the roots and children.
|
||||||
|
// If we find an ARIA text-position value on a DOM element - searching up
|
||||||
|
// from the supplied root DOM element - use the associated frame as the root
|
||||||
|
// frame. This ensures that we're using the proper root frame for comparison.
|
||||||
|
nsIFrame* ariaFrame = nullptr;
|
||||||
|
Maybe<TextPosValue> rootAria = GetAriaTextPosValue(aRootElm, ariaFrame);
|
||||||
|
if (rootAria && ariaFrame) {
|
||||||
|
aRootFrame = ariaFrame;
|
||||||
|
}
|
||||||
|
Maybe<TextPosValue> rootLayout = GetLayoutTextPosValue(aRootFrame);
|
||||||
|
Maybe<TextPosValue> childLayout;
|
||||||
|
Maybe<TextPosValue> childAria;
|
||||||
if (aFrame) {
|
if (aFrame) {
|
||||||
mNativeValue = GetTextPosValue(aFrame);
|
childLayout = GetLayoutTextPosValue(aFrame);
|
||||||
mIsDefined = mNativeValue != eTextPosNone;
|
}
|
||||||
|
if (aElm) {
|
||||||
|
childAria = GetAriaTextPosValue(aElm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aria values take precedence over layout values.
|
||||||
|
mIsRootDefined = rootAria || rootLayout;
|
||||||
|
mRootNativeValue = rootAria ? rootAria : rootLayout;
|
||||||
|
mIsDefined = childAria || childLayout;
|
||||||
|
mNativeValue = childAria ? childAria : childLayout;
|
||||||
|
|
||||||
|
// If there's no child text-position information from ARIA, and the child
|
||||||
|
// layout info is equivalent to the root layout info (i.e., it's inherited),
|
||||||
|
// then we should prefer the root information.
|
||||||
|
if (!childAria && childLayout == rootLayout) {
|
||||||
|
mIsDefined = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextAttrsMgr::TextPosTextAttr::GetValueFor(LocalAccessible* aAccessible,
|
bool TextAttrsMgr::TextPosTextAttr::GetValueFor(LocalAccessible* aAccessible,
|
||||||
TextPosValue* aValue) {
|
Maybe<TextPosValue>* aValue) {
|
||||||
nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
|
nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
|
||||||
if (elm) {
|
if (elm) {
|
||||||
nsIFrame* frame = elm->GetPrimaryFrame();
|
nsIFrame* frame = elm->GetPrimaryFrame();
|
||||||
if (frame) {
|
if (frame) {
|
||||||
*aValue = GetTextPosValue(frame);
|
Maybe<TextPosValue> layoutValue = GetLayoutTextPosValue(frame);
|
||||||
return *aValue != eTextPosNone;
|
Maybe<TextPosValue> ariaValue = GetAriaTextPosValue(elm);
|
||||||
|
|
||||||
|
*aValue = ariaValue ? ariaValue : layoutValue;
|
||||||
|
return aValue->isSome();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAttrsMgr::TextPosTextAttr::ExposeValue(AccAttributes* aAttributes,
|
void TextAttrsMgr::TextPosTextAttr::ExposeValue(
|
||||||
const TextPosValue& aValue) {
|
AccAttributes* aAttributes, const Maybe<TextPosValue>& aValue) {
|
||||||
|
if (aValue.isNothing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<nsAtom> atom = nullptr;
|
RefPtr<nsAtom> atom = nullptr;
|
||||||
switch (aValue) {
|
switch (*aValue) {
|
||||||
case eTextPosBaseline:
|
case eTextPosBaseline:
|
||||||
atom = nsGkAtoms::baseline;
|
atom = nsGkAtoms::baseline;
|
||||||
break;
|
break;
|
||||||
|
@ -703,9 +736,6 @@ void TextAttrsMgr::TextPosTextAttr::ExposeValue(AccAttributes* aAttributes,
|
||||||
case eTextPosSuper:
|
case eTextPosSuper:
|
||||||
atom = NS_Atomize("super");
|
atom = NS_Atomize("super");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eTextPosNone:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atom) {
|
if (atom) {
|
||||||
|
@ -713,42 +743,75 @@ void TextAttrsMgr::TextPosTextAttr::ExposeValue(AccAttributes* aAttributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextAttrsMgr::TextPosValue TextAttrsMgr::TextPosTextAttr::GetTextPosValue(
|
Maybe<TextAttrsMgr::TextPosValue>
|
||||||
nsIFrame* aFrame) const {
|
TextAttrsMgr::TextPosTextAttr::GetAriaTextPosValue(nsIContent* aElm) const {
|
||||||
|
nsIFrame* ariaFrame = nullptr;
|
||||||
|
return GetAriaTextPosValue(aElm, ariaFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<TextAttrsMgr::TextPosValue>
|
||||||
|
TextAttrsMgr::TextPosTextAttr::GetAriaTextPosValue(nsIContent* aElm,
|
||||||
|
nsIFrame*& ariaFrame) const {
|
||||||
|
// Search for the superscript and subscript roles that imply text-position.
|
||||||
|
const nsIContent* elm = aElm;
|
||||||
|
do {
|
||||||
|
if (elm->IsElement()) {
|
||||||
|
const mozilla::dom::Element* domElm = elm->AsElement();
|
||||||
|
static const dom::Element::AttrValuesArray tokens[] = {
|
||||||
|
nsGkAtoms::subscript, nsGkAtoms::superscript, nullptr};
|
||||||
|
const int32_t valueIdx = domElm->FindAttrValueIn(
|
||||||
|
kNameSpaceID_None, nsGkAtoms::role, tokens, eCaseMatters);
|
||||||
|
ariaFrame = domElm->GetPrimaryFrame();
|
||||||
|
if (valueIdx == 0) {
|
||||||
|
return Some(eTextPosSub);
|
||||||
|
}
|
||||||
|
if (valueIdx == 1) {
|
||||||
|
return Some(eTextPosSuper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((elm = elm->GetParent()) && elm != mRootElm);
|
||||||
|
|
||||||
|
ariaFrame = nullptr;
|
||||||
|
return Nothing{};
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<TextAttrsMgr::TextPosValue>
|
||||||
|
TextAttrsMgr::TextPosTextAttr::GetLayoutTextPosValue(nsIFrame* aFrame) const {
|
||||||
const auto& verticalAlign = aFrame->StyleDisplay()->mVerticalAlign;
|
const auto& verticalAlign = aFrame->StyleDisplay()->mVerticalAlign;
|
||||||
if (verticalAlign.IsKeyword()) {
|
if (verticalAlign.IsKeyword()) {
|
||||||
switch (verticalAlign.AsKeyword()) {
|
switch (verticalAlign.AsKeyword()) {
|
||||||
case StyleVerticalAlignKeyword::Baseline:
|
case StyleVerticalAlignKeyword::Baseline:
|
||||||
return eTextPosBaseline;
|
return Some(eTextPosBaseline);
|
||||||
case StyleVerticalAlignKeyword::Sub:
|
case StyleVerticalAlignKeyword::Sub:
|
||||||
return eTextPosSub;
|
return Some(eTextPosSub);
|
||||||
case StyleVerticalAlignKeyword::Super:
|
case StyleVerticalAlignKeyword::Super:
|
||||||
return eTextPosSuper;
|
return Some(eTextPosSuper);
|
||||||
// No good guess for the rest, so do not expose value of text-position
|
// No good guess for the rest, so do not expose value of text-position
|
||||||
// attribute.
|
// attribute.
|
||||||
default:
|
default:
|
||||||
return eTextPosNone;
|
return Nothing{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& length = verticalAlign.AsLength();
|
const auto& length = verticalAlign.AsLength();
|
||||||
if (length.ConvertsToPercentage()) {
|
if (length.ConvertsToPercentage()) {
|
||||||
float percentValue = length.ToPercentage();
|
const float percentValue = length.ToPercentage();
|
||||||
return percentValue > 0
|
return percentValue > 0 ? Some(eTextPosSuper)
|
||||||
? eTextPosSuper
|
: (percentValue < 0 ? Some(eTextPosSub)
|
||||||
: (percentValue < 0 ? eTextPosSub : eTextPosBaseline);
|
: Some(eTextPosBaseline));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length.ConvertsToLength()) {
|
if (length.ConvertsToLength()) {
|
||||||
nscoord coordValue = length.ToLength();
|
const nscoord coordValue = length.ToLength();
|
||||||
return coordValue > 0 ? eTextPosSuper
|
return coordValue > 0
|
||||||
: (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
|
? Some(eTextPosSuper)
|
||||||
|
: (coordValue < 0 ? Some(eTextPosSub) : Some(eTextPosBaseline));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const nsIContent* content = aFrame->GetContent()) {
|
if (const nsIContent* content = aFrame->GetContent()) {
|
||||||
if (content->IsHTMLElement(nsGkAtoms::sup)) return eTextPosSuper;
|
if (content->IsHTMLElement(nsGkAtoms::sup)) return Some(eTextPosSuper);
|
||||||
if (content->IsHTMLElement(nsGkAtoms::sub)) return eTextPosSub;
|
if (content->IsHTMLElement(nsGkAtoms::sub)) return Some(eTextPosSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
return eTextPosNone;
|
return Nothing{};
|
||||||
}
|
}
|
||||||
|
|
|
@ -407,27 +407,27 @@ class TextAttrsMgr {
|
||||||
* Class is used for the work with "text-position" text attribute.
|
* Class is used for the work with "text-position" text attribute.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum TextPosValue {
|
enum TextPosValue { eTextPosBaseline, eTextPosSub, eTextPosSuper };
|
||||||
eTextPosNone = 0,
|
|
||||||
eTextPosBaseline,
|
|
||||||
eTextPosSub,
|
|
||||||
eTextPosSuper
|
|
||||||
};
|
|
||||||
|
|
||||||
class TextPosTextAttr : public TTextAttr<TextPosValue> {
|
class TextPosTextAttr : public TTextAttr<Maybe<TextPosValue>> {
|
||||||
public:
|
public:
|
||||||
TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
|
TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame,
|
||||||
|
nsIContent* aRootElm, nsIContent* aElm);
|
||||||
virtual ~TextPosTextAttr() {}
|
virtual ~TextPosTextAttr() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// TextAttr
|
// TextAttr
|
||||||
virtual bool GetValueFor(LocalAccessible* aAccessible,
|
virtual bool GetValueFor(LocalAccessible* aAccessible,
|
||||||
TextPosValue* aValue) override;
|
Maybe<TextPosValue>* aValue) override;
|
||||||
virtual void ExposeValue(AccAttributes* aAttributes,
|
virtual void ExposeValue(AccAttributes* aAttributes,
|
||||||
const TextPosValue& aValue) override;
|
const Maybe<TextPosValue>& aValue) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextPosValue GetTextPosValue(nsIFrame* aFrame) const;
|
Maybe<TextPosValue> GetAriaTextPosValue(nsIContent* aElm) const;
|
||||||
|
Maybe<TextPosValue> GetAriaTextPosValue(nsIContent* aElm,
|
||||||
|
nsIFrame*& ariaFrame) const;
|
||||||
|
Maybe<TextPosValue> GetLayoutTextPosValue(nsIFrame* aFrame) const;
|
||||||
|
nsIContent* mRootElm;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // TextAttrMgr
|
}; // TextAttrMgr
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
interface nsIAccessibleRole : nsISupports
|
interface nsIAccessibleRole : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Used when accessible hans't strong defined role.
|
* Used when the accessible has no strongly-defined role.
|
||||||
*/
|
*/
|
||||||
const unsigned long ROLE_NOTHING = 0;
|
const unsigned long ROLE_NOTHING = 0;
|
||||||
|
|
||||||
|
@ -1077,4 +1077,18 @@ interface nsIAccessibleRole : nsISupports
|
||||||
*/
|
*/
|
||||||
const unsigned long ROLE_METER = 185;
|
const unsigned long ROLE_METER = 185;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents phrasing content that is presented with vertical alignment
|
||||||
|
* lower than the baseline and a smaller font size. For example, the "2" in
|
||||||
|
* the chemical formula H2O.
|
||||||
|
*/
|
||||||
|
const unsigned long ROLE_SUBSCRIPT = 186;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents phrasing content that is presented with vertical alignment
|
||||||
|
* higher than the baseline and a smaller font size. For example, the
|
||||||
|
* exponent in a math expression.
|
||||||
|
*/
|
||||||
|
const unsigned long ROLE_SUPERSCRIPT = 187;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,6 +94,8 @@ addAccessibleTask(
|
||||||
<hr id="hr" />
|
<hr id="hr" />
|
||||||
<ins id="insertion">Inserted text</ins>
|
<ins id="insertion">Inserted text</ins>
|
||||||
<meter id="meter" min="0" max="100" value="24">meter text here</meter>
|
<meter id="meter" min="0" max="100" value="24">meter text here</meter>
|
||||||
|
<sub id="sub">sub text here</sub>
|
||||||
|
<sup id="sup">sup text here</sup>
|
||||||
|
|
||||||
<!-- Some SVG stuff -->
|
<!-- Some SVG stuff -->
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg"
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg"
|
||||||
|
@ -211,6 +213,8 @@ addAccessibleTask(
|
||||||
null,
|
null,
|
||||||
"level indicator"
|
"level indicator"
|
||||||
);
|
);
|
||||||
|
testRoleAndSubRole(accDoc, "sub", "AXGroup", "AXSubscriptStyleGroup");
|
||||||
|
testRoleAndSubRole(accDoc, "sup", "AXGroup", "AXSuperscriptStyleGroup");
|
||||||
|
|
||||||
// Some SVG stuff
|
// Some SVG stuff
|
||||||
testRoleAndSubRole(accDoc, "svg", "AXImage");
|
testRoleAndSubRole(accDoc, "svg", "AXImage");
|
||||||
|
|
|
@ -1375,18 +1375,33 @@
|
||||||
};
|
};
|
||||||
testElm("strong_container", obj);
|
testElm("strong_container", obj);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// HTML:sub
|
||||||
|
obj = {
|
||||||
|
role: ROLE_SUBSCRIPT
|
||||||
|
};
|
||||||
|
testElm("sub", obj);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// HTML:sup
|
||||||
|
obj = {
|
||||||
|
role: ROLE_SUPERSCRIPT
|
||||||
|
};
|
||||||
|
testElm("sup", obj);
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
// HTML:sub contained by paragraph
|
// HTML:sub contained by paragraph
|
||||||
|
|
||||||
obj = {
|
obj = {
|
||||||
role: ROLE_PARAGRAPH,
|
role: ROLE_PARAGRAPH,
|
||||||
textAttrs: {
|
|
||||||
0: { },
|
|
||||||
6: { "text-position": "sub" },
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
{ role: ROLE_TEXT_LEAF }, // plain text
|
{ role: ROLE_TEXT_LEAF }, // plain text
|
||||||
{ role: ROLE_TEXT_LEAF }, // HTML:sub text
|
{
|
||||||
|
role: ROLE_SUBSCRIPT, // HTML:sub
|
||||||
|
children: [
|
||||||
|
{ role: ROLE_TEXT_LEAF } // HTML:sub text
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
testElm("sub_container", obj);
|
testElm("sub_container", obj);
|
||||||
|
@ -1396,13 +1411,14 @@
|
||||||
|
|
||||||
obj = {
|
obj = {
|
||||||
role: ROLE_PARAGRAPH,
|
role: ROLE_PARAGRAPH,
|
||||||
textAttrs: {
|
|
||||||
0: { },
|
|
||||||
6: { "text-position": "super" },
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
{ role: ROLE_TEXT_LEAF }, // plain text
|
{ role: ROLE_TEXT_LEAF }, // plain text
|
||||||
{ role: ROLE_TEXT_LEAF }, // HTML:sup text
|
{
|
||||||
|
role: ROLE_SUPERSCRIPT, // HTML:sup
|
||||||
|
children: [
|
||||||
|
{ role: ROLE_TEXT_LEAF } // HTML:sup text
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
testElm("sup_container", obj);
|
testElm("sup_container", obj);
|
||||||
|
@ -1961,6 +1977,8 @@
|
||||||
<span id="span"></span>
|
<span id="span"></span>
|
||||||
<span id="span_explicit" title="explicit"></span>
|
<span id="span_explicit" title="explicit"></span>
|
||||||
<p id="strong_container">normal<strong>strong</strong></p>
|
<p id="strong_container">normal<strong>strong</strong></p>
|
||||||
|
<sub id="sub"></sub>
|
||||||
|
<sup id="sup"></sup>
|
||||||
<p id="sub_container">normal<sub>sub</sub></p>
|
<p id="sub_container">normal<sub>sub</sub></p>
|
||||||
<p id="sup_container">normal<sup>sup</sup></p>
|
<p id="sup_container">normal<sup>sup</sup></p>
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,9 @@ const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
|
||||||
const ROLE_SPINBUTTON = nsIAccessibleRole.ROLE_SPINBUTTON;
|
const ROLE_SPINBUTTON = nsIAccessibleRole.ROLE_SPINBUTTON;
|
||||||
const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
|
const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
|
||||||
const ROLE_STATUSBAR = nsIAccessibleRole.ROLE_STATUSBAR;
|
const ROLE_STATUSBAR = nsIAccessibleRole.ROLE_STATUSBAR;
|
||||||
|
const ROLE_SUBSCRIPT = nsIAccessibleRole.ROLE_SUBSCRIPT;
|
||||||
const ROLE_SUGGESTION = nsIAccessibleRole.ROLE_SUGGESTION;
|
const ROLE_SUGGESTION = nsIAccessibleRole.ROLE_SUGGESTION;
|
||||||
|
const ROLE_SUPERSCRIPT = nsIAccessibleRole.ROLE_SUPERSCRIPT;
|
||||||
const ROLE_SUMMARY = nsIAccessibleRole.ROLE_SUMMARY;
|
const ROLE_SUMMARY = nsIAccessibleRole.ROLE_SUMMARY;
|
||||||
const ROLE_SWITCH = nsIAccessibleRole.ROLE_SWITCH;
|
const ROLE_SWITCH = nsIAccessibleRole.ROLE_SWITCH;
|
||||||
const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
|
const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
|
||||||
|
|
|
@ -146,8 +146,12 @@
|
||||||
testRole("aria_spinbutton_mixed", ROLE_SPINBUTTON);
|
testRole("aria_spinbutton_mixed", ROLE_SPINBUTTON);
|
||||||
testRole("aria_status", ROLE_STATUSBAR);
|
testRole("aria_status", ROLE_STATUSBAR);
|
||||||
testRole("aria_status_mixed", ROLE_STATUSBAR);
|
testRole("aria_status_mixed", ROLE_STATUSBAR);
|
||||||
|
testRole("aria_subscript", ROLE_SUBSCRIPT);
|
||||||
|
testRole("aria_subscript_mixed", ROLE_SUBSCRIPT);
|
||||||
testRole("aria_suggestion", ROLE_SUGGESTION);
|
testRole("aria_suggestion", ROLE_SUGGESTION);
|
||||||
testRole("aria_suggestion_mixed", ROLE_SUGGESTION);
|
testRole("aria_suggestion_mixed", ROLE_SUGGESTION);
|
||||||
|
testRole("aria_superscript", ROLE_SUPERSCRIPT);
|
||||||
|
testRole("aria_superscript_mixed", ROLE_SUPERSCRIPT);
|
||||||
testRole("aria_switch", ROLE_SWITCH);
|
testRole("aria_switch", ROLE_SWITCH);
|
||||||
testRole("aria_switch_mixed", ROLE_SWITCH);
|
testRole("aria_switch_mixed", ROLE_SWITCH);
|
||||||
testRole("aria_tab", ROLE_PAGETAB);
|
testRole("aria_tab", ROLE_PAGETAB);
|
||||||
|
@ -496,8 +500,12 @@
|
||||||
<span id="aria_spinbutton_mixed" role="sPINBUTTOn"></span>
|
<span id="aria_spinbutton_mixed" role="sPINBUTTOn"></span>
|
||||||
<span id="aria_status" role="status"></span>
|
<span id="aria_status" role="status"></span>
|
||||||
<span id="aria_status_mixed" role="sTATUs"></span>
|
<span id="aria_status_mixed" role="sTATUs"></span>
|
||||||
|
<span id="aria_subscript" role="subscript"></span>
|
||||||
|
<span id="aria_subscript_mixed" role="sUBSCRIPt"></span>
|
||||||
<span id="aria_suggestion" role="suggestion"></span>
|
<span id="aria_suggestion" role="suggestion"></span>
|
||||||
<span id="aria_suggestion_mixed" role="sUGGESTIOn"></span>
|
<span id="aria_suggestion_mixed" role="sUGGESTIOn"></span>
|
||||||
|
<span id="aria_superscript" role="superscript"></span>
|
||||||
|
<span id="aria_superscript_mixed" role="sUPERSCRIPt"></span>
|
||||||
<span id="aria_switch" role="switch"></span>
|
<span id="aria_switch" role="switch"></span>
|
||||||
<span id="aria_switch_mixed" role="sWITCh"></span>
|
<span id="aria_switch_mixed" role="sWITCh"></span>
|
||||||
<span id="aria_tab" role="tab"></span>
|
<span id="aria_tab" role="tab"></span>
|
||||||
|
|
|
@ -151,50 +151,50 @@
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
|
testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
|
||||||
|
|
||||||
attrs = { "text-position": "super", "font-size": "10pt" };
|
// Embedded object (sup) has no attributes but takes up one character.
|
||||||
testTextAttrs(ID, 5, attrs, defAttrs, 5, 13);
|
testTextAttrs(ID, 5, {}, {}, 5, 6);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 13, attrs, defAttrs, 13, 27);
|
testTextAttrs(ID, 6, attrs, defAttrs, 6, 20);
|
||||||
|
|
||||||
attrs = { "text-position": "super" };
|
attrs = { "text-position": "super" };
|
||||||
testTextAttrs(ID, 27, attrs, defAttrs, 27, 35);
|
testTextAttrs(ID, 20, attrs, defAttrs, 20, 28);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 35, attrs, defAttrs, 35, 39);
|
testTextAttrs(ID, 28, attrs, defAttrs, 28, 32);
|
||||||
|
|
||||||
attrs = { "text-position": "sub", "font-size": "10pt" };
|
// Embedded object (sub) has no attributes but takes up one character.
|
||||||
testTextAttrs(ID, 39, attrs, defAttrs, 39, 50);
|
testTextAttrs(ID, 32, {}, {}, 32, 33);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 50, attrs, defAttrs, 50, 55);
|
testTextAttrs(ID, 33, attrs, defAttrs, 33, 38);
|
||||||
|
|
||||||
attrs = { "text-position": "sub" };
|
attrs = { "text-position": "sub" };
|
||||||
testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
|
testTextAttrs(ID, 38, attrs, defAttrs, 38, 47);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 64, attrs, defAttrs, 64, 69);
|
testTextAttrs(ID, 47, attrs, defAttrs, 47, 52);
|
||||||
|
|
||||||
attrs = { "text-position": "super" };
|
attrs = { "text-position": "super" };
|
||||||
testTextAttrs(ID, 69, attrs, defAttrs, 69, 84);
|
testTextAttrs(ID, 52, attrs, defAttrs, 52, 67);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 84, attrs, defAttrs, 84, 89);
|
testTextAttrs(ID, 67, attrs, defAttrs, 67, 72);
|
||||||
|
|
||||||
attrs = { "text-position": "sub" };
|
attrs = { "text-position": "sub" };
|
||||||
testTextAttrs(ID, 89, attrs, defAttrs, 89, 102);
|
testTextAttrs(ID, 72, attrs, defAttrs, 72, 85);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 102, attrs, defAttrs, 102, 107);
|
testTextAttrs(ID, 85, attrs, defAttrs, 85, 90);
|
||||||
|
|
||||||
attrs = { "text-position": "super" };
|
attrs = { "text-position": "super" };
|
||||||
testTextAttrs(ID, 107, attrs, defAttrs, 107, 123);
|
testTextAttrs(ID, 90, attrs, defAttrs, 90, 106);
|
||||||
|
|
||||||
attrs = {};
|
attrs = {};
|
||||||
testTextAttrs(ID, 123, attrs, defAttrs, 123, 128);
|
testTextAttrs(ID, 106, attrs, defAttrs, 106, 111);
|
||||||
|
|
||||||
attrs = { "text-position": "sub" };
|
attrs = { "text-position": "sub" };
|
||||||
testTextAttrs(ID, 128, attrs, defAttrs, 128, 142);
|
testTextAttrs(ID, 111, attrs, defAttrs, 111, 125);
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
// area7
|
// area7
|
||||||
|
@ -573,6 +573,75 @@
|
||||||
testDefaultTextAttrs(ID, defAttrs);
|
testDefaultTextAttrs(ID, defAttrs);
|
||||||
|
|
||||||
testTextAttrs(ID, -1, {}, defAttrs, 0, 11);
|
testTextAttrs(ID, -1, {}, defAttrs, 0, 11);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// HTML sub tag offset test - verify attributes
|
||||||
|
ID = "sub_tag";
|
||||||
|
defAttrs = buildDefaultTextAttrs(ID, "10pt");
|
||||||
|
defAttrs["text-position"] = "sub";
|
||||||
|
testDefaultTextAttrs(ID, defAttrs);
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// HTML sup tag offset test - verify attributes
|
||||||
|
ID = "sup_tag";
|
||||||
|
defAttrs = buildDefaultTextAttrs(ID, "10pt");
|
||||||
|
defAttrs["text-position"] = "super";
|
||||||
|
testDefaultTextAttrs(ID, defAttrs);
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// ARIA subscript role - verify text-position attribute
|
||||||
|
ID = "subscript_role";
|
||||||
|
defAttrs = { "text-position": "sub" };
|
||||||
|
testDefaultTextAttrs(ID, defAttrs, true);
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// ARIA superscript role - verify text-position attribute
|
||||||
|
ID = "superscript_role";
|
||||||
|
defAttrs = { "text-position": "super" };
|
||||||
|
testDefaultTextAttrs(ID, defAttrs, true);
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
// test text-position attributes in various situations
|
||||||
|
ID = "superscript_role_in_div";
|
||||||
|
defAttrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "sub_within_superscript_role";
|
||||||
|
defAttrs = { "text-position": "sub" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "sup_within_subscript_role";
|
||||||
|
defAttrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "sub_within_sup";
|
||||||
|
defAttrs = { "text-position": "sub" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "sup_within_sub";
|
||||||
|
defAttrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "css_sub_within_superscript_role";
|
||||||
|
attrs = { "text-position": "sub" };
|
||||||
|
testTextAttrs(ID, 0, attrs, {}, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "css_super_within_subscript_role";
|
||||||
|
attrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 0, attrs, {}, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "sub_with_superscript_role";
|
||||||
|
defAttrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
|
ID = "sup_with_subscript_role";
|
||||||
|
defAttrs = { "text-position": "sub" };
|
||||||
|
testTextAttrs(ID, 0, {}, defAttrs, 0, 11, true);
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,5 +803,21 @@
|
||||||
|
|
||||||
<p id="area20" style="font-size: 15pt;">offset test</p>
|
<p id="area20" style="font-size: 15pt;">offset test</p>
|
||||||
|
|
||||||
|
<!-- subscript, superscript tests -->
|
||||||
|
<sub id="sub_tag">offset test</sub>
|
||||||
|
<sup id="sup_tag">offset test</sup>
|
||||||
|
<p id="subscript_role" role="subscript">offset test</p>
|
||||||
|
<p id="superscript_role" role="superscript">offset test</p>
|
||||||
|
|
||||||
|
<div><span id="superscript_role_in_div" role="superscript">offset test</span></div>
|
||||||
|
<p role="superscript"><sub id="sub_within_superscript_role">offset test</sub></p>
|
||||||
|
<p role="subscript"><sup id="sup_within_subscript_role">offset test</sup></p>
|
||||||
|
<sup><sub id="sub_within_sup">offset test</sub></sup>
|
||||||
|
<sub><sup id="sup_within_sub">offset test</sup></sub>
|
||||||
|
<p id="css_sub_within_superscript_role" role="superscript"><span style="vertical-align: sub">offset test</span></p>
|
||||||
|
<p id="css_super_within_subscript_role" role="subscript"><span style="vertical-align: super">offset test</span></p>
|
||||||
|
<sub id="sub_with_superscript_role" role="superscript">offset test</sub>
|
||||||
|
<sup id="sup_with_subscript_role" role="subscript">offset test</sup>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче