Bug 804040 - Selection event not fired when selection of ARIA tab changes, r=tbsaunde

This commit is contained in:
Alexander Surkov 2012-11-11 11:16:17 +09:00
parent 38de32d921
commit d3744bd61d
17 changed files with 132 additions and 71 deletions

View File

@ -7,6 +7,7 @@
#include "nsARIAMap.h"
#include "Accessible.h"
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "Role.h"
@ -19,6 +20,8 @@ using namespace mozilla;
using namespace mozilla::a11y;
using namespace mozilla::a11y::aria;
static const uint32_t kGenericAccType = 0;
/**
* This list of WAI-defined roles are currently hardcoded.
* Eventually we will most likely be loading an RDF resource that contains this information
@ -43,6 +46,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // alertdialog
@ -52,6 +56,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // application
@ -61,6 +66,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // article
@ -70,6 +76,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eReadonlyUntilEditable
},
@ -80,6 +87,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
ePressAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAPressed
},
@ -90,6 +98,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eCheckUncheckAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableMixed,
eARIAReadonly
@ -101,6 +110,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eSortAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable,
eARIAReadonly
@ -112,6 +122,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eOpenCloseAction,
eNoLiveAttr,
kGenericAccType,
states::COLLAPSED | states::HASPOPUP,
eARIAAutoComplete,
eARIAReadonly
@ -123,6 +134,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // directory
@ -132,6 +144,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // document
@ -141,6 +154,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eReadonlyUntilEditable
},
@ -151,6 +165,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // grid
@ -160,6 +175,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
Accessible::eSelectAccessible,
states::FOCUSABLE,
eARIAMultiSelectable,
eARIAReadonly
@ -171,6 +187,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable,
eARIAReadonly
@ -182,6 +199,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // heading
@ -191,6 +209,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // img
@ -200,6 +219,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // link
@ -209,6 +229,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eJumpAction,
eNoLiveAttr,
kGenericAccType,
states::LINKED
},
{ // list
@ -218,6 +239,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
states::READONLY
},
{ // listbox
@ -227,6 +249,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
Accessible::eSelectAccessible,
kNoReqStates,
eARIAMultiSelectable,
eARIAReadonly
@ -238,6 +261,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction, // XXX: should depend on state, parent accessible
eNoLiveAttr,
kGenericAccType,
states::READONLY
},
{ // log
@ -247,6 +271,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
ePoliteLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // marquee
@ -256,6 +281,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eOffLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // math
@ -265,6 +291,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // menu
@ -275,6 +302,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoAction, // XXX: technically accessibles of menupopup role haven't
// any action, but menu can be open or close.
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // menubar
@ -284,6 +312,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // menuitem
@ -293,6 +322,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eClickAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckedMixed
},
@ -303,6 +333,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eClickAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableMixed
},
@ -313,6 +344,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eClickAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableBool
},
@ -323,6 +355,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // option
@ -332,6 +365,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eSelectAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable,
eARIACheckedMixed
@ -343,6 +377,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // progressbar
@ -352,6 +387,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eHasValueMinMax,
eNoAction,
eNoLiveAttr,
kGenericAccType,
states::READONLY,
eIndeterminateIfNoValue
},
@ -362,6 +398,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eSelectAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIACheckableBool
},
@ -372,6 +409,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // region
@ -381,6 +419,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // row
@ -390,6 +429,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable
},
@ -400,6 +440,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eSortAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable,
eARIAReadonly
@ -411,6 +452,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eHasValueMinMax,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAOrientation,
eARIAReadonly
@ -422,6 +464,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAOrientation
},
@ -432,6 +475,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eHasValueMinMax,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAOrientation,
eARIAReadonly
@ -443,6 +487,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eHasValueMinMax,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAReadonly
},
@ -453,6 +498,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
ePoliteLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // tab
@ -462,6 +508,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eSwitchAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable
},
@ -472,6 +519,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
ePoliteLiveAttr,
Accessible::eSelectAccessible,
kNoReqStates
},
{ // tabpanel
@ -481,6 +529,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // textbox
@ -490,6 +539,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eActivateAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIAAutoComplete,
eARIAMultiline,
@ -511,6 +561,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // tooltip
@ -520,6 +571,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // tree
@ -529,6 +581,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
Accessible::eSelectAccessible,
kNoReqStates,
eARIAReadonly,
eARIAMultiSelectable
@ -540,6 +593,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eNoValue,
eNoAction,
eNoLiveAttr,
Accessible::eSelectAccessible,
kNoReqStates,
eARIAReadonly,
eARIAMultiSelectable
@ -552,6 +606,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eActivateAction, // XXX: should expose second 'expand/collapse' action based
// on states
eNoLiveAttr,
kGenericAccType,
kNoReqStates,
eARIASelectable,
eARIACheckedMixed
@ -565,6 +620,7 @@ static nsRoleMapEntry sLandmarkRoleMap = {
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
};
@ -575,6 +631,7 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
};

View File

@ -174,6 +174,9 @@ struct nsRoleMapEntry
// these object attributes if ARIA 'live' attribute is missed.
ELiveAttrRule liveAttRule;
// Accessible types this role belongs to.
uint32_t accTypes;
// Automatic state mapping rule: always include in nsIAccessibleStates
uint64_t state; // or kNoReqStates if no nsIAccessibleStates are automatic for this role.

View File

@ -5,6 +5,7 @@
#include "nsAccDocManager.h"
#include "Accessible-inl.h"
#include "ApplicationAccessible.h"
#include "DocAccessible-inl.h"
#include "nsAccessibilityService.h"

View File

@ -28,6 +28,14 @@ Accessible::ARIARole()
return ARIATransformRole(mRoleMapEntry->role);
}
inline void
Accessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
{
mRoleMapEntry = aRoleMapEntry;
if (mRoleMapEntry)
mFlags |= mRoleMapEntry->accTypes;
}
inline bool
Accessible::HasNumericValue() const
{

View File

@ -2731,20 +2731,6 @@ Accessible::AnchorURIAt(uint32_t aAnchorIndex)
////////////////////////////////////////////////////////////////////////////////
// SelectAccessible
bool
Accessible::IsSelect()
{
// If we have an ARIA role attribute present and the role allows multi
// selectable state, then we need to support SelectAccessible interface. If
// either attribute (role or multiselectable) change, then we'll destroy this
// accessible so that we can follow COM identity rules.
return mRoleMapEntry &&
(mRoleMapEntry->attributeMap1 == aria::eARIAMultiSelectable ||
mRoleMapEntry->attributeMap2 == aria::eARIAMultiSelectable ||
mRoleMapEntry->attributeMap3 == aria::eARIAMultiSelectable);
}
already_AddRefed<nsIArray>
Accessible::SelectedItems()
{

View File

@ -306,13 +306,8 @@ public:
/**
* Set the ARIA role map entry for a new accessible.
* For a newly created accessible, specify which role map entry should be used.
*
* @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or
* nullptr if none.
*/
void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
{ mRoleMapEntry = aRoleMapEntry; }
void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
/**
* Update the children cache.
@ -600,7 +595,7 @@ public:
* Return true if the accessible is a select control containing selectable
* items.
*/
virtual bool IsSelect();
bool IsSelect() const { return mFlags & eSelectAccessible; }
/**
* Return an array of selected items.
@ -777,6 +772,7 @@ protected:
eHasNumericValue = 1 << 6 // accessible has a numeric value
};
public: // XXX: a small hack to make these visible for nsARIAMap
/**
* Flags describing the type of this accessible.
* @note keep these flags in sync with ChildrenFlags and StateFlags
@ -797,11 +793,14 @@ protected:
eMenuPopupAccessible = 1 << 19,
eProgressAccessible = 1 << 20,
eRootAccessible = 1 << 21,
eTextLeafAccessible = 1 << 22,
eXULDeckAccessible = 1 << 23,
eXULTreeAccessible = 1 << 24
eSelectAccessible = 1 << 22,
eTextLeafAccessible = 1 << 23,
eXULDeckAccessible = 1 << 24,
eXULTreeAccessible = 1 << 25
};
protected:
//////////////////////////////////////////////////////////////////////////////
// Miscellaneous helpers

View File

@ -31,7 +31,7 @@ HTMLSelectListAccessible::
HTMLSelectListAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
mFlags |= eListControlAccessible;
mFlags |= eSelectAccessible | eListControlAccessible;
}
////////////////////////////////////////////////////////////////////////////////
@ -56,12 +56,6 @@ HTMLSelectListAccessible::NativeRole()
////////////////////////////////////////////////////////////////////////////////
// HTMLSelectListAccessible: SelectAccessible
bool
HTMLSelectListAccessible::IsSelect()
{
return true;
}
bool
HTMLSelectListAccessible::SelectAll()
{

View File

@ -43,7 +43,6 @@ public:
virtual uint64_t NativeState();
// SelectAccessible
virtual bool IsSelect();
virtual bool SelectAll();
virtual bool UnselectAll();

View File

@ -273,16 +273,11 @@ nsXFormsSelectableAccessible::
nsXFormsSelectableAccessible(nsIContent* aContent, DocAccessible* aDoc) :
nsXFormsEditableAccessible(aContent, aDoc), mIsSelect1Element(false)
{
mFlags |= eSelectAccessible;
mIsSelect1Element =
mContent->NodeInfo()->Equals(nsGkAtoms::select1);
}
bool
nsXFormsSelectableAccessible::IsSelect()
{
return true;
}
already_AddRefed<nsIArray>
nsXFormsSelectableAccessible::SelectedItems()
{

View File

@ -130,7 +130,6 @@ public:
nsXFormsSelectableAccessible(nsIContent* aContent, DocAccessible* aDoc);
// SelectAccessible
virtual bool IsSelect();
virtual already_AddRefed<nsIArray> SelectedItems();
virtual uint32_t SelectedItemCount();
virtual Accessible* GetSelectedItem(uint32_t aIndex);

View File

@ -440,6 +440,8 @@ XULMenupopupAccessible::
// May be the anonymous <menupopup> inside <menulist> (a combobox)
mSelectControl = do_QueryInterface(mContent->GetParent());
if (!mSelectControl)
mFlags &= ~eSelectAccessible;
}
uint64_t

View File

@ -31,6 +31,7 @@ XULSelectControlAccessible::
XULSelectControlAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
mFlags |= eSelectAccessible;
mSelectControl = do_QueryInterface(aContent);
}
@ -47,13 +48,6 @@ XULSelectControlAccessible::Shutdown()
////////////////////////////////////////////////////////////////////////////////
// XULSelectControlAccessible: SelectAccessible
bool
XULSelectControlAccessible::IsSelect()
{
return !!mSelectControl;
}
// Interface methods
already_AddRefed<nsIArray>
XULSelectControlAccessible::SelectedItems()
{

View File

@ -26,7 +26,6 @@ public:
virtual void Shutdown();
// SelectAccessible
virtual bool IsSelect();
virtual already_AddRefed<nsIArray> SelectedItems();
virtual uint32_t SelectedItemCount();
virtual Accessible* GetSelectedItem(uint32_t aIndex);

View File

@ -36,7 +36,7 @@ XULTreeAccessible::
XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
mFlags |= eXULTreeAccessible;
mFlags |= eSelectAccessible | eXULTreeAccessible;
mTree = nsCoreUtils::GetTreeBoxObject(aContent);
NS_ASSERTION(mTree, "Can't get mTree!\n");
@ -224,12 +224,6 @@ XULTreeAccessible::ChildAtPoint(int32_t aX, int32_t aY,
////////////////////////////////////////////////////////////////////////////////
// XULTreeAccessible: SelectAccessible
bool
XULTreeAccessible::IsSelect()
{
return true;
}
Accessible*
XULTreeAccessible::CurrentItem()
{

View File

@ -49,7 +49,6 @@ public:
virtual uint32_t ChildCount() const;
// SelectAccessible
virtual bool IsSelect();
virtual already_AddRefed<nsIArray> SelectedItems();
virtual uint32_t SelectedItemCount();
virtual Accessible* GetSelectedItem(uint32_t aIndex);

View File

@ -24,26 +24,26 @@
////////////////////////////////////////////////////////////////////////////
// Invokers
function selectTreeItem(aTreeID, aItemID)
function selectItem(aSelectID, aItemID)
{
this.treeNode = getNode(aTreeID);
this.selectNode = getNode(aSelectID);
this.itemNode = getNode(aItemID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION, aItemID)
];
this.invoke = function selectTreeItem_invoke() {
var itemNode = this.treeNode.querySelector("*[aria-selected='true']");
this.invoke = function selectItem_invoke() {
var itemNode = this.selectNode.querySelector("*[aria-selected='true']");
if (itemNode)
itemNode.removeAttribute("aria-selected", "true");
this.itemNode.setAttribute("aria-selected", "true");
}
this.getID = function selectTreeItem_getID()
this.getID = function selectItem_getID()
{
return "selectTreeItem " + prettyName(aItemID);
return "select item " + prettyName(aItemID);
}
}
@ -52,19 +52,22 @@
var gQueue = null;
//var gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new selectTreeItem("tree", "treeitem1"));
gQueue.push(new selectTreeItem("tree", "treeitem1a"));
gQueue.push(new selectTreeItem("tree", "treeitem1a1"));
gQueue.push(new selectItem("tablist", "tab1"));
gQueue.push(new selectItem("tablist", "tab2"));
gQueue.push(new selectTreeItem("tree2", "tree2item1"));
gQueue.push(new selectTreeItem("tree2", "tree2item1a"));
gQueue.push(new selectTreeItem("tree2", "tree2item1a1"));
gQueue.push(new selectItem("tree", "treeitem1"));
gQueue.push(new selectItem("tree", "treeitem1a"));
gQueue.push(new selectItem("tree", "treeitem1a1"));
gQueue.push(new selectItem("tree2", "tree2item1"));
gQueue.push(new selectItem("tree2", "tree2item1a"));
gQueue.push(new selectItem("tree2", "tree2item1a1"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -81,12 +84,22 @@
title="Make selection events async">
Mozilla Bug 569653
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=804040"
title="Selection event not fired when selection of ARIA tab changes">
Mozilla Bug 804040
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div role="tablist" id="tablist">
<div role="tab" id="tab1">tab1</div>
<div role="tab" id="tab2">tab2</div>
</div>
<div id="tree" role="tree">
<div id="treeitem1" role="treeitem">Canada
<div id="treeitem1a" role="treeitem">- Ontario

View File

@ -36,6 +36,15 @@
function doTest()
{
//////////////////////////////////////////////////////////////////////////
// role="tablist"
id = "tablist";
ok(isAccessible(id, [nsIAccessibleSelectable]),
"No selectable accessible for " + id);
testSelectableSelection(id, [ ]);
//////////////////////////////////////////////////////////////////////////
// role="listbox"
@ -117,22 +126,32 @@
href="https://bugzilla.mozilla.org/show_bug.cgi?id=530014"
title="ARIA single selectable widget should implement nsIAccessibleSelectable">
Mozilla Bug 530014
</a><br>
</a>
<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>
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=590176"
title="add pseudo SelectAccessible interface">
Mozilla Bug 590176
</a><br>
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=804040"
title="Selection event not fired when selection of ARIA tab changes">
Mozilla Bug 804040
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div role="tablist" id="tablist">
<div role="tab">tab1</div>
<div role="tab">tab2</div>
</div>
<div role="listbox" id="listbox1">
<div role="option">item1</div>
<div role="option">item2</div>