diff --git a/accessible/generic/ARIAGridAccessible.cpp b/accessible/generic/ARIAGridAccessible.cpp
index 8473436362..56b97da9e3 100644
--- a/accessible/generic/ARIAGridAccessible.cpp
+++ b/accessible/generic/ARIAGridAccessible.cpp
@@ -646,8 +646,9 @@ GroupPos
ARIAGridCellAccessible::GroupPosition()
{
int32_t count = 0, index = 0;
- if (nsCoreUtils::GetUIntAttr(Table()->AsAccessible()->GetContent(),
- nsGkAtoms::aria_colcount, &count) &&
+ TableAccessible* table = Table();
+ if (table && nsCoreUtils::GetUIntAttr(table->AsAccessible()->GetContent(),
+ nsGkAtoms::aria_colcount, &count) &&
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) {
return GroupPos(0, index, count);
}
diff --git a/accessible/html/HTMLTableAccessible.cpp b/accessible/html/HTMLTableAccessible.cpp
index d14b48c9a4..ca391899a9 100644
--- a/accessible/html/HTMLTableAccessible.cpp
+++ b/accessible/html/HTMLTableAccessible.cpp
@@ -147,8 +147,9 @@ GroupPos
HTMLTableCellAccessible::GroupPosition()
{
int32_t count = 0, index = 0;
- if (nsCoreUtils::GetUIntAttr(Table()->AsAccessible()->GetContent(),
- nsGkAtoms::aria_colcount, &count) &&
+ TableAccessible* table = Table();
+ if (table && nsCoreUtils::GetUIntAttr(table->AsAccessible()->GetContent(),
+ nsGkAtoms::aria_colcount, &count) &&
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) {
return GroupPos(0, index, count);
}
@@ -312,46 +313,43 @@ HTMLTableHeaderCellAccessible::NativeRole()
{
// Check value of @scope attribute.
static nsIContent::AttrValuesArray scopeValues[] =
- {&nsGkAtoms::col, &nsGkAtoms::row, nullptr};
+ { &nsGkAtoms::col, &nsGkAtoms::colgroup,
+ &nsGkAtoms::row, &nsGkAtoms::rowgroup, nullptr };
int32_t valueIdx =
mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::scope,
scopeValues, eCaseMatters);
switch (valueIdx) {
case 0:
- return roles::COLUMNHEADER;
case 1:
+ return roles::COLUMNHEADER;
+ case 2:
+ case 3:
return roles::ROWHEADER;
}
- // Assume it's columnheader if there are headers in siblings, otherwise
- // rowheader.
- // This should iterate the flattened tree
- nsIContent* parentContent = mContent->GetParent();
- if (!parentContent) {
- NS_ERROR("Deattached content on alive accessible?");
+ TableAccessible* table = Table();
+ if (!table)
return roles::NOTHING;
- }
- for (nsIContent* siblingContent = mContent->GetPreviousSibling(); siblingContent;
- siblingContent = siblingContent->GetPreviousSibling()) {
- if (siblingContent->IsElement()) {
- return nsCoreUtils::IsHTMLTableHeader(siblingContent) ?
- roles::COLUMNHEADER : roles::ROWHEADER;
- }
- }
+ // If the cell next to this one is not a header cell then assume this cell is
+ // a row header for it.
+ uint32_t rowIdx = RowIdx(), colIdx = ColIdx();
+ Accessible* cell = table->CellAt(rowIdx, colIdx + ColExtent());
+ if (cell && !nsCoreUtils::IsHTMLTableHeader(cell->GetContent()))
+ return roles::ROWHEADER;
- for (nsIContent* siblingContent = mContent->GetNextSibling(); siblingContent;
- siblingContent = siblingContent->GetNextSibling()) {
- if (siblingContent->IsElement()) {
- return nsCoreUtils::IsHTMLTableHeader(siblingContent) ?
- roles::COLUMNHEADER : roles::ROWHEADER;
- }
- }
+ // If the cell below this one is not a header cell then assume this cell is
+ // a column header for it.
+ uint32_t rowExtent = RowExtent();
+ cell = table->CellAt(rowIdx + rowExtent, colIdx);
+ if (cell && !nsCoreUtils::IsHTMLTableHeader(cell->GetContent()))
+ return roles::COLUMNHEADER;
- // No elements in siblings what means the table has one column only. Therefore
- // it should be column header.
- return roles::COLUMNHEADER;
+ // Otherwise if this cell is surrounded by header cells only then make a guess
+ // based on its cell spanning. In other words if it is row spanned then assume
+ // it's a row header, otherwise it's a column header.
+ return rowExtent > 1 ? roles::ROWHEADER : roles::COLUMNHEADER;
}
@@ -376,8 +374,9 @@ GroupPos
HTMLTableRowAccessible::GroupPosition()
{
int32_t count = 0, index = 0;
- if (nsCoreUtils::GetUIntAttr(nsAccUtils::TableFor(this)->GetContent(),
- nsGkAtoms::aria_rowcount, &count) &&
+ Accessible* table = nsAccUtils::TableFor(this);
+ if (table && nsCoreUtils::GetUIntAttr(table->GetContent(),
+ nsGkAtoms::aria_rowcount, &count) &&
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) {
return GroupPos(0, index, count);
}
diff --git a/accessible/tests/mochitest/table/test_headers_table.html b/accessible/tests/mochitest/table/test_headers_table.html
index 99c36f837b..335849484a 100644
--- a/accessible/tests/mochitest/table/test_headers_table.html
+++ b/accessible/tests/mochitest/table/test_headers_table.html
@@ -156,6 +156,278 @@
testHeaderCells(headerInfoMap);
+ //////////////////////////////////////////////////////////////////////////
+ // @scope="rowgroup" and @scope="row"
+
+ headerInfoMap = [
+ {
+ cell: "t7_r1c1",
+ rowHeaderCells: [ "t7_Females", "t7_Mary" ],
+ columnHeaderCells: [ "t7_1km" ]
+ },
+ {
+ cell: "t7_r1c2",
+ rowHeaderCells: [ "t7_Females", "t7_Mary" ],
+ columnHeaderCells: [ "t7_5km" ]
+ },
+ {
+ cell: "t7_r1c3",
+ rowHeaderCells: [ "t7_Females", "t7_Mary" ],
+ columnHeaderCells: [ "t7_10km" ]
+ },
+ {
+ cell: "t7_r2c1",
+ rowHeaderCells: [ "t7_Females", "t7_Betsy" ],
+ columnHeaderCells: [ "t7_1km" ]
+ },
+ {
+ cell: "t7_r2c2",
+ rowHeaderCells: [ "t7_Females", "t7_Betsy" ],
+ columnHeaderCells: [ "t7_5km" ]
+ },
+ {
+ cell: "t7_r2c3",
+ rowHeaderCells: [ "t7_Females", "t7_Betsy" ],
+ columnHeaderCells: [ "t7_10km" ]
+ },
+ {
+ cell: "t7_r3c1",
+ rowHeaderCells: [ "t7_Males", "t7_Matt" ],
+ columnHeaderCells: [ "t7_1km" ]
+ },
+ {
+ cell: "t7_r3c2",
+ rowHeaderCells: [ "t7_Males", "t7_Matt" ],
+ columnHeaderCells: [ "t7_5km" ]
+ },
+ {
+ cell: "t7_r3c3",
+ rowHeaderCells: [ "t7_Males", "t7_Matt" ],
+ columnHeaderCells: [ "t7_10km" ]
+ },
+ {
+ cell: "t7_r4c1",
+ rowHeaderCells: [ "t7_Males", "t7_Todd" ],
+ columnHeaderCells: [ "t7_1km" ]
+ },
+ {
+ cell: "t7_r4c2",
+ rowHeaderCells: [ "t7_Males", "t7_Todd" ],
+ columnHeaderCells: [ "t7_5km" ]
+ },
+ {
+ cell: "t7_r4c3",
+ rowHeaderCells: [ "t7_Males", "t7_Todd" ],
+ columnHeaderCells: [ "t7_10km" ]
+ }
+ ];
+
+ testHeaderCells(headerInfoMap);
+
+ //////////////////////////////////////////////////////////////////////////
+ // @scope="colgroup" and @scope="col"
+
+ headerInfoMap = [
+ {
+ cell: "t8_r1c1",
+ rowHeaderCells: [ "t8_1km" ],
+ columnHeaderCells: [ "t7_Females", "t7_Mary" ]
+ },
+ {
+ cell: "t8_r1c2",
+ rowHeaderCells: [ "t8_5km" ],
+ columnHeaderCells: [ "t8_Females", "t8_Mary" ]
+ },
+ {
+ cell: "t8_r1c3",
+ rowHeaderCells: [ "t8_10km" ],
+ columnHeaderCells: [ "t8_Females", "t8_Mary" ]
+ },
+ {
+ cell: "t8_r1c4",
+ rowHeaderCells: [ "t8_1km" ],
+ columnHeaderCells: [ "t8_Females", "t8_Betsy" ]
+ },
+ {
+ cell: "t8_r2c1",
+ rowHeaderCells: [ "t8_5km" ],
+ columnHeaderCells: [ "t8_Females", "t8_Betsy" ]
+ },
+ {
+ cell: "t8_r2c2",
+ rowHeaderCells: [ "t8_10km" ],
+ columnHeaderCells: [ "t8_Females", "t8_Betsy" ]
+ },
+ {
+ cell: "t8_r2c3",
+ rowHeaderCells: [ "t8_1km" ],
+ columnHeaderCells: [ "t8_Males", "t8_Matt" ]
+ },
+ {
+ cell: "t8_r2c4",
+ rowHeaderCells: [ "t8_5km" ],
+ columnHeaderCells: [ "t8_Males", "t8_Matt" ]
+ },
+ {
+ cell: "t8_r3c1",
+ rowHeaderCells: [ "t8_10km" ],
+ columnHeaderCells: [ "t8_Males", "t8_Matt" ]
+ },
+ {
+ cell: "t8_r3c2",
+ rowHeaderCells: [ "t8_1km" ],
+ columnHeaderCells: [ "t8_Males", "t8_Todd" ]
+ },
+ {
+ cell: "t8_r3c3",
+ rowHeaderCells: [ "t8_5km" ],
+ columnHeaderCells: [ "t8_Males", "t8_Todd" ]
+ },
+ {
+ cell: "t8_r3c4",
+ rowHeaderCells: [ "t8_10km" ],
+ columnHeaderCells: [ "t8_Males", "t8_Todd" ]
+ }
+ ];
+
+ testHeaderCells(headerInfoMap);
+
+ //////////////////////////////////////////////////////////////////////////
+ // spanned table header cells (v1), @headers define header order
+
+ headerInfoMap = [
+ {
+ cell: "t9_r1c1",
+ rowHeaderCells: [ "t9_females", "t9_mary" ],
+ columnHeaderCells: [ "t9_1km" ]
+ },
+ {
+ cell: "t9_r1c2",
+ rowHeaderCells: [ "t9_females", "t9_mary" ],
+ columnHeaderCells: [ "t9_5km" ]
+ },
+ {
+ cell: "t9_r1c3",
+ rowHeaderCells: [ "t9_females", "t9_mary" ],
+ columnHeaderCells: [ "t9_10km" ]
+ },
+ {
+ cell: "t9_r2c1",
+ rowHeaderCells: [ "t9_females", "t9_betsy" ],
+ columnHeaderCells: [ "t9_1km" ]
+ },
+ {
+ cell: "t9_r2c2",
+ rowHeaderCells: [ "t9_females", "t9_betsy" ],
+ columnHeaderCells: [ "t9_5km" ]
+ },
+ {
+ cell: "t9_r2c3",
+ rowHeaderCells: [ "t9_females", "t9_betsy" ],
+ columnHeaderCells: [ "t9_10km" ]
+ },
+ {
+ cell: "t9_r3c1",
+ rowHeaderCells: [ "t9_males", "t9_matt" ],
+ columnHeaderCells: [ "t9_1km" ]
+ },
+ {
+ cell: "t9_r3c2",
+ rowHeaderCells: [ "t9_males", "t9_matt" ],
+ columnHeaderCells: [ "t9_5km" ]
+ },
+ {
+ cell: "t9_r3c3",
+ rowHeaderCells: [ "t9_males", "t9_matt" ],
+ columnHeaderCells: [ "t9_10km" ]
+ },
+ {
+ cell: "t9_r4c1",
+ rowHeaderCells: [ "t9_males", "t9_todd" ],
+ columnHeaderCells: [ "t9_1km" ]
+ },
+ {
+ cell: "t9_r4c2",
+ rowHeaderCells: [ "t9_males", "t9_todd" ],
+ columnHeaderCells: [ "t9_5km" ]
+ },
+ {
+ cell: "t9_r4c3",
+ rowHeaderCells: [ "t9_males", "t9_todd" ],
+ columnHeaderCells: [ "t9_10km" ]
+ }
+ ];
+
+ testHeaderCells(headerInfoMap);
+
+ //////////////////////////////////////////////////////////////////////////
+ // spanned table header cells (v2), @headers define header order
+
+ headerInfoMap = [
+ {
+ cell: "t10_r1c1",
+ rowHeaderCells: [ "t10_1km" ],
+ columnHeaderCells: [ "t10_females", "t10_mary" ]
+ },
+ {
+ cell: "t10_r1c2",
+ rowHeaderCells: [ "t10_1km" ],
+ columnHeaderCells: [ "t10_females", "t10_betsy" ]
+ },
+ {
+ cell: "t10_r1c3",
+ rowHeaderCells: [ "t10_1km" ],
+ columnHeaderCells: [ "t10_males", "t10_matt" ]
+ },
+ {
+ cell: "t10_r1c4",
+ rowHeaderCells: [ "t10_1km" ],
+ columnHeaderCells: [ "t10_males", "t10_todd" ]
+ },
+ {
+ cell: "t10_r2c1",
+ rowHeaderCells: [ "t10_5km" ],
+ columnHeaderCells: [ "t10_females", "t10_mary" ]
+ },
+ {
+ cell: "t10_r2c2",
+ rowHeaderCells: [ "t10_5km" ],
+ columnHeaderCells: [ "t10_females", "t10_betsy" ]
+ },
+ {
+ cell: "t10_r2c3",
+ rowHeaderCells: [ "t10_5km" ],
+ columnHeaderCells: [ "t10_males", "t10_matt" ]
+ },
+ {
+ cell: "t10_r2c4",
+ rowHeaderCells: [ "t10_5km" ],
+ columnHeaderCells: [ "t10_males", "t10_todd" ]
+ },
+ {
+ cell: "t10_r3c1",
+ rowHeaderCells: [ "t10_10km" ],
+ columnHeaderCells: [ "t10_females", "t10_mary" ]
+ },
+ {
+ cell: "t10_r3c2",
+ rowHeaderCells: [ "t10_10km" ],
+ columnHeaderCells: [ "t10_females", "t10_betsy" ]
+ },
+ {
+ cell: "t10_r3c3",
+ rowHeaderCells: [ "t10_10km" ],
+ columnHeaderCells: [ "t10_males", "t10_matt" ]
+ },
+ {
+ cell: "t10_r3c4",
+ rowHeaderCells: [ "t10_10km" ],
+ columnHeaderCells: [ "t10_males", "t10_todd" ]
+ }
+ ];
+
+ testHeaderCells(headerInfoMap);
+
SimpleTest.finish();
}
@@ -175,6 +447,11 @@
href="https://bugzilla.mozilla.org/show_bug.cgi?id=704465">
Bug 704465
+
+ Bug 1141978
+
@@ -275,5 +552,162 @@
cell |
+
+
+ Version 1 with rowgroup
+
+
+ | |
+ 1 km |
+ 5 km |
+ 10 km |
+
+
+
+
+ | Females |
+ Mary |
+ 8:32 |
+ 28:04 |
+ 1:01:16 |
+
+
+ | Betsy |
+ 7:43 |
+ 26:47 |
+ 55:38 |
+
+
+ | Males |
+ Matt |
+ 7:55 |
+ 27:29 |
+ 57:04 |
+
+
+ | Todd |
+ 7:01 |
+ 24:21 |
+ 50:35 |
+
+
+
+
+
+ Version 2 with colgroup
+
+
+ | |
+ Females |
+ Males |
+
+
+ | Mary |
+ Betsy |
+ Matt |
+ Todd |
+
+
+
+
+ | 1 km |
+ 8:32 |
+ 7:43 |
+ 7:55 |
+ 7:01 |
+
+
+ | 5 km |
+ 28:04 |
+ 26:47 |
+ 27:27 |
+ 24:21 |
+
+
+ | 10 km |
+ 1:01:16 |
+ 55:38 |
+ 57:04 |
+ 50:35 |
+
+
+
+
+
+
+
+ Example 1 (row group headers):
+
+
+ | empty |
+ 1 km |
+ 5 km |
+ 10 km |
+
+
+ | Females |
+ Mary |
+ 8:32 |
+ 28:04 |
+ 1:01:16 |
+
+
+ | Betsy |
+ 7:43 |
+ 26:47 |
+ 55:38 |
+
+
+ | Males |
+ Matt |
+ 7:55 |
+ 27:29 |
+ 57:04 |
+
+
+ | Todd |
+ 7:01 |
+ 24:21 |
+ 50:35 |
+
+
+
+
+
+ Example 2 (column group headers):
+
+
+ | empty |
+ Females |
+ Males |
+
+
+ | Mary |
+ Betsy |
+ Matt |
+ Todd |
+
+
+ | 1 km |
+ 8:32 |
+ 7:43 |
+ 7:55 |
+ 7:01 |
+
+
+ | 5 km |
+ 28:04 |
+ 26:47 |
+ 27:29 |
+ 24:21 |
+
+
+ | 10 km |
+ 1:01:16 |
+ 55:38 |
+ 57:04 |
+ 50:35 |
+
+