From 0ab3700bff90312bc8e40e64bda6d0d22ff21df5 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Thu, 26 Mar 2015 08:05:06 -0400 Subject: [PATCH] Bug 1146257 - spanned headers don't work well in our table code, r=marcoz --- accessible/html/HTMLTableAccessible.cpp | 42 ++-- .../mochitest/table/test_headers_table.html | 211 ++++++++++++++++++ 2 files changed, 229 insertions(+), 24 deletions(-) diff --git a/accessible/html/HTMLTableAccessible.cpp b/accessible/html/HTMLTableAccessible.cpp index 35a52c697c6f..4d44b76c7bf4 100644 --- a/accessible/html/HTMLTableAccessible.cpp +++ b/accessible/html/HTMLTableAccessible.cpp @@ -314,34 +314,28 @@ HTMLTableHeaderCellAccessible::NativeRole() 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; } diff --git a/accessible/tests/mochitest/table/test_headers_table.html b/accessible/tests/mochitest/table/test_headers_table.html index d81ff5f73d5d..26691fbfb68e 100644 --- a/accessible/tests/mochitest/table/test_headers_table.html +++ b/accessible/tests/mochitest/table/test_headers_table.html @@ -292,6 +292,142 @@ 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(); } @@ -498,5 +634,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Example 1 (row group headers): +
empty1 km5 km10 km
FemalesMary8:3228:041:01:16
Betsy7:4326:4755:38
MalesMatt7:5527:2957:04
Todd7:0124:2150:35
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Example 2 (column group headers): +
emptyFemalesMales
MaryBetsyMattTodd
1 km8:327:437:557:01
5 km28:0426:4727:2924:21
10 km1:01:1655:3857:0450:35