mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 345780 - Support multiple targets for same relation, r=davidb, r=MarcoZ, sr=neil
This commit is contained in:
parent
ce48d2a2db
commit
30549e95c1
@ -58,7 +58,7 @@ interface nsIAccessibleRelation;
|
||||
*
|
||||
* @status UNDER_REVIEW
|
||||
*/
|
||||
[scriptable, uuid(670fc322-14ec-4f3b-8279-9d62ab8895c0)]
|
||||
[scriptable, uuid(76c72c70-2c4b-4fce-8e75-b121db024333)]
|
||||
interface nsIAccessible : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -251,10 +251,10 @@ interface nsIAccessible : nsISupports
|
||||
nsIAccessible getAccessibleBelow();
|
||||
|
||||
/**
|
||||
* Return accessible related to this one by the given relation type (see.
|
||||
* Return accessible relation by the given relation type (see.
|
||||
* constants defined in nsIAccessibleRelation).
|
||||
*/
|
||||
nsIAccessible getAccessibleRelated(in unsigned long aRelationType);
|
||||
nsIAccessibleRelation getRelationByType(in unsigned long aRelationType);
|
||||
|
||||
/**
|
||||
* Returns the number of accessible relations for this object.
|
||||
|
@ -1053,7 +1053,6 @@ refRelationSetCB(AtkObject *aAtkObj)
|
||||
return relation_set;
|
||||
}
|
||||
|
||||
AtkObject *accessible_array[1];
|
||||
AtkRelation* relation;
|
||||
|
||||
PRUint32 relationType[] = {nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
@ -1074,14 +1073,28 @@ refRelationSetCB(AtkObject *aAtkObj)
|
||||
atk_relation_set_remove(relation_set, relation);
|
||||
}
|
||||
|
||||
nsIAccessible* accRelated;
|
||||
nsresult rv = accWrap->GetAccessibleRelated(relationType[i], &accRelated);
|
||||
if (NS_SUCCEEDED(rv) && accRelated) {
|
||||
accessible_array[0] = nsAccessibleWrap::GetAtkObject(accRelated);
|
||||
relation = atk_relation_new(accessible_array, 1,
|
||||
static_cast<AtkRelationType>(relationType[i]));
|
||||
atk_relation_set_add(relation_set, relation);
|
||||
g_object_unref(relation);
|
||||
nsCOMPtr<nsIAccessibleRelation> geckoRelation;
|
||||
nsresult rv = accWrap->GetRelationByType(relationType[i],
|
||||
getter_AddRefs(geckoRelation));
|
||||
if (NS_SUCCEEDED(rv) && geckoRelation) {
|
||||
PRUint32 targetsCount = 0;
|
||||
geckoRelation->GetTargetsCount(&targetsCount);
|
||||
if (targetsCount) {
|
||||
AtkObject** accessible_array = new AtkObject*[targetsCount];
|
||||
for (PRUint32 index = 0; index < targetsCount; index++) {
|
||||
nsCOMPtr<nsIAccessible> geckoTarget;
|
||||
geckoRelation->GetTarget(index, getter_AddRefs(geckoTarget));
|
||||
accessible_array[index] =
|
||||
nsAccessibleWrap::GetAtkObject(geckoTarget);
|
||||
}
|
||||
|
||||
relation = atk_relation_new(accessible_array, targetsCount,
|
||||
static_cast<AtkRelationType>(relationType[i]));
|
||||
atk_relation_set_add(relation_set, relation);
|
||||
g_object_unref(relation);
|
||||
|
||||
delete [] accessible_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@ CPPSRCS = \
|
||||
nsCoreUtils.cpp \
|
||||
nsAccUtils.cpp \
|
||||
nsNameUtils.cpp \
|
||||
nsRelUtils.cpp \
|
||||
nsAccessibilityService.cpp \
|
||||
nsAccessible.cpp \
|
||||
nsAccessibleRelation.cpp \
|
||||
|
@ -84,6 +84,7 @@
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
@ -1701,48 +1702,35 @@ nsresult nsAccessible::GetTextFromRelationID(nsIAtom *aIDProperty, nsString &aNa
|
||||
// Get DHTML name from content subtree pointed to by ID attribute
|
||||
aName.Truncate();
|
||||
NS_ASSERTION(mDOMNode, "Called from shutdown accessible");
|
||||
|
||||
nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode);
|
||||
if (!content)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString ids;
|
||||
if (!content->GetAttr(kNameSpaceID_None, aIDProperty, ids))
|
||||
nsCOMPtr<nsIArray> refElms;
|
||||
nsCoreUtils::GetElementsByIDRefsAttr(content, aIDProperty,
|
||||
getter_AddRefs(refElms));
|
||||
|
||||
if (!refElms)
|
||||
return NS_OK;
|
||||
|
||||
ids.CompressWhitespace(PR_TRUE, PR_TRUE);
|
||||
PRUint32 count = 0;
|
||||
nsresult rv = refElms->GetLength(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(content->GetOwnerDoc());
|
||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIContent> refContent;
|
||||
for (PRUint32 idx = 0; idx < count; idx++) {
|
||||
refContent = do_QueryElementAt(refElms, idx, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Support idlist as in aria-labelledby="id1 id2 id3"
|
||||
while (!ids.IsEmpty()) {
|
||||
nsAutoString id;
|
||||
PRInt32 idLength = ids.FindChar(' ');
|
||||
NS_ASSERTION(idLength != 0, "Should not be 0 because of CompressWhitespace() call above");
|
||||
if (idLength == kNotFound) {
|
||||
id = ids;
|
||||
ids.Truncate();
|
||||
} else {
|
||||
id = Substring(ids, 0, idLength);
|
||||
ids.Cut(0, idLength + 1);
|
||||
}
|
||||
|
||||
if (!aName.IsEmpty()) {
|
||||
if (!aName.IsEmpty())
|
||||
aName += ' '; // Need whitespace between multiple labels or descriptions
|
||||
}
|
||||
nsCOMPtr<nsIDOMElement> labelElement;
|
||||
domDoc->GetElementById(id, getter_AddRefs(labelElement));
|
||||
content = do_QueryInterface(labelElement);
|
||||
if (!content) {
|
||||
return NS_OK;
|
||||
}
|
||||
// We have a label content
|
||||
nsresult rv = AppendFlatStringFromSubtree(content, &aName);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aName.CompressWhitespace();
|
||||
}
|
||||
|
||||
rv = AppendFlatStringFromSubtree(refContent, &aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
||||
aName.CompressWhitespace();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1922,7 +1910,8 @@ NS_IMETHODIMP nsAccessible::GetFinalRole(PRUint32 *aRole)
|
||||
*aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
|
||||
}
|
||||
else { // Check to see if combo owns the listbox instead
|
||||
GetAccessibleRelated(nsIAccessibleRelation::RELATION_NODE_CHILD_OF, getter_AddRefs(possibleCombo));
|
||||
possibleCombo = nsRelUtils::
|
||||
GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_NODE_CHILD_OF);
|
||||
if (nsAccUtils::Role(possibleCombo) == nsIAccessibleRole::ROLE_COMBOBOX)
|
||||
*aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
|
||||
}
|
||||
@ -2228,10 +2217,8 @@ nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
} else {
|
||||
// Expose 'selected' state on ARIA tab if the focus is on internal element
|
||||
// of related tabpanel.
|
||||
nsCOMPtr<nsIAccessible> tabPanel;
|
||||
rv = GetAccessibleRelated(nsIAccessibleRelation::RELATION_LABEL_FOR,
|
||||
getter_AddRefs(tabPanel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIAccessible> tabPanel = nsRelUtils::
|
||||
GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_LABEL_FOR);
|
||||
|
||||
if (nsAccUtils::Role(tabPanel) == nsIAccessibleRole::ROLE_PROPERTYPAGE) {
|
||||
nsCOMPtr<nsIAccessNode> tabPanelAccessNode(do_QueryInterface(tabPanel));
|
||||
@ -2705,78 +2692,119 @@ nsIDOMNode* nsAccessible::GetAtomicRegion()
|
||||
return atomicRegion;
|
||||
}
|
||||
|
||||
/* nsIAccessible getAccessibleRelated(); */
|
||||
NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated)
|
||||
// nsIAccessible getRelationByType()
|
||||
NS_IMETHODIMP
|
||||
nsAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
// When adding support for relations, make sure to add them to
|
||||
// appropriate places in nsAccessibleWrap implementations
|
||||
*aRelated = nsnull;
|
||||
NS_ENSURE_ARG_POINTER(aRelation);
|
||||
*aRelation = nsnull;
|
||||
|
||||
// Relationships are defined on the same content node
|
||||
// that the role would be defined on
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Relationships are defined on the same content node that the role would be
|
||||
// defined on.
|
||||
nsIContent *content = nsCoreUtils::GetRoleContent(mDOMNode);
|
||||
if (!content) {
|
||||
return NS_ERROR_FAILURE; // Node already shut down
|
||||
}
|
||||
if (!content)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> relatedNode;
|
||||
nsAutoString relatedID;
|
||||
nsresult rv;
|
||||
|
||||
// Search for the related DOM node according to the specified "relation type"
|
||||
switch (aRelationType)
|
||||
{
|
||||
case nsIAccessibleRelation::RELATION_LABEL_FOR:
|
||||
{
|
||||
if (content->Tag() == nsAccessibilityAtoms::label) {
|
||||
nsIAtom *relatedIDAttr = content->IsNodeOfType(nsINode::eHTML) ?
|
||||
nsIAtom *IDAttr = content->IsNodeOfType(nsINode::eHTML) ?
|
||||
nsAccessibilityAtoms::_for : nsAccessibilityAtoms::control;
|
||||
content->GetAttr(kNameSpaceID_None, relatedIDAttr, relatedID);
|
||||
rv = nsRelUtils::
|
||||
AddTargetFromIDRefAttr(aRelationType, aRelation, content, IDAttr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
return NS_OK; // XXX bug 381599, avoid performance problems
|
||||
}
|
||||
if (relatedID.IsEmpty()) {
|
||||
relatedNode =
|
||||
do_QueryInterface(nsCoreUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::aria_labelledby));
|
||||
}
|
||||
break;
|
||||
|
||||
return nsRelUtils::
|
||||
AddTargetFromNeighbour(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_labelledby);
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_LABELLED_BY:
|
||||
{
|
||||
if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_labelledby, relatedID)) {
|
||||
relatedNode = do_QueryInterface(nsCoreUtils::GetLabelContent(content));
|
||||
}
|
||||
break;
|
||||
rv = nsRelUtils::
|
||||
AddTargetFromIDRefsAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_labelledby);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
return NS_OK; // XXX bug 381599, avoid performance problems
|
||||
|
||||
return nsRelUtils::
|
||||
AddTargetFromContent(aRelationType, aRelation,
|
||||
nsCoreUtils::GetLabelContent(content));
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_DESCRIBED_BY:
|
||||
{
|
||||
if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_describedby, relatedID)) {
|
||||
relatedNode = do_QueryInterface(
|
||||
nsCoreUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::control, nsAccessibilityAtoms::description));
|
||||
}
|
||||
break;
|
||||
rv = nsRelUtils::
|
||||
AddTargetFromIDRefsAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_describedby);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
return NS_OK; // XXX bug 381599, avoid performance problems
|
||||
|
||||
return nsRelUtils::
|
||||
AddTargetFromNeighbour(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::control,
|
||||
nsAccessibilityAtoms::description);
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR:
|
||||
{
|
||||
relatedNode =
|
||||
do_QueryInterface(nsCoreUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::aria_describedby));
|
||||
rv = nsRelUtils::
|
||||
AddTargetFromNeighbour(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_describedby);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!relatedNode && content->Tag() == nsAccessibilityAtoms::description &&
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
return NS_OK; // XXX bug 381599, avoid performance problems
|
||||
|
||||
if (content->Tag() == nsAccessibilityAtoms::description &&
|
||||
content->IsNodeOfType(nsINode::eXUL)) {
|
||||
// This affectively adds an optional control attribute to xul:description,
|
||||
// which only affects accessibility, by allowing the description to be
|
||||
// tied to a control.
|
||||
content->GetAttr(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::control, relatedID);
|
||||
return nsRelUtils::
|
||||
AddTargetFromIDRefAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::control);
|
||||
}
|
||||
break;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_NODE_CHILD_OF:
|
||||
{
|
||||
relatedNode =
|
||||
do_QueryInterface(nsCoreUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::aria_owns));
|
||||
if (!relatedNode && mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
|
||||
// This is an ARIA tree that doesn't use owns, so we need to get the parent the hard way
|
||||
nsAccUtils::GetARIATreeItemParent(this, content, aRelated);
|
||||
return NS_OK;
|
||||
rv = nsRelUtils::
|
||||
AddTargetFromNeighbour(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_owns);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
return NS_OK; // XXX bug 381599, avoid performance problems
|
||||
|
||||
if (mRoleMapEntry &&
|
||||
mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
|
||||
// This is an ARIA tree that doesn't use owns, so we need to get
|
||||
// the parent the hard way.
|
||||
nsCOMPtr<nsIAccessible> accTarget;
|
||||
nsAccUtils::GetARIATreeItemParent(this, content,
|
||||
getter_AddRefs(accTarget));
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget);
|
||||
}
|
||||
|
||||
// If accessible is in its own Window then we should provide NODE_CHILD_OF relation
|
||||
// so that MSAA clients can easily get to true parent instead of getting to oleacc's
|
||||
// ROLE_WINDOW accessible which will prevent us from going up further (because it is
|
||||
@ -2787,34 +2815,44 @@ NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAcce
|
||||
if (view) {
|
||||
nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
|
||||
if (scrollFrame || view->GetWidget()) {
|
||||
return GetParent(aRelated);
|
||||
nsCOMPtr<nsIAccessible> accTarget;
|
||||
GetParent(getter_AddRefs(accTarget));
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
|
||||
{
|
||||
relatedNode =
|
||||
do_QueryInterface(nsCoreUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::aria_controls));
|
||||
break;
|
||||
return nsRelUtils::
|
||||
AddTargetFromNeighbour(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_controls);
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_CONTROLLER_FOR:
|
||||
{
|
||||
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_controls, relatedID);
|
||||
break;
|
||||
return nsRelUtils::
|
||||
AddTargetFromIDRefsAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_controls);
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_FLOWS_TO:
|
||||
{
|
||||
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_flowto, relatedID);
|
||||
break;
|
||||
return nsRelUtils::
|
||||
AddTargetFromIDRefsAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_flowto);
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_FLOWS_FROM:
|
||||
{
|
||||
relatedNode =
|
||||
do_QueryInterface(nsCoreUtils::FindNeighbourPointingToNode(content, nsAccessibilityAtoms::aria_flowto));
|
||||
break;
|
||||
return nsRelUtils::
|
||||
AddTargetFromNeighbour(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::aria_flowto);
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON:
|
||||
{
|
||||
if (content->IsNodeOfType(nsINode::eHTML)) {
|
||||
@ -2824,8 +2862,12 @@ NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAcce
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> htmlform;
|
||||
control->GetForm(getter_AddRefs(htmlform));
|
||||
nsCOMPtr<nsIForm> form(do_QueryInterface(htmlform));
|
||||
if (form)
|
||||
relatedNode = do_QueryInterface(form->GetDefaultSubmitElement());
|
||||
if (form) {
|
||||
nsCOMPtr<nsIContent> formContent =
|
||||
do_QueryInterface(form->GetDefaultSubmitElement());
|
||||
return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
|
||||
formContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -2864,37 +2906,24 @@ NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAcce
|
||||
}
|
||||
}
|
||||
}
|
||||
relatedNode = do_QueryInterface(buttonEl);
|
||||
nsCOMPtr<nsIContent> relatedContent(do_QueryInterface(buttonEl));
|
||||
return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
|
||||
relatedContent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_MEMBER_OF:
|
||||
{
|
||||
relatedNode = GetAtomicRegion();
|
||||
break;
|
||||
nsCOMPtr<nsIContent> regionContent = do_QueryInterface(GetAtomicRegion());
|
||||
return nsRelUtils::
|
||||
AddTargetFromContent(aRelationType, aRelation, regionContent);
|
||||
}
|
||||
|
||||
default:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!relatedID.IsEmpty()) {
|
||||
// In some cases we need to get the relatedNode from an ID-style attribute
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mDOMNode->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDOMElement> relatedEl;
|
||||
domDoc->GetElementById(relatedID, getter_AddRefs(relatedEl));
|
||||
relatedNode = do_QueryInterface(relatedEl);
|
||||
}
|
||||
|
||||
// Return the corresponding accessible if the related DOM node is found
|
||||
if (relatedNode) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
|
||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||
accService->GetAccessibleInWeakShell(relatedNode, mWeakShell, aRelated);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2945,16 +2974,12 @@ nsAccessible::GetRelations(nsIArray **aRelations)
|
||||
for (PRUint32 relType = nsIAccessibleRelation::RELATION_FIRST;
|
||||
relType < nsIAccessibleRelation::RELATION_LAST;
|
||||
++relType) {
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
GetAccessibleRelated(relType, getter_AddRefs(accessible));
|
||||
|
||||
if (accessible) {
|
||||
nsCOMPtr<nsIAccessibleRelation> relation =
|
||||
new nsAccessibleRelationWrap(relType, accessible);
|
||||
NS_ENSURE_TRUE(relation, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsCOMPtr<nsIAccessibleRelation> relation;
|
||||
nsresult rv = GetRelationByType(relType, getter_AddRefs(relation));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && relation)
|
||||
relations->AppendElement(relation, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*aRelations = relations);
|
||||
|
@ -48,9 +48,10 @@
|
||||
#include "nsIAccessibleValue.h"
|
||||
#include "nsIAccessibleRole.h"
|
||||
#include "nsIAccessibleStates.h"
|
||||
#include "nsAccessibleRelationWrap.h"
|
||||
#include "nsIAccessibleEvent.h"
|
||||
|
||||
#include "nsRelUtils.h"
|
||||
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
@ -38,17 +38,21 @@
|
||||
|
||||
#include "nsAccessibleRelation.h"
|
||||
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
nsAccessibleRelation::
|
||||
nsAccessibleRelation(PRUint32 aType, nsIAccessible *aTarget) :
|
||||
mType(aType), mTarget(aTarget)
|
||||
mType(aType)
|
||||
{
|
||||
mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (aTarget)
|
||||
mTargets->AppendElement(aTarget, PR_FALSE);
|
||||
}
|
||||
|
||||
// nsISupports
|
||||
NS_IMPL_ISUPPORTS1(nsAccessibleRelation, nsIAccessibleRelation)
|
||||
NS_IMPL_ISUPPORTS2(nsAccessibleRelation, nsAccessibleRelation,
|
||||
nsIAccessibleRelation)
|
||||
|
||||
// nsIAccessibleRelation
|
||||
NS_IMETHODIMP
|
||||
@ -64,33 +68,48 @@ NS_IMETHODIMP
|
||||
nsAccessibleRelation::GetTargetsCount(PRUint32 *aCount)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCount);
|
||||
*aCount = 0;
|
||||
|
||||
*aCount = 1;
|
||||
return NS_OK;
|
||||
NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
return mTargets->GetLength(aCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibleRelation::GetTarget(PRUint32 aIndex, nsIAccessible **aTarget)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTarget);
|
||||
*aTarget = nsnull;
|
||||
|
||||
if (aIndex != 0)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_IF_ADDREF(*aTarget = mTarget);
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIAccessible> target = do_QueryElementAt(mTargets, aIndex, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
target.swap(*aTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibleRelation::GetTargets(nsIArray **aRelations)
|
||||
nsAccessibleRelation::GetTargets(nsIArray **aTargets)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRelations);
|
||||
NS_ENSURE_ARG_POINTER(aTargets);
|
||||
*aTargets = nsnull;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
relations->AppendElement(mTarget, PR_FALSE);
|
||||
|
||||
NS_ADDREF(*aRelations = relations);
|
||||
NS_ADDREF(*aTargets = mTargets);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsAccessibleRelation
|
||||
nsresult
|
||||
nsAccessibleRelation::AddTarget(nsIAccessible *aTarget)
|
||||
{
|
||||
NS_ENSURE_ARG(aTarget);
|
||||
|
||||
NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
return mTargets->AppendElement(aTarget, PR_FALSE);
|
||||
}
|
||||
|
@ -43,7 +43,19 @@
|
||||
#include "nsIAccessibleRelation.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMutableArray.h"
|
||||
|
||||
#define NS_ACCRELATION_IMPL_CID \
|
||||
{ \
|
||||
0xb20390d0, \
|
||||
0x40d3, \
|
||||
0x4c76, \
|
||||
{ 0xb6, 0x2e, 0xc2, 0x30, 0xc8, 0xea, 0x0c, 0x1e } \
|
||||
}
|
||||
|
||||
/**
|
||||
* Class represents an accessible relation.
|
||||
*/
|
||||
class nsAccessibleRelation: public nsIAccessibleRelation
|
||||
{
|
||||
public:
|
||||
@ -52,9 +64,20 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIACCESSIBLERELATION
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCRELATION_IMPL_CID)
|
||||
|
||||
/**
|
||||
* Add target for the given key.
|
||||
*
|
||||
* @param aTarget - accessible target for the given relation.
|
||||
*/
|
||||
nsresult AddTarget(nsIAccessible *aTarget);
|
||||
|
||||
private:
|
||||
PRUint32 mType;
|
||||
nsCOMPtr<nsIAccessible> mTarget;
|
||||
nsCOMPtr<nsIMutableArray> mTargets;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessibleRelation, NS_ACCRELATION_IMPL_CID)
|
||||
|
||||
#endif
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "nsContentCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIMutableArray.h"
|
||||
|
||||
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
@ -742,6 +743,51 @@ nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
||||
walkUp = walkUp->GetParent();
|
||||
}
|
||||
|
||||
void
|
||||
nsCoreUtils::GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr,
|
||||
nsIArray **aRefElements)
|
||||
{
|
||||
*aRefElements = nsnull;
|
||||
|
||||
nsAutoString ids;
|
||||
if (!aContent->GetAttr(kNameSpaceID_None, aAttr, ids))
|
||||
return;
|
||||
|
||||
ids.CompressWhitespace(PR_TRUE, PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(aContent->GetOwnerDoc());
|
||||
NS_ASSERTION(document, "The given node is not in document!");
|
||||
if (!document)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> refElms = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
|
||||
while (!ids.IsEmpty()) {
|
||||
nsAutoString id;
|
||||
PRInt32 idLength = ids.FindChar(' ');
|
||||
NS_ASSERTION(idLength != 0,
|
||||
"Should not be 0 because of CompressWhitespace() call above");
|
||||
|
||||
if (idLength == kNotFound) {
|
||||
id = ids;
|
||||
ids.Truncate();
|
||||
} else {
|
||||
id = Substring(ids, 0, idLength);
|
||||
ids.Cut(0, idLength + 1);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> refElement;
|
||||
document->GetElementById(id, getter_AddRefs(refElement));
|
||||
if (!refElement)
|
||||
continue;
|
||||
|
||||
refElms->AppendElement(refElement, PR_FALSE);
|
||||
}
|
||||
|
||||
NS_ADDREF(*aRefElements = refElms);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsCoreUtils::GetComputedStyleDeclaration(const nsAString& aPseudoElt,
|
||||
nsIDOMNode *aNode,
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsPoint.h"
|
||||
|
||||
class nsCoreUtils
|
||||
@ -233,6 +234,17 @@ public:
|
||||
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
||||
nsAString& aLanguage);
|
||||
|
||||
/**
|
||||
* Return the array of elements the given node is referred to by its
|
||||
* IDRefs attribute.
|
||||
*
|
||||
* @param aContent [in] the given node
|
||||
* @param aAttr [in] IDRefs attribute on the given node
|
||||
* @param aRefElements [out] result array of elements
|
||||
*/
|
||||
static void GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr,
|
||||
nsIArray **aRefElements);
|
||||
|
||||
/**
|
||||
* Return computed styles declaration for the given node.
|
||||
*/
|
||||
|
160
accessible/src/base/nsRelUtils.cpp
Normal file
160
accessible/src/base/nsRelUtils.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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) 2009
|
||||
* 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 of 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 "nsRelUtils.h"
|
||||
|
||||
#include "nsAccessNode.h"
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsRelUtils::GetRelatedAccessible(nsIAccessible *aAccessible,
|
||||
PRUint32 aRelationType)
|
||||
{
|
||||
nsCOMPtr<nsIAccessibleRelation> relation;
|
||||
nsresult rv = aAccessible->GetRelationByType(aRelationType,
|
||||
getter_AddRefs(relation));
|
||||
if (NS_FAILED(rv) || !relation)
|
||||
return nsnull;
|
||||
|
||||
nsIAccessible *targetAccessible = nsnull;
|
||||
rv = relation->GetTarget(0, &targetAccessible);
|
||||
return targetAccessible;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRelUtils::AddTarget(PRUint32 aRelationType, nsIAccessibleRelation **aRelation,
|
||||
nsIAccessible *aTarget)
|
||||
{
|
||||
if (!aTarget)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
if (*aRelation) {
|
||||
nsRefPtr<nsAccessibleRelation> relation = QueryAccRelation(*aRelation);
|
||||
return relation->AddTarget(aTarget);
|
||||
}
|
||||
|
||||
*aRelation = new nsAccessibleRelationWrap(aRelationType, aTarget);
|
||||
NS_ENSURE_TRUE(*aRelation, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ADDREF(*aRelation);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRelUtils::AddTargetFromContent(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent)
|
||||
{
|
||||
if (!aContent)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
nsCOMPtr<nsIAccessibilityService> accService = nsAccessNode::GetAccService();
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleFor(node, getter_AddRefs(accessible));
|
||||
return AddTarget(aRelationType, aRelation, accessible);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRelUtils::AddTargetFromIDRefAttr(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent, nsIAtom *aAttr)
|
||||
{
|
||||
nsAutoString id;
|
||||
if (!aContent->GetAttr(kNameSpaceID_None, aAttr, id))
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> document =
|
||||
do_QueryInterface(aContent->GetOwnerDoc());
|
||||
NS_ASSERTION(document, "The given node is not in document!");
|
||||
if (!document)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> refElm;
|
||||
document->GetElementById(id, getter_AddRefs(refElm));
|
||||
|
||||
nsCOMPtr<nsIContent> refContent(do_QueryInterface(refElm));
|
||||
return AddTargetFromContent(aRelationType, aRelation, refContent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent, nsIAtom *aAttr)
|
||||
{
|
||||
nsCOMPtr<nsIArray> refElms;
|
||||
nsCoreUtils::GetElementsByIDRefsAttr(aContent, aAttr, getter_AddRefs(refElms));
|
||||
|
||||
if (!refElms)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
PRUint32 count = 0;
|
||||
nsresult rv = refElms->GetLength(&count);
|
||||
if (NS_FAILED(rv) || count == 0)
|
||||
return NS_OK_NO_RELATION_TARGET;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
for (PRUint32 idx = 0; idx < count; idx++) {
|
||||
content = do_QueryElementAt(refElms, idx, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddTargetFromContent(aRelationType, aRelation, content);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRelUtils::AddTargetFromNeighbour(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent,
|
||||
nsIAtom *aNeighboutAttr,
|
||||
nsIAtom *aNeighboutTagName)
|
||||
{
|
||||
return AddTargetFromContent(
|
||||
aRelationType, aRelation,
|
||||
nsCoreUtils::FindNeighbourPointingToNode(aContent, aNeighboutAttr,
|
||||
aNeighboutTagName));
|
||||
}
|
151
accessible/src/base/nsRelUtils.h
Normal file
151
accessible/src/base/nsRelUtils.h
Normal file
@ -0,0 +1,151 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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) 2009
|
||||
* 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 of 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 _nsRelUtils_H_
|
||||
#define _nsRelUtils_H_
|
||||
|
||||
#include "nsAccessibleRelationWrap.h"
|
||||
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
// Used by AddTarget...() methods. Returned when can't get target accessible.
|
||||
#define NS_OK_NO_RELATION_TARGET \
|
||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x24)
|
||||
|
||||
/**
|
||||
* Utils class designed to work with accessible relations.
|
||||
*/
|
||||
class nsRelUtils
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Return first target of the relation of the given relation type for
|
||||
* the given accessible.
|
||||
*
|
||||
* @param aAccessible [in] the accessible to get an relation
|
||||
* @param aRelationType [in] relation type
|
||||
* @return an accessible
|
||||
*/
|
||||
static already_AddRefed<nsIAccessible>
|
||||
GetRelatedAccessible(nsIAccessible *aAccessible, PRUint32 aRelationType);
|
||||
|
||||
/**
|
||||
* Create the relation if the given relation is null. Add target to it
|
||||
* which is the given accessible.
|
||||
*
|
||||
* @param aRelationType [in] relation type
|
||||
* @param aRelation [in, out] relation object
|
||||
* @param aTarget [in] accessible object
|
||||
*/
|
||||
static nsresult AddTarget(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIAccessible *aTarget);
|
||||
|
||||
/**
|
||||
* Create the relation if the given relation is null and add the target to it
|
||||
* which is the accessible for the given node.
|
||||
*
|
||||
* @param aRelationType [in] relation type
|
||||
* @param aRelation [in, out] relation object
|
||||
* @param aContent [in] accessible node
|
||||
*/
|
||||
static nsresult AddTargetFromContent(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent);
|
||||
|
||||
/**
|
||||
* Create the relation if the given relation is null and add the target to it
|
||||
* pointed by IDRef attribute on the given node.
|
||||
*
|
||||
* @param aRelationType [in] relation type
|
||||
* @param aRelation [in, out] relation object
|
||||
* @param aContent [in] node having the given IDRef attribute
|
||||
* @param aAttr [in] IDRef attribute
|
||||
*/
|
||||
static nsresult AddTargetFromIDRefAttr(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent, nsIAtom *aAttr);
|
||||
|
||||
/**
|
||||
* Create the relation if the given relation is null and add the targets to it
|
||||
* that are pointed by IDRefs attribute on the given node.
|
||||
*
|
||||
* @param aRelationType [in] relation type
|
||||
* @param aRelation [in, out] relation object
|
||||
* @param aContent [in] node having the given IDRefs attribute
|
||||
* @param aAttr [in] IDRefs attribute
|
||||
*/
|
||||
static nsresult AddTargetFromIDRefsAttr(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent, nsIAtom *aAttr);
|
||||
|
||||
/**
|
||||
* Create the relation if the given relation is null and add the target to it
|
||||
* found in neighbour tree.
|
||||
*
|
||||
* @param aRelationType [in] relation type
|
||||
* @param aRelation [in, out] relation object
|
||||
* @param aContent [in] node defining neighbour tree
|
||||
* @param aNeighboutAttr [in] IDRef attribute of the node in neighbour
|
||||
* tree pointing to node defining neighbour tree
|
||||
* @param aNeighboutTagName [in, optional] tag name of the node in neighbour
|
||||
* tree having IDRef attribute pointed by previous
|
||||
* argument
|
||||
*/
|
||||
static nsresult AddTargetFromNeighbour(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation,
|
||||
nsIContent *aContent,
|
||||
nsIAtom *aNeighboutAttr,
|
||||
nsIAtom *aNeighboutTagName = nsnull);
|
||||
|
||||
/**
|
||||
* Query nsAccessibleRelation from the given nsIAccessibleRelation.
|
||||
*/
|
||||
static already_AddRefed<nsAccessibleRelation>
|
||||
QueryAccRelation(nsIAccessibleRelation *aRelation)
|
||||
{
|
||||
nsAccessibleRelation* relation = nsnull;
|
||||
if (aRelation)
|
||||
CallQueryInterface(aRelation, &relation);
|
||||
|
||||
return relation;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -1029,13 +1029,15 @@ nsRootAccessible::GetContentDocShell(nsIDocShellTreeItem *aStart)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRootAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
NS_IMETHODIMP
|
||||
nsRootAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
*aRelated = nsnull;
|
||||
NS_ENSURE_ARG_POINTER(aRelation);
|
||||
*aRelation = nsnull;
|
||||
|
||||
if (!mDOMNode || aRelationType != nsIAccessibleRelation::RELATION_EMBEDS) {
|
||||
return nsDocAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
||||
return nsDocAccessibleWrap::GetRelationByType(aRelationType, aRelation);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
||||
@ -1046,9 +1048,10 @@ NS_IMETHODIMP nsRootAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsCOMPtr<nsIAccessibleDocument> accDoc =
|
||||
GetDocAccessibleFor(contentTreeItem, PR_TRUE);
|
||||
|
||||
if (accDoc)
|
||||
CallQueryInterface(accDoc, aRelated);
|
||||
nsCOMPtr<nsIAccessible> acc(do_QueryInterface(accDoc));
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, acc);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,8 @@ class nsRootAccessible : public nsDocAccessibleWrap,
|
||||
NS_IMETHOD GetName(nsAString& aName);
|
||||
NS_IMETHOD GetParent(nsIAccessible * *aParent);
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// ----- nsPIAccessibleDocument -----------------------
|
||||
NS_IMETHOD FireDocLoadEvents(PRUint32 aEventType);
|
||||
|
@ -619,28 +619,17 @@ nsHTMLGroupboxAccessible::GetNameInternal(nsAString& aName)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLGroupboxAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
nsHTMLGroupboxAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
if (!mDOMNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ENSURE_ARG_POINTER(aRelated);
|
||||
|
||||
*aRelated = nsnull;
|
||||
|
||||
nsresult rv = nsHyperTextAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
||||
if (NS_FAILED(rv) || *aRelated) {
|
||||
// Either the node is shut down, or another relation mechanism has been used
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = nsHyperTextAccessibleWrap::GetRelationByType(aRelationType,
|
||||
aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_LABELLED_BY) {
|
||||
// No override for label, so use <legend> for this <fieldset>
|
||||
nsCOMPtr<nsIDOMNode> legendNode = do_QueryInterface(GetLegend());
|
||||
if (legendNode) {
|
||||
GetAccService()->GetAccessibleInWeakShell(legendNode, mWeakShell, aRelated);
|
||||
}
|
||||
return nsRelUtils::
|
||||
AddTargetFromContent(aRelationType, aRelation, GetLegend());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -652,31 +641,28 @@ nsHyperTextAccessibleWrap(aNode, aShell)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLLegendAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
nsHTMLLegendAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
*aRelated = nsnull;
|
||||
|
||||
nsresult rv = nsHyperTextAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
||||
if (NS_FAILED(rv) || *aRelated) {
|
||||
// Either the node is shut down, or another relation mechanism has been used
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = nsHyperTextAccessibleWrap::
|
||||
GetRelationByType(aRelationType, aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
|
||||
// Look for groupbox parent
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
|
||||
if (!content) {
|
||||
return NS_ERROR_FAILURE; // Node already shut down
|
||||
}
|
||||
nsCOMPtr<nsIAccessible> groupboxAccessible = GetParent();
|
||||
if (nsAccUtils::Role(groupboxAccessible) == nsIAccessibleRole::ROLE_GROUPING) {
|
||||
nsCOMPtr<nsIAccessible> testLabelAccessible;
|
||||
groupboxAccessible->GetAccessibleRelated(nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
getter_AddRefs(testLabelAccessible));
|
||||
// XXX: if group box exposes more than one relation of the given type
|
||||
// then we fail.
|
||||
nsCOMPtr<nsIAccessible> testLabelAccessible =
|
||||
nsRelUtils::GetRelatedAccessible(groupboxAccessible,
|
||||
nsIAccessibleRelation::RELATION_LABELLED_BY);
|
||||
|
||||
if (testLabelAccessible == this) {
|
||||
// We're the first child of the parent groupbox
|
||||
NS_ADDREF(*aRelated = groupboxAccessible);
|
||||
// We're the first child of the parent groupbox, see
|
||||
// nsHTMLGroupboxAccessible::GetRelationByType().
|
||||
return nsRelUtils::
|
||||
AddTarget(aRelationType, aRelation, groupboxAccessible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,8 @@ public:
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
@ -153,8 +154,12 @@ class nsHTMLLegendAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLLegendAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole) { *aRole = nsIAccessibleRole::ROLE_LABEL; return NS_OK; }
|
||||
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -241,24 +241,17 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTableAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
nsHTMLTableAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRelated);
|
||||
*aRelated = nsnull;
|
||||
|
||||
if (!mDOMNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = nsAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
||||
if (NS_FAILED(rv) || *aRelated) {
|
||||
// Either the node is shut down, or another relation mechanism has been used
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType,
|
||||
aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_DESCRIBED_BY) {
|
||||
return GetCaption(aRelated);
|
||||
nsCOMPtr<nsIAccessible> accCaption;
|
||||
GetCaption(getter_AddRefs(accCaption));
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, accCaption);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1254,24 +1247,17 @@ nsHTMLTableHeadAccessible::GetRows(PRInt32 *aRows)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCaptionAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
nsHTMLCaptionAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRelated);
|
||||
*aRelated = nsnull;
|
||||
|
||||
if (!mDOMNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = nsHyperTextAccessible::GetAccessibleRelated(aRelationType, aRelated);
|
||||
if (NS_FAILED(rv) || *aRelated) {
|
||||
// Either the node is shut down, or another relation mechanism has been used
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = nsHyperTextAccessible::GetRelationByType(aRelationType,
|
||||
aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_DESCRIPTION_FOR) {
|
||||
return GetParent(aRelated);
|
||||
nsCOMPtr<nsIAccessible> accParent;
|
||||
GetParent(getter_AddRefs(accParent));
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, accParent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -75,7 +75,8 @@ public:
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aResult);
|
||||
NS_IMETHOD GetDescription(nsAString& aDescription);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
@ -160,7 +161,9 @@ public:
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole)
|
||||
{ *aRole = nsIAccessibleRole::ROLE_CAPTION; return NS_OK; }
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated);
|
||||
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -987,13 +987,8 @@ __try {
|
||||
|
||||
pvarEndUpAt->vt = VT_EMPTY;
|
||||
|
||||
if (xpRelation) {
|
||||
nsresult rv = GetAccessibleRelated(xpRelation,
|
||||
getter_AddRefs(xpAccessibleResult));
|
||||
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
if (xpRelation)
|
||||
xpAccessibleResult = nsRelUtils::GetRelatedAccessible(this, xpRelation);
|
||||
|
||||
if (xpAccessibleResult) {
|
||||
pvarEndUpAt->pdispVal = NativeAccessible(xpAccessibleResult);
|
||||
|
@ -421,9 +421,10 @@ NS_IMETHODIMP nsXULGroupboxAccessible::GetRole(PRUint32 *aRole)
|
||||
nsresult
|
||||
nsXULGroupboxAccessible::GetNameInternal(nsAString& aName)
|
||||
{
|
||||
nsCOMPtr<nsIAccessible> label;
|
||||
GetAccessibleRelated(nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
getter_AddRefs(label));
|
||||
// XXX: we use the first related accessible only.
|
||||
nsCOMPtr<nsIAccessible> label =
|
||||
nsRelUtils::GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_LABELLED_BY);
|
||||
|
||||
if (label) {
|
||||
return label->GetName(aName);
|
||||
}
|
||||
@ -432,16 +433,11 @@ nsXULGroupboxAccessible::GetNameInternal(nsAString& aName)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULGroupboxAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
nsXULGroupboxAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
*aRelated = nsnull;
|
||||
|
||||
nsresult rv = nsAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
||||
if (NS_FAILED(rv) || *aRelated) {
|
||||
// Either the node is shut down, or another relation mechanism has been used
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_LABELLED_BY) {
|
||||
// The label for xul:groupbox is generated from xul:label that is
|
||||
@ -451,13 +447,16 @@ nsXULGroupboxAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
while (NextChild(testLabelAccessible)) {
|
||||
if (nsAccUtils::Role(testLabelAccessible) == nsIAccessibleRole::ROLE_LABEL) {
|
||||
// Ensure that it's our label
|
||||
nsCOMPtr<nsIAccessible> testGroupboxAccessible;
|
||||
testLabelAccessible->GetAccessibleRelated(nsIAccessibleRelation::RELATION_LABEL_FOR,
|
||||
getter_AddRefs(testGroupboxAccessible));
|
||||
// XXX: we'll fail if group accessible expose more than one relation
|
||||
// targets.
|
||||
nsCOMPtr<nsIAccessible> testGroupboxAccessible =
|
||||
nsRelUtils::GetRelatedAccessible(testLabelAccessible,
|
||||
nsIAccessibleRelation::RELATION_LABEL_FOR);
|
||||
|
||||
if (testGroupboxAccessible == this) {
|
||||
// The <label> points back to this groupbox
|
||||
NS_ADDREF(*aRelated = testLabelAccessible);
|
||||
return NS_OK;
|
||||
return nsRelUtils::
|
||||
AddTarget(aRelationType, aRelation, testLabelAccessible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,8 @@ public:
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *_retval);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
|
@ -130,21 +130,14 @@ nsXULTabAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTabAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelatedAccessible)
|
||||
nsXULTabAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRelatedAccessible);
|
||||
*aRelatedAccessible = nsnull;
|
||||
|
||||
if (!mDOMNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = nsLeafAccessible::GetAccessibleRelated(aRelationType,
|
||||
aRelatedAccessible);
|
||||
nsresult rv = nsLeafAccessible::GetRelationByType(aRelationType,
|
||||
aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (*aRelatedAccessible ||
|
||||
aRelationType != nsIAccessibleRelation::RELATION_LABEL_FOR)
|
||||
if (aRelationType != nsIAccessibleRelation::RELATION_LABEL_FOR)
|
||||
return NS_OK;
|
||||
|
||||
// Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
|
||||
@ -154,24 +147,12 @@ nsXULTabAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
|
||||
// Check whether tab and tabpanel are related by 'linkedPanel' attribute on
|
||||
// xul:tab element.
|
||||
nsAutoString linkedPanelID;
|
||||
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::linkedPanel,
|
||||
linkedPanelID);
|
||||
rv = nsRelUtils::AddTargetFromIDRefAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::linkedPanel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!linkedPanelID.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMDocument> document;
|
||||
mDOMNode->GetOwnerDocument(getter_AddRefs(document));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> linkedPanel;
|
||||
document->GetElementById(linkedPanelID, getter_AddRefs(linkedPanel));
|
||||
if (linkedPanel) {
|
||||
nsCOMPtr<nsIDOMNode> linkedPanelNode(do_QueryInterface(linkedPanel));
|
||||
GetAccService()->GetAccessibleInWeakShell(linkedPanelNode, mWeakShell,
|
||||
aRelatedAccessible);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
return NS_OK;
|
||||
|
||||
// If there is no 'linkedPanel' attribute on xul:tab element then we
|
||||
// assume tab and tabpanels are related 1 to 1. We follow algorithm from
|
||||
@ -205,10 +186,8 @@ nsXULTabAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
tabBoxAcc->GetFirstChild(getter_AddRefs(childAcc));
|
||||
while (childAcc) {
|
||||
if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PROPERTYPAGE) {
|
||||
if (tabIndex == 0) {
|
||||
NS_ADDREF(*aRelatedAccessible = childAcc);
|
||||
return NS_OK;
|
||||
}
|
||||
if (tabIndex == 0)
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, childAcc);
|
||||
|
||||
tabIndex--;
|
||||
}
|
||||
@ -319,21 +298,13 @@ nsXULTabpanelAccessible::GetRole(PRUint32 *aRole)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTabpanelAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelatedAccessible)
|
||||
nsXULTabpanelAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRelatedAccessible);
|
||||
*aRelatedAccessible = nsnull;
|
||||
|
||||
if (!mDOMNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = nsAccessibleWrap::GetAccessibleRelated(aRelationType,
|
||||
aRelatedAccessible);
|
||||
nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (*aRelatedAccessible ||
|
||||
aRelationType != nsIAccessibleRelation::RELATION_LABELLED_BY)
|
||||
if (aRelationType != nsIAccessibleRelation::RELATION_LABELLED_BY)
|
||||
return NS_OK;
|
||||
|
||||
// Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
|
||||
@ -384,8 +355,7 @@ nsXULTabpanelAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
if (tabContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::linkedPanel, atomID,
|
||||
eCaseMatters)) {
|
||||
NS_ADDREF(*aRelatedAccessible = childAcc);
|
||||
return NS_OK;
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, childAcc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,7 +373,6 @@ nsXULTabpanelAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
childAcc.swap(acc);
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aRelatedAccessible = foundTabAcc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,8 @@ public:
|
||||
NS_IMETHOD GetNumActions(PRUint8 *_retval);
|
||||
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
|
||||
NS_IMETHOD DoAction(PRUint8 index);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelatedAccessible);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
|
||||
@ -108,8 +108,8 @@ public:
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole);
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelatedAccessible);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -81,19 +81,16 @@ nsXULTextAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTextAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated)
|
||||
nsXULTextAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
nsresult rv =
|
||||
nsHyperTextAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
||||
nsHyperTextAccessibleWrap::GetRelationByType(aRelationType, aRelation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (*aRelated) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent *content = nsCoreUtils::GetRoleContent(mDOMNode);
|
||||
if (!content)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
|
||||
// Caption is the label for groupbox
|
||||
@ -102,7 +99,8 @@ nsXULTextAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsCOMPtr<nsIAccessible> parentAccessible;
|
||||
GetParent(getter_AddRefs(parentAccessible));
|
||||
if (nsAccUtils::Role(parentAccessible) == nsIAccessibleRole::ROLE_GROUPING)
|
||||
parentAccessible.swap(*aRelated);
|
||||
return nsRelUtils::
|
||||
AddTarget(aRelationType, aRelation, parentAccessible);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,8 @@ public:
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole) { *aRole = nsIAccessibleRole::ROLE_LABEL; return NS_OK; }
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType,
|
||||
nsIAccessible **aRelated);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
|
@ -1281,31 +1281,40 @@ NS_IMETHODIMP nsXULTreeitemAccessible::TakeFocus()
|
||||
return nsAccessible::TakeFocus();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXULTreeitemAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated)
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeitemAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRelation);
|
||||
*aRelation = nsnull;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aRelated = nsnull;
|
||||
if (aRelationType == nsIAccessibleRelation::RELATION_NODE_CHILD_OF) {
|
||||
PRInt32 columnIndex;
|
||||
if (NS_SUCCEEDED(mColumn->GetIndex(&columnIndex)) && columnIndex == 0) {
|
||||
PRInt32 parentIndex;
|
||||
if (NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex))) {
|
||||
if (parentIndex == -1) {
|
||||
NS_IF_ADDREF(*aRelated = mParent);
|
||||
return NS_OK;
|
||||
} else {
|
||||
nsCOMPtr<nsIAccessibleTreeCache> cache =
|
||||
do_QueryInterface(mParent);
|
||||
return cache->GetCachedTreeitemAccessible(parentIndex, mColumn, aRelated);
|
||||
}
|
||||
if (parentIndex == -1)
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, mParent);
|
||||
|
||||
nsCOMPtr<nsIAccessibleTreeCache> cache =
|
||||
do_QueryInterface(mParent);
|
||||
nsCOMPtr<nsIAccessible> accParent;
|
||||
nsresult rv = cache->
|
||||
GetCachedTreeitemAccessible(parentIndex, mColumn,
|
||||
getter_AddRefs(accParent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, accParent);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsAccessible::GetAccessibleRelated(aRelationType, aRelated);
|
||||
return nsAccessible::GetRelationByType(aRelationType, aRelation);
|
||||
}
|
||||
|
||||
// attribute AString nsIAccessibleTreeItem::cachedName
|
||||
|
@ -129,7 +129,8 @@ public:
|
||||
NS_IMETHOD SetSelected(PRBool aSelect);
|
||||
NS_IMETHOD TakeFocus(void);
|
||||
|
||||
NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated);
|
||||
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
|
||||
nsIAccessibleRelation **aRelation);
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
@ -283,6 +283,22 @@ function relationTypeToString(aRelationType)
|
||||
return gAccRetrieval.getStringRelationType(aRelationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pretty name for identifier, it may be ID, DOM node or accessible.
|
||||
*/
|
||||
function prettyName(aIdentifier)
|
||||
{
|
||||
if (aIdentifier instanceof nsIAccessible) {
|
||||
var acc = getAccessible(aIdentifier, [nsIAccessNode]);
|
||||
return getNodePrettyName(acc.DOMNode);
|
||||
}
|
||||
|
||||
if (aIdentifier instanceof nsIDOMNode)
|
||||
return getNodePrettyName(aIdentifier);
|
||||
|
||||
return " '" + aIdentifier + "' ";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -297,3 +313,11 @@ function initialize()
|
||||
}
|
||||
|
||||
addLoadEvent(initialize);
|
||||
|
||||
function getNodePrettyName(aNode)
|
||||
{
|
||||
if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
|
||||
return " '" + aNode.getAttribute("id") + "' ";
|
||||
|
||||
return " '" + aNode.localName + " node' ";
|
||||
}
|
||||
|
@ -24,59 +24,106 @@ const RELATION_SUBWINDOW_OF = nsIAccessibleRelation.RELATION_SUBWINDOW_OF;
|
||||
/**
|
||||
* Test the accessible relation.
|
||||
*
|
||||
* @param aIdentifier [in] identifier to get an accessible implementing
|
||||
* the given interfaces may be ID attribute or DOM
|
||||
* element or accessible object
|
||||
* @param aRelType [in] relation type (see constants above)
|
||||
* @param aRelatedIdentifier [in] identifier of expected related accessible
|
||||
* @param aIdentifier [in] identifier to get an accessible, may be ID
|
||||
* attribute or DOM element or accessible object
|
||||
* @param aRelType [in] relation type (see constants above)
|
||||
* @param aRelatedIdentifiers [in] identifier or array of identifiers of
|
||||
* expected related accessibles
|
||||
*/
|
||||
function testRelation(aIdentifier, aRelType, aRelatedIdentifier)
|
||||
function testRelation(aIdentifier, aRelType, aRelatedIdentifiers)
|
||||
{
|
||||
var actualRelatedAcc = getRelatedAccessible(aIdentifier, aRelType);
|
||||
var relation = getRelationByType(aIdentifier, aRelType);
|
||||
|
||||
var relDescr = getRelationErrorMsg(aIdentifier, aRelType);
|
||||
if (!actualRelatedAcc && !aRelatedIdentifier) {
|
||||
ok(true, "No" + relDescr);
|
||||
var relDescrStart = getRelationErrorMsg(aIdentifier, aRelType, true);
|
||||
|
||||
if (!relation || !relation.targetsCount) {
|
||||
if (!aRelatedIdentifiers) {
|
||||
ok(true, "No" + relDescr);
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = relDescrStart + "has no expected targets: '" +
|
||||
prettyName(aRelatedIdentifiers) + "'";
|
||||
|
||||
ok(false, msg);
|
||||
return;
|
||||
|
||||
} else if (!aRelatedIdentifiers) {
|
||||
ok(false, "There are unexpected targets of " + relDescr);
|
||||
return;
|
||||
}
|
||||
|
||||
var relatedAcc = getAccessible(aRelatedIdentifier);
|
||||
if (!relatedAcc)
|
||||
var relatedIds = (aRelatedIdentifiers instanceof Array) ?
|
||||
aRelatedIdentifiers : [aRelatedIdentifiers];
|
||||
|
||||
var targets = [];
|
||||
for (var idx = 0; idx < relatedIds.length; idx++)
|
||||
targets.push(getAccessible(relatedIds[idx]));
|
||||
|
||||
if (targets.length != relatedIds.length)
|
||||
return;
|
||||
|
||||
is(actualRelatedAcc, relatedAcc,
|
||||
aRelatedIdentifier + " is not a target of" + relDescr);
|
||||
var actualTargets = relation.getTargets();
|
||||
|
||||
// Check if all given related accessibles are targets of obtained relation.
|
||||
for (var idx = 0; idx < targets.length; idx++) {
|
||||
var isFound = false;
|
||||
var enumerate = actualTargets.enumerate();
|
||||
while (enumerate.hasMoreElements()) {
|
||||
var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
|
||||
if (targets[idx] == relatedAcc) {
|
||||
isFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ok(isFound, relatedIds[idx] + " is not a target of" + relDescr);
|
||||
}
|
||||
|
||||
// Check if all obtained targets are given related accessibles.
|
||||
var enumerate = actualTargets.enumerate();
|
||||
while (enumerate.hasMoreElements()) {
|
||||
var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
|
||||
for (var idx = 0; idx < targets.length && relatedAcc != targets[idx]; idx++);
|
||||
|
||||
if (idx == targets.length)
|
||||
ok(false, "There is unexpected target" + prettyName(relatedAcc) + "of" + relDescr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return related accessible for the given relation type.
|
||||
*
|
||||
* @param aIdentifier [in] identifier to get an accessible implementing
|
||||
* the given interfaces may be ID attribute or DOM
|
||||
* element or accessible object
|
||||
* @param aIdentifier [in] identifier to get an accessible, may be ID attribute
|
||||
* or DOM element or accessible object
|
||||
* @param aRelType [in] relation type (see constants above)
|
||||
*/
|
||||
function getRelatedAccessible(aIdentifier, aRelType)
|
||||
function getRelationByType(aIdentifier, aRelType)
|
||||
{
|
||||
var acc = getAccessible(aIdentifier);
|
||||
if (!acc)
|
||||
return;
|
||||
|
||||
var relatedAcc = null;
|
||||
var relation = null;
|
||||
try {
|
||||
relatedAcc = acc.getAccessibleRelated(aRelType);
|
||||
relation = acc.getRelationByType(aRelType);
|
||||
} catch (e) {
|
||||
ok(false, "Can't get" + getRelationErrorMsg(aIdentifier, aRelType));
|
||||
}
|
||||
|
||||
return relatedAcc;
|
||||
return relation;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private implementation details
|
||||
|
||||
function getRelationErrorMsg(aIdentifier, aRelType)
|
||||
function getRelationErrorMsg(aIdentifier, aRelType, aIsStartSentence)
|
||||
{
|
||||
var relStr = relationTypeToString(aRelType);
|
||||
return " relation of '" + relStr + "' type for " + aIdentifier + ".";
|
||||
var msg = aIsStartSentence ? "Relation of '" : " relation of '";
|
||||
msg += relStr + "' type for '" + prettyName(aIdentifier) + "'";
|
||||
msg += aIsStartSentence ? " " : ".";
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
@ -24,17 +24,28 @@
|
||||
testRelation("label2", RELATION_LABEL_FOR, "checkbox2");
|
||||
testRelation("checkbox2", RELATION_LABELLED_BY, "label2");
|
||||
|
||||
// aria-describedby
|
||||
testRelation("descr1", RELATION_DESCRIPTION_FOR, "checkbox3");
|
||||
testRelation("checkbox3", RELATION_DESCRIBED_BY, "descr1");
|
||||
// aria-labelledby, multiple relations
|
||||
testRelation("label3", RELATION_LABEL_FOR, "checkbox3");
|
||||
testRelation("label4", RELATION_LABEL_FOR, "checkbox3");
|
||||
testRelation("checkbox3", RELATION_LABELLED_BY, ["label3", "label4"]);
|
||||
|
||||
// aria_owns
|
||||
// aria-describedby
|
||||
testRelation("descr1", RELATION_DESCRIPTION_FOR, "checkbox4");
|
||||
testRelation("checkbox4", RELATION_DESCRIBED_BY, "descr1");
|
||||
|
||||
// aria-describedby, multiple relations
|
||||
testRelation("descr2", RELATION_DESCRIPTION_FOR, "checkbox5");
|
||||
testRelation("descr3", RELATION_DESCRIPTION_FOR, "checkbox5");
|
||||
testRelation("checkbox5", RELATION_DESCRIBED_BY, ["descr2", "descr3"]);
|
||||
|
||||
// aria_owns, multiple relations
|
||||
testRelation("treeitem1", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
|
||||
|
||||
// 'node child of' relation for outlineitem role
|
||||
testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "treeitem3");
|
||||
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem5", RELATION_NODE_CHILD_OF, "treeitem4");
|
||||
|
||||
// 'node child of' relation for the document having window, returns
|
||||
// direct accessible parent (fixed in bug 419770).
|
||||
@ -48,10 +59,20 @@
|
||||
testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab");
|
||||
testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel");
|
||||
|
||||
// aria-controls, multiple relations
|
||||
testRelation("lr1", RELATION_CONTROLLED_BY, "button");
|
||||
testRelation("lr2", RELATION_CONTROLLED_BY, "button");
|
||||
testRelation("button", RELATION_CONTROLLER_FOR, ["lr1", "lr2"]);
|
||||
|
||||
// aria-flowto
|
||||
testRelation("flowto", RELATION_FLOWS_TO, "flowfrom");
|
||||
testRelation("flowfrom", RELATION_FLOWS_FROM, "flowto");
|
||||
|
||||
// aria-flowto, multiple relations
|
||||
testRelation("flowto1", RELATION_FLOWS_TO, ["flowfrom1", "flowfrom2"]);
|
||||
testRelation("flowfrom1", RELATION_FLOWS_FROM, "flowto1");
|
||||
testRelation("flowfrom2", RELATION_FLOWS_FROM, "flowto1");
|
||||
|
||||
// 'default button' relation
|
||||
testRelation("input", RELATION_DEFAULT_BUTTON, "submit");
|
||||
|
||||
@ -104,16 +125,25 @@
|
||||
<input id="checkbox1" />
|
||||
|
||||
<span id="label2">label</span>
|
||||
<span role="checkbox" id="checkbox2" aria-labelledby="label2" />
|
||||
<span role="checkbox" id="checkbox2" aria-labelledby="label2"></span>
|
||||
|
||||
<span id="label3">label1</span>
|
||||
<span id="label4">label2</span>
|
||||
<span role="checkbox" id="checkbox3" aria-labelledby="label3 label4"></span>
|
||||
|
||||
<span id="descr1">description</span>
|
||||
<span role="checkbox" id="checkbox3" aria-describedby="descr1" />
|
||||
<span role="checkbox" id="checkbox4" aria-describedby="descr1"></span>
|
||||
|
||||
<span id="descr2">description1</span>
|
||||
<span id="descr3">description2</span>
|
||||
<span role="checkbox" id="checkbox5" aria-describedby="descr2 descr3"></span>
|
||||
|
||||
<div role="treeitem" id="treeitem1">Yellow</div>
|
||||
<div id="tree" role="tree" aria-owns="treeitem1">
|
||||
<div role="treeitem" id="treeitem2">Blue</div>
|
||||
<div role="treeitem" id="treeitem3" aria-level="1">Green</div>
|
||||
<div role="treeitem" id="treeitem4" aria-level="2">Light green</div>
|
||||
<div role="treeitem" id="treeitem2">Orange</div>
|
||||
<div id="tree" role="tree" aria-owns="treeitem1 treeitem2">
|
||||
<div role="treeitem" id="treeitem3">Blue</div>
|
||||
<div role="treeitem" id="treeitem4" aria-level="1">Green</div>
|
||||
<div role="treeitem" id="treeitem5" aria-level="2">Light green</div>
|
||||
</div>
|
||||
|
||||
<iframe id="iframe"></iframe>
|
||||
@ -123,9 +153,18 @@
|
||||
</div>
|
||||
<div id="tabpanel" role="tabpanel">tabpanel</div>
|
||||
|
||||
<div id="lr1" aria-live="assertive">1</div>
|
||||
<div id="lr2" aria-live="assertive">a</div>
|
||||
<input type="button" id="button" aria-controls="lr1 lr2"
|
||||
onclick="getNode('lr1').textContent += '1'; getNode('lr2').textContent += 'a';"/>
|
||||
|
||||
<span id="flowto" aria-flowto="flowfrom">flow to</span>
|
||||
<span id="flowfrom">flow from</span>
|
||||
|
||||
<span id="flowto1" aria-flowto="flowfrom1 flowfrom2">flow to</span>
|
||||
<span id="flowfrom1">flow from</span>
|
||||
<span id="flowfrom2">flow from</span>
|
||||
|
||||
<form>
|
||||
<input id="input" />
|
||||
<input type="submit" id="submit" />
|
||||
|
@ -28,21 +28,32 @@
|
||||
testRelation("label2", RELATION_LABEL_FOR, "checkbox2");
|
||||
testRelation("checkbox2", RELATION_LABELLED_BY, "label2");
|
||||
|
||||
// aria-labelledby, multiple relations
|
||||
testRelation("label3", RELATION_LABEL_FOR, "checkbox3");
|
||||
testRelation("label4", RELATION_LABEL_FOR, "checkbox3");
|
||||
testRelation("checkbox3", RELATION_LABELLED_BY, ["label3", "label4"]);
|
||||
|
||||
// aria-describedby
|
||||
testRelation("descr1", RELATION_DESCRIPTION_FOR, "checkbox3");
|
||||
testRelation("checkbox3", RELATION_DESCRIBED_BY, "descr1");
|
||||
testRelation("descr1", RELATION_DESCRIPTION_FOR, "checkbox4");
|
||||
testRelation("checkbox4", RELATION_DESCRIBED_BY, "descr1");
|
||||
|
||||
// aria-describedby, multiple relations
|
||||
testRelation("descr2", RELATION_DESCRIPTION_FOR, "checkbox5");
|
||||
testRelation("descr3", RELATION_DESCRIPTION_FOR, "checkbox5");
|
||||
testRelation("checkbox5", RELATION_DESCRIBED_BY, ["descr2", "descr3"]);
|
||||
|
||||
// xul:description@control
|
||||
testRelation("descr2", RELATION_DESCRIPTION_FOR, "checkbox4");
|
||||
testRelation("checkbox4", RELATION_DESCRIBED_BY, "descr2");
|
||||
testRelation("descr4", RELATION_DESCRIPTION_FOR, "checkbox6");
|
||||
testRelation("checkbox6", RELATION_DESCRIBED_BY, "descr4");
|
||||
|
||||
// aria_owns
|
||||
// aria_owns, multiple relations
|
||||
testRelation("treeitem1", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
|
||||
|
||||
// 'node child of' relation for outlineitem role
|
||||
testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "treeitem3");
|
||||
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem5", RELATION_NODE_CHILD_OF, "treeitem4");
|
||||
|
||||
// 'node child of' relation for the document having window, returns
|
||||
// direct accessible parent (fixed in bug 419770).
|
||||
@ -56,10 +67,20 @@
|
||||
testRelation("tabpanel", RELATION_CONTROLLED_BY, "tab");
|
||||
testRelation("tab", RELATION_CONTROLLER_FOR, "tabpanel");
|
||||
|
||||
// aria-controls, multiple relations
|
||||
testRelation("lr1", RELATION_CONTROLLED_BY, "button");
|
||||
testRelation("lr2", RELATION_CONTROLLED_BY, "button");
|
||||
testRelation("button", RELATION_CONTROLLER_FOR, ["lr1", "lr2"]);
|
||||
|
||||
// aria-flowto
|
||||
testRelation("flowto", RELATION_FLOWS_TO, "flowfrom");
|
||||
testRelation("flowfrom", RELATION_FLOWS_FROM, "flowto");
|
||||
|
||||
// aria-flowto, multiple relations
|
||||
testRelation("flowto1", RELATION_FLOWS_TO, ["flowfrom1", "flowfrom2"]);
|
||||
testRelation("flowfrom1", RELATION_FLOWS_FROM, "flowto1");
|
||||
testRelation("flowfrom2", RELATION_FLOWS_FROM, "flowto1");
|
||||
|
||||
// 'default button' relation
|
||||
testRelation("textbox", RELATION_DEFAULT_BUTTON, "submit");
|
||||
|
||||
@ -113,17 +134,28 @@
|
||||
<description id="label2">label</description>
|
||||
<description role="checkbox" id="checkbox2" aria-labelledby="label2"/>
|
||||
|
||||
<description id="descr1">description</description>
|
||||
<description role="checkbox" id="checkbox3" aria-describedby="descr1"/>
|
||||
<description id="label3">label</description>
|
||||
<description id="label4">label</description>
|
||||
<description role="checkbox" id="checkbox3"
|
||||
aria-labelledby="label3 label4"/>
|
||||
|
||||
<description id="descr2" control="checkbox4">description</description>
|
||||
<checkbox id="checkbox4"/>
|
||||
<description id="descr1">description</description>
|
||||
<description role="checkbox" id="checkbox4" aria-describedby="descr1"/>
|
||||
|
||||
<description id="descr2">label</description>
|
||||
<description id="descr3">label</description>
|
||||
<description role="checkbox" id="checkbox5"
|
||||
aria-describedby="descr2 descr3"/>
|
||||
|
||||
<description id="descr4" control="checkbox6">description</description>
|
||||
<checkbox id="checkbox6"/>
|
||||
|
||||
<description role="treeitem" id="treeitem1">Yellow</description>
|
||||
<vbox id="tree" role="tree" aria-owns="treeitem1">
|
||||
<description role="treeitem" id="treeitem2">Blue</description>
|
||||
<description role="treeitem" id="treeitem3" aria-level="1">Green</description>
|
||||
<description role="treeitem" id="treeitem4" aria-level="2">Light green</description>
|
||||
<description role="treeitem" id="treeitem2">Orange</description>
|
||||
<vbox id="tree" role="tree" aria-owns="treeitem1 treeitem2">
|
||||
<description role="treeitem" id="treeitem3">Blue</description>
|
||||
<description role="treeitem" id="treeitem4" aria-level="1">Green</description>
|
||||
<description role="treeitem" id="treeitem5" aria-level="2">Light green</description>
|
||||
</vbox>
|
||||
|
||||
<iframe id="iframe"/>
|
||||
@ -133,6 +165,15 @@
|
||||
</hbox>
|
||||
<description id="tabpanel" role="tabpanel">tabpanel</description>
|
||||
|
||||
<description id="lr1" aria-live="assertive">1</description>
|
||||
<description id="lr2" aria-live="assertive">a</description>
|
||||
<button id="button" aria-controls="lr1 lr2" label="button"
|
||||
oncommand="getNode('lr1').textContent += '1'; getNode('lr2').textContent += 'a';"/>
|
||||
|
||||
<description id="flowto1" aria-flowto="flowfrom1 flowfrom2">flow to</description>
|
||||
<description id="flowfrom1">flow from</description>
|
||||
<description id="flowfrom2">flow from</description>
|
||||
|
||||
<description id="flowto" aria-flowto="flowfrom">flow to</description>
|
||||
<description id="flowfrom">flow from</description>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user