Bug 573469 - part1, add iterator for IDRefs elements, r=fherrera, sr=neil, a=blockingFinal+

This commit is contained in:
Alexander Surkov 2010-11-16 22:32:15 -05:00
Родитель b17c3a82d2
Коммит 99e3c36599
5 изменённых файлов: 126 добавлений и 128 удалений

Просмотреть файл

@ -47,7 +47,6 @@
#include "nsIDOM3Node.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentView.h"
#include "nsIDOMDocumentXBL.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMNodeList.h"
@ -805,67 +804,6 @@ 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<nsIDOMDocumentXBL> xblDocument;
if (aContent->IsInAnonymousSubtree())
xblDocument = do_QueryInterface(document);
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);
}
// If content is anonymous subtree then use "anonid" attribute to get
// elements, otherwise search elements in DOM by ID attribute.
nsCOMPtr<nsIDOMElement> refElement;
if (xblDocument) {
nsCOMPtr<nsIDOMElement> elm =
do_QueryInterface(aContent->GetBindingParent());
xblDocument->GetAnonymousElementByAttribute(elm,
NS_LITERAL_STRING("anonid"),
id,
getter_AddRefs(refElement));
} else {
document->GetElementById(id, getter_AddRefs(refElement));
}
if (!refElement)
continue;
refElms->AppendElement(refElement, PR_FALSE);
}
NS_ADDREF(*aRefElements = refElms);
return;
}
void
nsCoreUtils::GetElementsHavingIDRefsAttr(nsIContent *aRootContent,
nsIContent *aContent,
@ -1165,3 +1103,74 @@ nsAccessibleDOMStringList::Contains(const nsAString& aString, PRBool *aResult)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// IDRefsIterator
////////////////////////////////////////////////////////////////////////////////
IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
mCurrIdx(0)
{
if (!aContent->IsInDoc() ||
!aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
return;
if (aContent->IsInAnonymousSubtree()) {
mXBLDocument = do_QueryInterface(aContent->GetOwnerDoc());
mBindingParent = do_QueryInterface(aContent->GetBindingParent());
} else {
mDocument = aContent->GetOwnerDoc();
}
}
const nsDependentSubstring
IDRefsIterator::NextID()
{
for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
break;
}
if (mCurrIdx >= mIDs.Length())
return nsDependentSubstring();
nsAString::index_type idStartIdx = mCurrIdx;
while (++mCurrIdx < mIDs.Length()) {
if (NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
break;
}
return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
}
nsIContent*
IDRefsIterator::NextElem()
{
while (true) {
const nsDependentSubstring id = NextID();
if (id.IsEmpty())
break;
if (mXBLDocument) {
// If content is anonymous subtree then use "anonid" attribute to get
// elements, otherwise search elements in DOM by ID attribute.
nsCOMPtr<nsIDOMElement> refElm;
mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
NS_LITERAL_STRING("anonid"),
id,
getter_AddRefs(refElm));
nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
if (refContent)
return refContent;
} else {
nsIContent* refContent = mDocument->GetElementById(id);
if (refContent)
return refContent;
}
}
return nsnull;
}

Просмотреть файл

@ -41,6 +41,7 @@
#include "nsAccessibilityAtoms.h"
#include "nsIDOMDocumentXBL.h"
#include "nsIDOMNode.h"
#include "nsIContent.h"
#include "nsIBoxObject.h"
@ -304,17 +305,6 @@ 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 the array of elements having IDRefs that points to the given node.
*
@ -515,5 +505,34 @@ private:
nsTArray<nsString> mNames;
};
/**
* Used to iterate through IDs or elements pointed by IDRefs attribute. Note,
* any method used to iterate through IDs or elements moves iterator to next
* position.
*/
class IDRefsIterator
{
public:
IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr);
/**
* Return next ID.
*/
const nsDependentSubstring NextID();
/**
* Return next element.
*/
nsIContent* NextElem();
private:
nsString mIDs;
nsAString::index_type mCurrIdx;
nsIDocument* mDocument;
nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
nsCOMPtr<nsIDOMElement> mBindingParent;
};
#endif

Просмотреть файл

@ -134,27 +134,16 @@ nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType,
nsIAccessibleRelation **aRelation,
nsIContent *aContent, nsIAtom *aAttr)
{
nsCOMPtr<nsIArray> refElms;
nsCoreUtils::GetElementsByIDRefsAttr(aContent, aAttr, getter_AddRefs(refElms));
nsresult rv = NS_OK_NO_RELATION_TARGET;
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);
nsIContent* refElm = nsnull;
IDRefsIterator iter(aContent, aAttr);
while ((refElm = iter.NextElem())) {
rv = AddTargetFromContent(aRelationType, aRelation, refElm);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
return rv;
}
nsresult

Просмотреть файл

@ -92,26 +92,14 @@ nsTextEquivUtils::GetTextEquivFromIDRefs(nsAccessible *aAccessible,
if (!content)
return NS_OK;
nsCOMPtr<nsIArray> refElms;
nsCoreUtils::GetElementsByIDRefsAttr(content, aIDRefsAttr,
getter_AddRefs(refElms));
if (!refElms)
return NS_OK;
PRUint32 count = 0;
nsresult rv = refElms->GetLength(&count);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> refContent;
for (PRUint32 idx = 0; idx < count; idx++) {
refContent = do_QueryElementAt(refElms, idx, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsIContent* refContent = nsnull;
IDRefsIterator iter(content, aIDRefsAttr);
while ((refContent = iter.NextElem())) {
if (!aTextEquiv.IsEmpty())
aTextEquiv += ' ';
rv = AppendTextEquivFromContent(aAccessible, refContent, &aTextEquiv);
nsresult rv = AppendTextEquivFromContent(aAccessible, refContent,
&aTextEquiv);
NS_ENSURE_SUCCESS(rv, rv);
}

Просмотреть файл

@ -308,34 +308,27 @@ nsHTMLTableCellAccessible::GetHeaderCells(PRInt32 aRowOrColumnHeaderCell,
nsIArray **aHeaderCells)
{
// Get header cells from @header attribute.
nsCOMPtr<nsIArray> headerCellElms;
nsCoreUtils::GetElementsByIDRefsAttr(mContent, nsAccessibilityAtoms::headers,
getter_AddRefs(headerCellElms));
if (headerCellElms) {
IDRefsIterator iter(mContent, nsAccessibilityAtoms::headers);
nsIContent* headerCellElm = iter.NextElem();
if (headerCellElm) {
nsresult rv = NS_OK;
nsCOMPtr<nsIMutableArray> headerCells =
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 count = 0;
rv = headerCellElms->GetLength(&count);
if (NS_SUCCEEDED(rv) && count > 0) {
nsCOMPtr<nsIContent> headerCellContent;
for (PRUint32 idx = 0; idx < count; idx++) {
headerCellContent = do_QueryElementAt(headerCellElms, idx, &rv);
nsAccessible *headerCell =
GetAccService()->GetAccessibleInWeakShell(headerCellContent, mWeakShell);
do {
nsAccessible* headerCell =
GetAccService()->GetAccessibleInWeakShell(headerCellElm, mWeakShell);
if (headerCell &&
(aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells &&
headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER ||
aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells &&
headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER))
headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell),
PR_FALSE);
if (headerCell &&
(aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells &&
headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER ||
aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells &&
headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER)) {
headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell),
PR_FALSE);
}
}
} while ((headerCellElm = iter.NextElem()));
NS_ADDREF(*aHeaderCells = headerCells);
return NS_OK;