mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
566551 - ARIA grid and accessible selectable methods shouldn't use GetNextSibling, r=marcoz, sr=neil
This commit is contained in:
parent
4770823335
commit
d2b83f1189
@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1
|
||||
CPPSRCS = \
|
||||
nsAccessNode.cpp \
|
||||
nsAccEvent.cpp \
|
||||
nsAccIterator.cpp \
|
||||
nsARIAGridAccessible.cpp \
|
||||
nsARIAMap.cpp \
|
||||
nsDocAccessible.cpp \
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
#include "nsARIAGridAccessible.h"
|
||||
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsAccIterator.h"
|
||||
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -101,9 +101,13 @@ nsARIAGridAccessible::GetColumnCount(PRInt32 *acolumnCount)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row = GetNextRow();
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while ((cell = GetNextCellInRow(row, cell)))
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
nsAccessible *row = rowIter.GetNext();
|
||||
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
|
||||
while ((cell = cellIter.GetNext()))
|
||||
(*acolumnCount)++;
|
||||
|
||||
return NS_OK;
|
||||
@ -118,8 +122,8 @@ nsARIAGridAccessible::GetRowCount(PRInt32 *arowCount)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
while ((row = GetNextRow(row)))
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
while (rowIter.GetNext())
|
||||
(*arowCount)++;
|
||||
|
||||
return NS_OK;
|
||||
@ -135,10 +139,10 @@ nsARIAGridAccessible::GetCellAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row = GetRowAt(aRowIndex);
|
||||
nsAccessible *row = GetRowAt(aRowIndex);
|
||||
NS_ENSURE_ARG(row);
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumnIndex);
|
||||
nsAccessible *cell = GetCellInRowAt(row, aColumnIndex);
|
||||
NS_ENSURE_ARG(cell);
|
||||
|
||||
NS_ADDREF(*aAccessible = cell);
|
||||
@ -288,20 +292,21 @@ nsARIAGridAccessible::IsColumnSelected(PRInt32 aColumn, PRBool *aIsSelected)
|
||||
|
||||
NS_ENSURE_ARG(IsValidColumn(aColumn));
|
||||
|
||||
nsCOMPtr<nsIAccessible> row = GetNextRow();
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
nsAccessible *row = rowIter.GetNext();
|
||||
if (!row)
|
||||
return NS_OK;
|
||||
|
||||
do {
|
||||
if (!nsAccUtils::IsARIASelected(row)) {
|
||||
nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
|
||||
nsAccessible *cell = GetCellInRowAt(row, aColumn);
|
||||
if (!cell) // Do not fail due to wrong markup
|
||||
return NS_OK;
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(cell))
|
||||
return NS_OK;
|
||||
}
|
||||
} while ((row = GetNextRow(row)));
|
||||
} while ((row = rowIter.GetNext()));
|
||||
|
||||
*aIsSelected = PR_TRUE;
|
||||
return NS_OK;
|
||||
@ -316,12 +321,13 @@ nsARIAGridAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
|
||||
nsAccessible *row = GetRowAt(aRow);
|
||||
NS_ENSURE_ARG(row);
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(row)) {
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while ((cell = GetNextCellInRow(row, cell))) {
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
while ((cell = cellIter.GetNext())) {
|
||||
if (!nsAccUtils::IsARIASelected(cell))
|
||||
return NS_OK;
|
||||
}
|
||||
@ -341,11 +347,11 @@ nsARIAGridAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row(GetRowAt(aRow));
|
||||
nsAccessible *row = GetRowAt(aRow);
|
||||
NS_ENSURE_ARG(row);
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(row)) {
|
||||
nsCOMPtr<nsIAccessible> cell(GetCellInRowAt(row, aColumn));
|
||||
nsAccessible *cell = GetCellInRowAt(row, aColumn);
|
||||
NS_ENSURE_ARG(cell);
|
||||
|
||||
if (!nsAccUtils::IsARIASelected(cell))
|
||||
@ -367,16 +373,20 @@ nsARIAGridAccessible::GetSelectedCellCount(PRUint32* aCount)
|
||||
|
||||
PRInt32 colCount = 0;
|
||||
GetColumnCount(&colCount);
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
while ((row = GetNextRow(row))) {
|
||||
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
while ((row = rowIter.GetNext())) {
|
||||
if (nsAccUtils::IsARIASelected(row)) {
|
||||
(*aCount) += colCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while ((cell = GetNextCellInRow(row, cell))) {
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
|
||||
while ((cell = cellIter.GetNext())) {
|
||||
if (nsAccUtils::IsARIASelected(cell))
|
||||
(*aCount)++;
|
||||
}
|
||||
@ -400,14 +410,17 @@ nsARIAGridAccessible::GetSelectedRowCount(PRUint32* aCount)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
while ((row = GetNextRow(row))) {
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
while ((row = rowIter.GetNext())) {
|
||||
if (nsAccUtils::IsARIASelected(row)) {
|
||||
(*aCount)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell = GetNextCellInRow(row);
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = cellIter.GetNext();
|
||||
if (!cell)
|
||||
continue;
|
||||
|
||||
@ -417,7 +430,7 @@ nsARIAGridAccessible::GetSelectedRowCount(PRUint32* aCount)
|
||||
isRowSelected = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
} while ((cell = GetNextCellInRow(row, cell)));
|
||||
} while ((cell = cellIter.GetNext()));
|
||||
|
||||
if (isRowSelected)
|
||||
(*aCount)++;
|
||||
@ -440,18 +453,21 @@ nsARIAGridAccessible::GetSelectedCells(nsIArray **aCells)
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
while (row = GetNextRow(row)) {
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
while (row = rowIter.GetNext()) {
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsIAccessible *cell = nsnull;
|
||||
|
||||
if (nsAccUtils::IsARIASelected(row)) {
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while (cell = GetNextCellInRow(row, cell))
|
||||
while (cell = cellIter.GetNext())
|
||||
selCells->AppendElement(cell, PR_FALSE);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while (cell = GetNextCellInRow(row, cell)) {
|
||||
while (cell = cellIter.GetNext()) {
|
||||
if (nsAccUtils::IsARIASelected(cell))
|
||||
selCells->AppendElement(cell, PR_FALSE);
|
||||
}
|
||||
@ -481,8 +497,10 @@ nsARIAGridAccessible::GetSelectedCellIndices(PRUint32 *aCellsCount,
|
||||
|
||||
nsTArray<PRInt32> selCells(rowCount * colCount);
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
|
||||
if (nsAccUtils::IsARIASelected(row)) {
|
||||
for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++)
|
||||
selCells.AppendElement(rowIdx * colCount + colIdx);
|
||||
@ -490,8 +508,10 @@ nsARIAGridAccessible::GetSelectedCellIndices(PRUint32 *aCellsCount,
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
for (PRInt32 colIdx = 0; cell = GetNextCellInRow(row, cell); colIdx++) {
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
|
||||
for (PRInt32 colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
|
||||
if (nsAccUtils::IsARIASelected(cell))
|
||||
selCells.AppendElement(rowIdx * colCount + colIdx);
|
||||
}
|
||||
@ -537,14 +557,17 @@ nsARIAGridAccessible::GetSelectedRowIndices(PRUint32 *arowCount,
|
||||
|
||||
nsTArray<PRInt32> selRows(rowCount);
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
|
||||
if (nsAccUtils::IsARIASelected(row)) {
|
||||
selRows.AppendElement(rowIdx);
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell = GetNextCellInRow(row);
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = cellIter.GetNext();
|
||||
if (!cell)
|
||||
continue;
|
||||
|
||||
@ -554,7 +577,7 @@ nsARIAGridAccessible::GetSelectedRowIndices(PRUint32 *arowCount,
|
||||
isRowSelected = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
} while ((cell = GetNextCellInRow(row, cell)));
|
||||
} while ((cell = cellIter.GetNext()));
|
||||
|
||||
if (isRowSelected)
|
||||
selRows.AppendElement(rowIdx);
|
||||
@ -580,8 +603,10 @@ nsARIAGridAccessible::SelectRow(PRInt32 aRow)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
|
||||
nsresult rv = SetARIASelected(row, rowIdx == aRow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -597,14 +622,16 @@ nsARIAGridAccessible::SelectColumn(PRInt32 aColumn)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
while ((row = GetNextRow(row))) {
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
while ((row = rowIter.GetNext())) {
|
||||
// Unselect all cells in the row.
|
||||
nsresult rv = SetARIASelected(row, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Select cell at the column index.
|
||||
nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
|
||||
nsAccessible *cell = GetCellInRowAt(row, aColumn);
|
||||
if (cell) {
|
||||
rv = SetARIASelected(cell, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -620,7 +647,7 @@ nsARIAGridAccessible::UnselectRow(PRInt32 aRow)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
|
||||
nsAccessible *row = GetRowAt(aRow);
|
||||
NS_ENSURE_ARG(row);
|
||||
|
||||
return SetARIASelected(row, PR_FALSE);
|
||||
@ -634,9 +661,11 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
while ((row = GetNextRow(row))) {
|
||||
nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = nsnull;
|
||||
while ((row = rowIter.GetNext())) {
|
||||
nsAccessible *cell = GetCellInRowAt(row, aColumn);
|
||||
if (cell) {
|
||||
nsresult rv = SetARIASelected(cell, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -696,84 +725,39 @@ nsARIAGridAccessible::IsValidRowNColumn(PRInt32 aRow, PRInt32 aColumn)
|
||||
return aColumn < colCount;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsAccessible*
|
||||
nsARIAGridAccessible::GetRowAt(PRInt32 aRow)
|
||||
{
|
||||
PRInt32 rowIdx = aRow;
|
||||
nsCOMPtr<nsIAccessible> row(GetNextRow());
|
||||
while (rowIdx != 0 && (row = GetNextRow(row)))
|
||||
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
|
||||
nsAccessible *row = rowIter.GetNext();
|
||||
while (rowIdx != 0 && (row = rowIter.GetNext()))
|
||||
rowIdx--;
|
||||
|
||||
return row.forget();
|
||||
return row;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsARIAGridAccessible::GetCellInRowAt(nsIAccessible *aRow, PRInt32 aColumn)
|
||||
nsAccessible*
|
||||
nsARIAGridAccessible::GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn)
|
||||
{
|
||||
PRInt32 colIdx = aColumn;
|
||||
nsCOMPtr<nsIAccessible> cell(GetNextCellInRow(aRow));
|
||||
while (colIdx != 0 && (cell = GetNextCellInRow(aRow, cell)))
|
||||
|
||||
nsAccIterator cellIter(aRow, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = cellIter.GetNext();
|
||||
while (colIdx != 0 && (cell = cellIter.GetNext()))
|
||||
colIdx--;
|
||||
|
||||
return cell.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsARIAGridAccessible::GetNextRow(nsIAccessible *aRow)
|
||||
{
|
||||
nsCOMPtr<nsIAccessible> nextRow, tmpAcc;
|
||||
if (!aRow)
|
||||
GetFirstChild(getter_AddRefs(nextRow));
|
||||
else
|
||||
aRow->GetNextSibling(getter_AddRefs(nextRow));
|
||||
|
||||
while (nextRow) {
|
||||
if (nsAccUtils::Role(nextRow) == nsIAccessibleRole::ROLE_ROW)
|
||||
return nextRow.forget();
|
||||
|
||||
nextRow->GetNextSibling(getter_AddRefs(tmpAcc));
|
||||
tmpAcc.swap(nextRow);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsARIAGridAccessible::GetNextCellInRow(nsIAccessible *aRow, nsIAccessible *aCell)
|
||||
{
|
||||
if (!aRow)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessible> nextCell, tmpAcc;
|
||||
if (!aCell)
|
||||
aRow->GetFirstChild(getter_AddRefs(nextCell));
|
||||
else
|
||||
aCell->GetNextSibling(getter_AddRefs(nextCell));
|
||||
|
||||
while (nextCell) {
|
||||
PRUint32 role = nsAccUtils::Role(nextCell);
|
||||
if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
|
||||
role == nsIAccessibleRole::ROLE_ROWHEADER ||
|
||||
role == nsIAccessibleRole::ROLE_COLUMNHEADER)
|
||||
return nextCell.forget();
|
||||
|
||||
nextCell->GetNextSibling(getter_AddRefs(tmpAcc));
|
||||
tmpAcc.swap(nextCell);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
return cell;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsARIAGridAccessible::SetARIASelected(nsIAccessible *aAccessible,
|
||||
nsARIAGridAccessible::SetARIASelected(nsAccessible *aAccessible,
|
||||
PRBool aIsSelected, PRBool aNotify)
|
||||
{
|
||||
nsRefPtr<nsAccessible> acc = do_QueryObject(aAccessible);
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
acc->GetDOMNode(getter_AddRefs(node));
|
||||
NS_ENSURE_STATE(node);
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aAccessible->GetDOMNode()));
|
||||
NS_ENSURE_STATE(content);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (aIsSelected)
|
||||
@ -800,8 +784,10 @@ nsARIAGridAccessible::SetARIASelected(nsIAccessible *aAccessible,
|
||||
// If the given accessible is row that was unselected then remove
|
||||
// aria-selected from cell accessible.
|
||||
if (role == nsIAccessibleRole::ROLE_ROW) {
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while ((cell = GetNextCellInRow(aAccessible, cell))) {
|
||||
nsAccIterator cellIter(aAccessible, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
|
||||
while ((cell = cellIter.GetNext())) {
|
||||
rv = SetARIASelected(cell, PR_FALSE, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -814,16 +800,16 @@ nsARIAGridAccessible::SetARIASelected(nsIAccessible *aAccessible,
|
||||
if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
|
||||
role == nsIAccessibleRole::ROLE_ROWHEADER ||
|
||||
role == nsIAccessibleRole::ROLE_COLUMNHEADER) {
|
||||
nsCOMPtr<nsIAccessible> row;
|
||||
aAccessible->GetParent(getter_AddRefs(row));
|
||||
nsAccessible *row = aAccessible->GetParent();
|
||||
|
||||
if (nsAccUtils::Role(row) == nsIAccessibleRole::ROLE_ROW &&
|
||||
nsAccUtils::IsARIASelected(row)) {
|
||||
rv = SetARIASelected(row, PR_FALSE, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
while ((cell = GetNextCellInRow(row, cell))) {
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
while ((cell = cellIter.GetNext())) {
|
||||
if (cell != aAccessible) {
|
||||
rv = SetARIASelected(cell, PR_TRUE, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -847,7 +833,8 @@ nsARIAGridAccessible::GetSelectedColumnsArray(PRUint32 *acolumnCount,
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> row = GetNextRow();
|
||||
nsAccIterator rowIter(this, nsAccIterator::GetRow);
|
||||
nsAccessible *row = rowIter.GetNext();
|
||||
if (!row)
|
||||
return NS_OK;
|
||||
|
||||
@ -868,15 +855,17 @@ nsARIAGridAccessible::GetSelectedColumnsArray(PRUint32 *acolumnCount,
|
||||
continue;
|
||||
|
||||
PRInt32 colIdx = 0;
|
||||
nsCOMPtr<nsIAccessible> cell;
|
||||
for (colIdx = 0; cell = GetNextCellInRow(row, cell); colIdx++) {
|
||||
|
||||
nsAccIterator cellIter(row, nsAccIterator::GetCell);
|
||||
nsAccessible *cell = nsnull;
|
||||
for (colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
|
||||
if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) &&
|
||||
!nsAccUtils::IsARIASelected(cell)) {
|
||||
isColSelArray[colIdx] = PR_FALSE;
|
||||
selColCount--;
|
||||
}
|
||||
}
|
||||
} while ((row = GetNextRow(row)));
|
||||
} while ((row = rowIter.GetNext()));
|
||||
|
||||
if (!selColCount)
|
||||
return NS_OK;
|
||||
|
@ -77,31 +77,12 @@ protected:
|
||||
/**
|
||||
* Return row accessible at the given row index.
|
||||
*/
|
||||
already_AddRefed<nsIAccessible> GetRowAt(PRInt32 aRow);
|
||||
nsAccessible *GetRowAt(PRInt32 aRow);
|
||||
|
||||
/**
|
||||
* Return cell accessible at the given column index in the row.
|
||||
*/
|
||||
already_AddRefed<nsIAccessible> GetCellInRowAt(nsIAccessible *aRow,
|
||||
PRInt32 aColumn);
|
||||
|
||||
/**
|
||||
* Return next row accessible relative given row accessible or first row
|
||||
* accessible if it is null.
|
||||
*
|
||||
* @param aRow [in, optional] row accessible
|
||||
*/
|
||||
already_AddRefed<nsIAccessible> GetNextRow(nsIAccessible *aRow = nsnull);
|
||||
|
||||
/**
|
||||
* Return next cell accessible relative given cell accessible or first cell
|
||||
* in the given row accessible if given cell accessible is null.
|
||||
*
|
||||
* @param aRow [in] row accessible
|
||||
* @param aCell [in, optional] cell accessible
|
||||
*/
|
||||
already_AddRefed<nsIAccessible> GetNextCellInRow(nsIAccessible *aRow,
|
||||
nsIAccessible *aCell = nsnull);
|
||||
nsAccessible *GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn);
|
||||
|
||||
/**
|
||||
* Set aria-selected attribute value on DOM node of the given accessible.
|
||||
@ -111,7 +92,7 @@ protected:
|
||||
* @param aNotify [in, optional] specifies if DOM should be notified
|
||||
* about attribute change (used internally).
|
||||
*/
|
||||
nsresult SetARIASelected(nsIAccessible *aAccessible, PRBool aIsSelected,
|
||||
nsresult SetARIASelected(nsAccessible *aAccessible, PRBool aIsSelected,
|
||||
PRBool aNotify = PR_TRUE);
|
||||
|
||||
/**
|
||||
|
93
accessible/src/base/nsAccIterator.cpp
Normal file
93
accessible/src/base/nsAccIterator.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsAccIterator.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccIterator
|
||||
|
||||
nsAccIterator::nsAccIterator(nsAccessible *aAccessible,
|
||||
AccIteratorFilterFuncPtr aFilterFunc,
|
||||
IterationType aIterationType) :
|
||||
mFilterFunc(aFilterFunc), mIsDeep(aIterationType != eFlatNav)
|
||||
{
|
||||
mState = new IteratorState(aAccessible);
|
||||
}
|
||||
|
||||
nsAccIterator::~nsAccIterator()
|
||||
{
|
||||
while (mState) {
|
||||
IteratorState *tmp = mState;
|
||||
mState = tmp->mParentState;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccIterator::GetNext()
|
||||
{
|
||||
while (mState) {
|
||||
nsAccessible *child = mState->mParent->GetChildAt(mState->mIndex++);
|
||||
if (!child) {
|
||||
IteratorState *tmp = mState;
|
||||
mState = mState->mParentState;
|
||||
delete tmp;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
PRBool isComplying = mFilterFunc(child);
|
||||
if (isComplying)
|
||||
return child;
|
||||
|
||||
if (mIsDeep) {
|
||||
IteratorState *childState = new IteratorState(child, mState);
|
||||
mState = childState;
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccIterator::IteratorState
|
||||
|
||||
nsAccIterator::IteratorState::IteratorState(nsAccessible *aParent,
|
||||
IteratorState *mParentState) :
|
||||
mParent(aParent), mIndex(0), mParentState(mParentState)
|
||||
{
|
||||
}
|
124
accessible/src/base/nsAccIterator.h
Normal file
124
accessible/src/base/nsAccIterator.h
Normal file
@ -0,0 +1,124 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsAccIterator_h_
|
||||
#define nsAccIterator_h_
|
||||
|
||||
#include "nsAccessible.h"
|
||||
#include "nsAccUtils.h"
|
||||
|
||||
/**
|
||||
* Return true if the traversed accessible complies with filter.
|
||||
*/
|
||||
typedef PRBool (*AccIteratorFilterFuncPtr) (nsAccessible *);
|
||||
|
||||
/**
|
||||
* Allows to iterate through accessible children or subtree complying with
|
||||
* filter function.
|
||||
*/
|
||||
class nsAccIterator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Used to define iteration type.
|
||||
*/
|
||||
enum IterationType {
|
||||
/**
|
||||
* Navigation happens through direct children.
|
||||
*/
|
||||
eFlatNav,
|
||||
|
||||
/**
|
||||
* Navigation through subtree excluding iterator root; if the accessible
|
||||
* complies with filter, iterator ignores its children.
|
||||
*/
|
||||
eTreeNav
|
||||
};
|
||||
|
||||
nsAccIterator(nsAccessible *aRoot, AccIteratorFilterFuncPtr aFilterFunc,
|
||||
IterationType aIterationType = eFlatNav);
|
||||
~nsAccIterator();
|
||||
|
||||
/**
|
||||
* Return next accessible complying with filter function. Return the first
|
||||
* accessible for the first time.
|
||||
*/
|
||||
nsAccessible *GetNext();
|
||||
|
||||
/**
|
||||
* Predefined filters.
|
||||
*/
|
||||
static PRBool GetSelected(nsAccessible *aAccessible)
|
||||
{
|
||||
return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTED;
|
||||
}
|
||||
static PRBool GetSelectable(nsAccessible *aAccessible)
|
||||
{
|
||||
return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTABLE;
|
||||
}
|
||||
static PRBool GetRow(nsAccessible *aAccessible)
|
||||
{
|
||||
return nsAccUtils::Role(aAccessible) == nsIAccessibleRole::ROLE_ROW;
|
||||
}
|
||||
static PRBool GetCell(nsAccessible *aAccessible)
|
||||
{
|
||||
PRUint32 role = nsAccUtils::Role(aAccessible);
|
||||
return role == nsIAccessibleRole::ROLE_GRID_CELL ||
|
||||
role == nsIAccessibleRole::ROLE_ROWHEADER ||
|
||||
role == nsIAccessibleRole::ROLE_COLUMNHEADER;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAccIterator();
|
||||
nsAccIterator(const nsAccIterator&);
|
||||
nsAccIterator& operator =(const nsAccIterator&);
|
||||
|
||||
struct IteratorState
|
||||
{
|
||||
IteratorState(nsAccessible *aParent, IteratorState *mParentState = nsnull);
|
||||
|
||||
nsAccessible *mParent;
|
||||
PRInt32 mIndex;
|
||||
IteratorState *mParentState;
|
||||
};
|
||||
|
||||
AccIteratorFilterFuncPtr mFilterFunc;
|
||||
PRBool mIsDeep;
|
||||
IteratorState *mState;
|
||||
};
|
||||
|
||||
#endif
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "nsIXBLAccessible.h"
|
||||
|
||||
#include "nsAccIterator.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "nsDocAccessible.h"
|
||||
@ -2466,39 +2467,6 @@ nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
|
||||
nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsAccessible::GetNextWithState(nsIAccessible *aStart, PRUint32 matchState)
|
||||
{
|
||||
// Return the next descendant that matches one of the states in matchState
|
||||
// Uses depth first search
|
||||
NS_ASSERTION(matchState, "GetNextWithState() not called with a state to match");
|
||||
NS_ASSERTION(aStart, "GetNextWithState() not called with an accessible to start with");
|
||||
nsCOMPtr<nsIAccessible> look, current = aStart;
|
||||
PRUint32 state = 0;
|
||||
while (0 == (state & matchState)) {
|
||||
current->GetFirstChild(getter_AddRefs(look));
|
||||
while (!look) {
|
||||
if (current == this) {
|
||||
return nsnull; // At top of subtree
|
||||
}
|
||||
current->GetNextSibling(getter_AddRefs(look));
|
||||
if (!look) {
|
||||
current->GetParent(getter_AddRefs(look));
|
||||
current = look;
|
||||
look = nsnull;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
current.swap(look);
|
||||
state = nsAccUtils::State(current);
|
||||
}
|
||||
|
||||
nsIAccessible *returnAccessible = nsnull;
|
||||
current.swap(returnAccessible);
|
||||
|
||||
return returnAccessible;
|
||||
}
|
||||
|
||||
// nsIAccessibleSelectable
|
||||
NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles)
|
||||
{
|
||||
@ -2508,10 +2476,10 @@ NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles)
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
NS_ENSURE_STATE(selectedAccessibles);
|
||||
|
||||
nsCOMPtr<nsIAccessible> selected = this;
|
||||
while ((selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
|
||||
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
|
||||
nsIAccessible *selected = nsnull;
|
||||
while ((selected = iter.GetNext()))
|
||||
selectedAccessibles->AppendElement(selected, PR_FALSE);
|
||||
}
|
||||
|
||||
PRUint32 length = 0;
|
||||
selectedAccessibles->GetLength(&length);
|
||||
@ -2526,16 +2494,22 @@ NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles)
|
||||
// return the nth selected descendant nsIAccessible object
|
||||
NS_IMETHODIMP nsAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aSelected)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSelected);
|
||||
*aSelected = nsnull;
|
||||
|
||||
if (aIndex < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsCOMPtr<nsIAccessible> selected = this;
|
||||
|
||||
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
|
||||
nsAccessible *selected = nsnull;
|
||||
|
||||
PRInt32 count = 0;
|
||||
while (count ++ <= aIndex) {
|
||||
selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED);
|
||||
selected = iter.GetNext();
|
||||
if (!selected) {
|
||||
return NS_ERROR_FAILURE; // aIndex out of range
|
||||
// The index is out of range.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
NS_IF_ADDREF(*aSelected = selected);
|
||||
@ -2544,11 +2518,13 @@ NS_IMETHODIMP nsAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aSelect
|
||||
|
||||
NS_IMETHODIMP nsAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSelectionCount);
|
||||
*aSelectionCount = 0;
|
||||
nsCOMPtr<nsIAccessible> selected = this;
|
||||
while ((selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
|
||||
++ *aSelectionCount;
|
||||
}
|
||||
|
||||
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
|
||||
nsAccessible *selected = nsnull;
|
||||
while ((selected = iter.GetNext()))
|
||||
++(*aSelectionCount);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2604,21 +2580,24 @@ NS_IMETHODIMP nsAccessible::IsChildSelected(PRInt32 aIndex, PRBool *aIsSelected)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessible::ClearSelection()
|
||||
NS_IMETHODIMP
|
||||
nsAccessible::ClearSelection()
|
||||
{
|
||||
nsCOMPtr<nsIAccessible> selected = this;
|
||||
while ((selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
|
||||
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
|
||||
nsAccessible *selected = nsnull;
|
||||
while ((selected = iter.GetNext()))
|
||||
selected->SetSelected(PR_FALSE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAccessible::SelectAllSelection(PRBool *_retval)
|
||||
{
|
||||
nsCOMPtr<nsIAccessible> selectable = this;
|
||||
while ((selectable = GetNextWithState(selectable, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
|
||||
nsAccIterator iter(this, nsAccIterator::GetSelectable, nsAccIterator::eTreeNav);
|
||||
nsAccessible *selectable = nsnull;
|
||||
while((selectable = iter.GetNext()))
|
||||
selectable->SetSelected(PR_TRUE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -325,8 +325,6 @@ protected:
|
||||
// helper method to verify frames
|
||||
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
|
||||
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
|
||||
|
||||
already_AddRefed<nsIAccessible> GetNextWithState(nsIAccessible *aStart, PRUint32 matchState);
|
||||
|
||||
/**
|
||||
* Return an accessible for the given DOM node, or if that node isn't
|
||||
|
@ -68,6 +68,7 @@ _TEST_FILES =\
|
||||
nsIAccessible_selects.js \
|
||||
relations.js \
|
||||
role.js \
|
||||
selectable.js \
|
||||
states.js \
|
||||
table.js \
|
||||
value.js \
|
||||
|
36
accessible/tests/mochitest/selectable.js
Normal file
36
accessible/tests/mochitest/selectable.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Test selection getter methods of nsIAccessibleSelectable.
|
||||
*
|
||||
* @param aIdentifier [in] selectable container accessible
|
||||
* @param aSelectedChildren [in] array of selected children
|
||||
*/
|
||||
function testSelectableSelection(aIdentifier, aSelectedChildren)
|
||||
{
|
||||
var acc = getAccessible(aIdentifier, [nsIAccessibleSelectable]);
|
||||
if (!acc)
|
||||
return;
|
||||
|
||||
var len = aSelectedChildren.length;
|
||||
|
||||
// getSelectedChildren
|
||||
var selectedChildren = acc.GetSelectedChildren();
|
||||
is(selectedChildren ? selectedChildren.length : 0, aSelectedChildren.length,
|
||||
"getSelectedChildren: wrong selected children count for " + prettyName(aIdentifier));
|
||||
|
||||
for (var idx = 0; idx < len; idx++) {
|
||||
var expectedAcc = getAccessible(aSelectedChildren[idx]);
|
||||
is(selectedChildren.queryElementAt(idx, nsIAccessible), expectedAcc,
|
||||
"getSelectedChildren: wrong selected child at index " + idx + " for " + prettyName(aIdentifier));
|
||||
}
|
||||
|
||||
// selectionCount
|
||||
is(acc.selectionCount, aSelectedChildren.length,
|
||||
"selectionCount: wrong selected children count for " + prettyName(aIdentifier));
|
||||
|
||||
// refSelection
|
||||
for (var idx = 0; idx < len; idx++) {
|
||||
var expectedAcc = getAccessible(aSelectedChildren[idx]);
|
||||
is(acc.refSelection(idx), expectedAcc,
|
||||
"refSelection: wrong selected child at index " + idx + " for " + prettyName(aIdentifier));
|
||||
}
|
||||
}
|
@ -17,8 +17,23 @@
|
||||
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/a11y/accessible/role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/a11y/accessible/selectable.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function testSelectable(aID, aSelectableChildren)
|
||||
{
|
||||
var acc = getAccessible(aID, [nsIAccessibleSelectable]);
|
||||
|
||||
testSelectableSelection(acc, []);
|
||||
|
||||
acc.selectAllSelection();
|
||||
testSelectableSelection(acc, aSelectableChildren);
|
||||
|
||||
acc.clearSelection();
|
||||
testSelectableSelection(acc, []);
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var id = "list1";
|
||||
@ -45,6 +60,11 @@
|
||||
ok(isAccessible(id, [nsIAccessibleSelectable]),
|
||||
"No selectable accessible for " + id);
|
||||
|
||||
// Test selection methods for selectable children in subtree.
|
||||
testSelectable("grid2",
|
||||
["grid2_colhead1", "grid2_colhead2", "grid2_colhead3",
|
||||
"grid2_rowhead", "grid2_cell1", "grid2_cell2"]);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -61,6 +81,11 @@
|
||||
title="ARIA single selectable widget should implement nsIAccessibleSelectable">
|
||||
Mozilla Bug 530014
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=566551"
|
||||
title="ARIA grid and accessible selectable methods shouldn't use GetNextSibling">
|
||||
Mozilla Bug 566551
|
||||
</a><br>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -116,5 +141,29 @@
|
||||
<span role="gridcell">cell</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table tabindex="0" border="2" cellspacing="0" id="grid2" role="grid"
|
||||
aria-multiselectable="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th tabindex="-1" role="columnheader" id="grid2_colhead1"
|
||||
style="width:6em">Entry #</th>
|
||||
<th tabindex="-1" role="columnheader" id="grid2_colhead2"
|
||||
style="width:10em">Date</th>
|
||||
<th tabindex="-1" role="columnheader" id="grid2_colhead3"
|
||||
style="width:20em">Expense</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td tabindex="-1" role="rowheader" id="grid2_rowhead"
|
||||
aria-readonly="true">1</td>
|
||||
<td tabindex="-1" role="gridcell" id="grid2_cell1"
|
||||
aria-selected="false">03/14/05</td>
|
||||
<td tabindex="-1" role="gridcell" id="grid2_cell2"
|
||||
aria-selected="false">Conference Fee</td>
|
||||
</tr>
|
||||
</tobdy>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user