зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1316285 - Expose role and landmark role for HTML header and footer only if they are direct descendants of the body tag, section otherwise. r=eeejay
MozReview-Commit-ID: LbelxxgHlJ6 --HG-- extra : rebase_source : 6f4bbb7672cf70f15ae00abeaa41b3edc02a03f5
This commit is contained in:
Родитель
d0ef137841
Коммит
9998f9ab0d
|
@ -64,12 +64,12 @@ MARKUPMAP(form,
|
|||
roles::FORM)
|
||||
|
||||
MARKUPMAP(footer,
|
||||
New_HyperText,
|
||||
roles::FOOTER)
|
||||
New_HTMLHeaderOrFooter,
|
||||
0)
|
||||
|
||||
MARKUPMAP(header,
|
||||
New_HyperText,
|
||||
roles::HEADER)
|
||||
New_HTMLHeaderOrFooter,
|
||||
0)
|
||||
|
||||
MARKUPMAP(h1,
|
||||
New_HyperText,
|
||||
|
|
|
@ -161,6 +161,9 @@ static Accessible* New_HTMLFigcaption(nsIContent* aContent, Accessible* aContext
|
|||
static Accessible* New_HTMLFigure(nsIContent* aContent, Accessible* aContext)
|
||||
{ return new HTMLFigureAccessible(aContent, aContext->Document()); }
|
||||
|
||||
static Accessible* New_HTMLHeaderOrFooter(nsIContent* aContent, Accessible* aContext)
|
||||
{ return new HTMLHeaderOrFooterAccessible(aContent, aContext->Document()); }
|
||||
|
||||
static Accessible* New_HTMLLegend(nsIContent* aContent, Accessible* aContext)
|
||||
{ return new HTMLLegendAccessible(aContent, aContext->Document()); }
|
||||
|
||||
|
|
|
@ -1142,31 +1142,6 @@ HyperTextAccessible::LandmarkRole() const
|
|||
return nsGkAtoms::navigation;
|
||||
}
|
||||
|
||||
if (mContent->IsAnyOfHTMLElements(nsGkAtoms::header,
|
||||
nsGkAtoms::footer)) {
|
||||
// Only map header and footer if they are not descendants of an article
|
||||
// or section tag.
|
||||
nsIContent* parent = mContent->GetParent();
|
||||
while (parent) {
|
||||
if (parent->IsAnyOfHTMLElements(nsGkAtoms::article, nsGkAtoms::section)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
// No article or section elements found.
|
||||
if (!parent) {
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::header)) {
|
||||
return nsGkAtoms::banner;
|
||||
}
|
||||
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::footer)) {
|
||||
return nsGkAtoms::contentinfo;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::aside)) {
|
||||
return nsGkAtoms::complementary;
|
||||
}
|
||||
|
|
|
@ -202,3 +202,59 @@ HTMLSummaryAccessible::IsWidget() const
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLHeaderOrFooterAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(HTMLHeaderOrFooterAccessible, HyperTextAccessible)
|
||||
|
||||
role
|
||||
HTMLHeaderOrFooterAccessible::NativeRole()
|
||||
{
|
||||
// Only map header and footer if they are direct descendants of the body tag.
|
||||
// If other sectioning or sectioning root elements, they become sections.
|
||||
nsIContent* parent = mContent->GetParent();
|
||||
while (parent) {
|
||||
if (parent->IsAnyOfHTMLElements(nsGkAtoms::article, nsGkAtoms::aside,
|
||||
nsGkAtoms::nav, nsGkAtoms::section,
|
||||
nsGkAtoms::blockquote, nsGkAtoms::details,
|
||||
nsGkAtoms::dialog, nsGkAtoms::fieldset,
|
||||
nsGkAtoms::figure, nsGkAtoms::td)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
// No sectioning or sectioning root elements found.
|
||||
if (!parent) {
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::header)) {
|
||||
return roles::HEADER;
|
||||
}
|
||||
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::footer)) {
|
||||
return roles::FOOTER;
|
||||
}
|
||||
}
|
||||
|
||||
return roles::SECTION;
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
HTMLHeaderOrFooterAccessible::LandmarkRole() const
|
||||
{
|
||||
if (!HasOwnContent())
|
||||
return nullptr;
|
||||
|
||||
a11y::role r = const_cast<HTMLHeaderOrFooterAccessible*>(this)->Role();
|
||||
if (r == roles::HEADER) {
|
||||
return nsGkAtoms::banner;
|
||||
}
|
||||
|
||||
if (r == roles::FOOTER) {
|
||||
return nsGkAtoms::contentinfo;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,26 @@ public:
|
|||
virtual bool IsWidget() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for HTML header and footer elements.
|
||||
*/
|
||||
class HTMLHeaderOrFooterAccessible : public HyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
|
||||
HTMLHeaderOrFooterAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
HyperTextAccessibleWrap(aContent, aDoc) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// Accessible
|
||||
virtual nsIAtom* LandmarkRole() const override;
|
||||
virtual a11y::role NativeRole() override;
|
||||
|
||||
protected:
|
||||
virtual ~HTMLHeaderOrFooterAccessible() {}
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -524,12 +524,20 @@
|
|||
testElm("footer", obj);
|
||||
|
||||
obj = {
|
||||
role: ROLE_FOOTER,
|
||||
role: ROLE_SECTION,
|
||||
absentAttributes: { "xml-roles": "contentinfo" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ]
|
||||
};
|
||||
testElm("footer_in_article", obj);
|
||||
testElm("footer_in_aside", obj);
|
||||
testElm("footer_in_nav", obj);
|
||||
testElm("footer_in_section", obj);
|
||||
testElm("footer_in_blockquote", obj);
|
||||
testElm("footer_in_details", obj);
|
||||
testElm("footer_in_dialog", obj);
|
||||
testElm("footer_in_fieldset", obj);
|
||||
testElm("footer_in_figure", obj);
|
||||
testElm("footer_in_td", obj);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// HTML:form
|
||||
|
@ -609,12 +617,20 @@
|
|||
testElm("header", obj);
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADER,
|
||||
role: ROLE_SECTION,
|
||||
absentAttributes: { "xml-roles": "banner" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ]
|
||||
};
|
||||
testElm("header_in_article", obj);
|
||||
testElm("header_in_aside", obj);
|
||||
testElm("header_in_nav", obj);
|
||||
testElm("header_in_section", obj);
|
||||
testElm("header_in_blockquote", obj);
|
||||
testElm("header_in_details", obj);
|
||||
testElm("header_in_dialog", obj);
|
||||
testElm("header_in_fieldset", obj);
|
||||
testElm("header_in_figure", obj);
|
||||
testElm("header_in_td", obj);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// HTML:hr
|
||||
|
@ -1471,9 +1487,33 @@
|
|||
<article>
|
||||
<footer id="footer_in_article">Some copyright info</footer>
|
||||
</article>
|
||||
<aside>
|
||||
<footer id="footer_in_aside">Some copyright info</footer>
|
||||
</aside>
|
||||
<nav>
|
||||
<footer id="footer_in_nav">Some copyright info</footer>
|
||||
</nav>
|
||||
<section>
|
||||
<footer id="footer_in_section">Some copyright info</footer>
|
||||
</section>
|
||||
<blockquote>
|
||||
<footer id="footer_in_blockquote">Some copyright info</footer>
|
||||
</blockquote>
|
||||
<details open="true">
|
||||
<footer id="footer_in_details">Some copyright info</footer>
|
||||
</details>
|
||||
<dialog open="true">
|
||||
<footer id="footer_in_dialog">Some copyright info</footer>
|
||||
</dialog>
|
||||
<fieldset>
|
||||
<footer id="footer_in_fieldset">Some copyright info</footer>
|
||||
</fieldset>
|
||||
<figure>
|
||||
<footer id="footer_in_figure">Some copyright info</footer>
|
||||
</figure>
|
||||
<table><tr><td>
|
||||
<footer id="footer_in_td">Some copyright info</footer>
|
||||
</td></tr></table>
|
||||
|
||||
<form id="form"></form>
|
||||
|
||||
|
@ -1492,9 +1532,33 @@
|
|||
<article>
|
||||
<header id="header_in_article">Not logo</header>
|
||||
</article>
|
||||
<aside>
|
||||
<header id="header_in_aside">Not logo</header>
|
||||
</aside>
|
||||
<nav>
|
||||
<header id="header_in_nav">Not logo</header>
|
||||
</nav>
|
||||
<section>
|
||||
<header id="header_in_section">Not logo</header>
|
||||
</section>
|
||||
<blockquote>
|
||||
<header id="header_in_blockquote">Not logo</header>
|
||||
</blockquote>
|
||||
<details open="true">
|
||||
<header id="header_in_details">Not logo</header>
|
||||
</details>
|
||||
<dialog open="true">
|
||||
<header id="header_in_dialog">Not logo</header>
|
||||
</dialog>
|
||||
<fieldset>
|
||||
<header id="header_in_fieldset">Not logo</header>
|
||||
</fieldset>
|
||||
<figure>
|
||||
<header id="header_in_figure">Not logo</header>
|
||||
</figure>
|
||||
<table><tr><td>
|
||||
<header id="header_in_td">Not logo</header>
|
||||
</td></tr></table>
|
||||
|
||||
<hr id="hr">
|
||||
<p id="i_container">normal<i>italic</i></p>
|
||||
|
|
|
@ -47,34 +47,34 @@
|
|||
}, {
|
||||
accOrElmOrID: "article_header",
|
||||
expectedUtterance: [
|
||||
[{"string": "header"}, "a header within an article"],
|
||||
["a header within an article", {"string": "header"}]],
|
||||
["a header within an article"],
|
||||
["a header within an article"]],
|
||||
expectedBraille: [
|
||||
[{"string": "headerAbbr"}, "a header within an article"],
|
||||
["a header within an article", {"string": "headerAbbr"}]],
|
||||
["a header within an article"],
|
||||
["a header within an article"]],
|
||||
}, {
|
||||
accOrElmOrID: "article_footer",
|
||||
expectedUtterance: [
|
||||
[{"string": "footer"}, "a footer within an article"],
|
||||
["a footer within an article", {"string": "footer"}]],
|
||||
["a footer within an article"],
|
||||
["a footer within an article"]],
|
||||
expectedBraille: [
|
||||
[{"string": "footerAbbr"}, "a footer within an article"],
|
||||
["a footer within an article", {"string": "footerAbbr"}]]
|
||||
["a footer within an article"],
|
||||
["a footer within an article"]]
|
||||
}, {
|
||||
accOrElmOrID: "section_header",
|
||||
expectedUtterance: [[{"string": "header"}, "a header within a section"],
|
||||
["a header within a section", {"string": "header"}]],
|
||||
expectedUtterance: [["a header within a section"],
|
||||
["a header within a section"]],
|
||||
expectedBraille: [
|
||||
[{"string": "headerAbbr"}, "a header within a section"],
|
||||
["a header within a section", {"string": "headerAbbr"}]]
|
||||
["a header within a section"],
|
||||
["a header within a section"]]
|
||||
}, {
|
||||
accOrElmOrID: "section_footer",
|
||||
expectedUtterance: [
|
||||
[{"string": "footer"}, "a footer within a section"],
|
||||
["a footer within a section", {"string": "footer"}]],
|
||||
["a footer within a section"],
|
||||
["a footer within a section"]],
|
||||
expectedBraille: [
|
||||
[{"string": "footerAbbr"}, "a footer within a section"],
|
||||
["a footer within a section", {"string": "footerAbbr"}]]
|
||||
["a footer within a section"],
|
||||
["a footer within a section"]]
|
||||
}, {
|
||||
accOrElmOrID: "aside",
|
||||
expectedUtterance: [
|
||||
|
|
|
@ -32,9 +32,9 @@
|
|||
// Check that landmark elements get accessibles with styled overflow.
|
||||
testRole("section_overflow", ROLE_SECTION);
|
||||
testRole("nav_overflow", ROLE_SECTION);
|
||||
testRole("header_overflow", ROLE_HEADER);
|
||||
testRole("header_overflow", ROLE_SECTION);
|
||||
testRole("aside_overflow", ROLE_NOTE);
|
||||
testRole("footer_overflow", ROLE_FOOTER);
|
||||
testRole("footer_overflow", ROLE_SECTION);
|
||||
testRole("article_overflow", ROLE_ARTICLE);
|
||||
|
||||
// test html:div
|
||||
|
|
Загрузка…
Ссылка в новой задаче