Bug 1146257 - spanned headers don't work well in our table code, r=marcoz

This commit is contained in:
Alexander Surkov 2015-03-26 08:05:06 -04:00
parent be05901872
commit c9a7be251b
2 changed files with 229 additions and 24 deletions

View File

@ -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;
}

View File

@ -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 @@
</tbody>
</table>
<table id="table9" border="1">
<caption>
Example 1 (row group headers):
</caption>
<tr>
<td colspan="2"><span class="offscreen">empty</span></td>
<th id="t9_1km" width="40">1 km</th>
<th id="t9_5km" width="35">5 km</th>
<th id="t9_10km" width="42">10 km</th>
</tr>
<tr>
<th id="t9_females" width="56" rowspan="2">Females</th>
<th id="t9_mary" width="39">Mary</th>
<td id="t9_r1c1" headers="t9_females t9_mary t9_1km">8:32</td>
<td id="t9_r1c2" headers="t9_females t9_mary t9_5km">28:04</td>
<td id="t9_r1c3" headers="t9_females t9_mary t9_10km">1:01:16</td>
</tr>
<tr>
<th id="t9_betsy">Betsy</th>
<td id="t9_r2c1" headers="t9_females t9_betsy t9_1km">7:43</td>
<td id="t9_r2c2" headers="t9_females t9_betsy t9_5km">26:47</td>
<td id="t9_r2c3" headers="t9_females t9_betsy t9_10km">55:38</td>
</tr>
<tr>
<th id="t9_males" rowspan="2">Males</th>
<th id="t9_matt">Matt</th>
<td id="t9_r3c1" headers="t9_males t9_matt t9_1km">7:55</td>
<td id="t9_r3c2" headers="t9_males t9_matt t9_5km">27:29</td>
<td id="t9_r3c3" headers="t9_males t9_matt t9_10km">57:04</td>
</tr>
<tr>
<th id="t9_todd">Todd</th>
<td id="t9_r4c1" headers="t9_males t9_todd t9_1km">7:01</td>
<td id="t9_r4c2" headers="t9_males t9_todd t9_5km">24:21</td>
<td id="t9_r4c3" headers="t9_males t9_todd t9_10km">50:35</td>
</tr>
</table>
<table id="table10" border="1">
<caption>
Example 2 (column group headers):
</caption>
<tr>
<td rowspan="2"><span class="offscreen">empty</span></td>
<th colspan="2" id="t10_females">Females</th>
<th colspan="2" id="t10_males">Males</th>
</tr>
<tr>
<th width="40" id="t10_mary">Mary</th>
<th width="35" id="t10_betsy">Betsy</th>
<th width="42" id="t10_matt">Matt</th>
<th width="42" id="t10_todd">Todd</th>
</tr>
<tr>
<th width="39" id="t10_1km">1 km</th>
<td headers="t10_females t10_mary t10_1km" id="t10_r1c1">8:32</td>
<td headers="t10_females t10_betsy t10_1km" id="t10_r1c2">7:43</td>
<td headers="t10_males t10_matt t10_1km" id="t10_r1c3">7:55</td>
<td headers="t10_males t10_todd t10_1km" id="t10_r1c4">7:01</td>
</tr>
<tr>
<th id="t10_5km">5 km</th>
<td headers="t10_females t10_mary t10_5km" id="t10_r2c1">28:04</td>
<td headers="t10_females t10_betsy t10_5km" id="t10_r2c2">26:47</td>
<td headers="t10_males t10_matt t10_5km" id="t10_r2c3">27:29</td>
<td headers="t10_males t10_todd t10_5km" id="t10_r2c4">24:21</td>
</tr>
<tr>
<th id="t10_10km">10 km</th>
<td headers="t10_females t10_mary t10_10km" id="t10_r3c1">1:01:16</td>
<td headers="t10_females t10_betsy t10_10km" id="t10_r3c2">55:38</td>
<td headers="t10_males t10_matt t10_10km" id="t10_r3c3">57:04</td>
<td headers="t10_males t10_todd t10_10km" id="t10_r3c4">50:35</td>
</tr>
</table>
</body>
</html>