Bug 656379 part 2. Make labels expose a nicer API for getting their labeled content. r=smaug

This commit is contained in:
Boris Zbarsky 2011-05-24 20:18:31 -04:00
parent ca59214f04
commit 5d28b8f140

View File

@ -56,6 +56,7 @@
// construction, destruction
using namespace mozilla::dom;
NS_IMPL_NS_NEW_HTML_ELEMENT(Label)
@ -105,8 +106,7 @@ nsHTMLLabelElement::GetControl(nsIDOMHTMLElement** aElement)
{
*aElement = nsnull;
nsCOMPtr<nsIContent> content = GetControlContent();
nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(content);
nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(GetLabeledElement());
element.swap(*aElement);
return NS_OK;
@ -121,9 +121,7 @@ nsHTMLLabelElement::Focus()
// retarget the focus method at the for content
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIContent> content = GetControlContent();
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetLabeledElement());
if (elem)
fm->SetFocus(elem, 0);
}
@ -187,7 +185,8 @@ nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
return NS_OK;
}
nsCOMPtr<nsIContent> content = GetControlContent();
// Strong ref because event dispatch is going to happen.
nsRefPtr<Element> content = GetLabeledElement();
if (content && !EventTargetIn(aVisitor.mEvent, content, this)) {
mHandlingEvent = PR_TRUE;
@ -299,9 +298,9 @@ nsHTMLLabelElement::PerformAccesskey(PRBool aKeyCausesActivation,
PRBool aIsTrustedEvent)
{
if (!aKeyCausesActivation) {
nsCOMPtr<nsIContent> content = GetControlContent();
if (content)
content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
nsRefPtr<Element> element = GetLabeledElement();
if (element)
element->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
} else {
nsPresContext *presContext = GetPresContext();
if (!presContext)
@ -320,15 +319,15 @@ nsHTMLLabelElement::PerformAccesskey(PRBool aKeyCausesActivation,
}
}
already_AddRefed<nsIContent>
nsHTMLLabelElement::GetControlContent()
Element*
nsHTMLLabelElement::GetLabeledElement()
{
nsAutoString elementId;
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_for, elementId)) {
// No @for, so we are a label for our first form control element.
// Do a depth-first traversal to look for the first form control element.
return GetFirstFormControl(this);
return GetFirstDescendantFormControl();
}
// We have a @for. The id has to be linked to an element in the same document
@ -338,41 +337,31 @@ nsHTMLLabelElement::GetControlContent()
return nsnull;
}
nsIContent* content = doc->GetElementById(elementId);
if (!content) {
Element* element = doc->GetElementById(elementId);
if (!element) {
return nsnull;
}
nsCOMPtr<nsIFormControl> element = do_QueryInterface(content);
if (element && element->IsLabelableControl()) {
nsCOMPtr<nsIFormControl> controlElement = do_QueryInterface(element);
if (controlElement && controlElement->IsLabelableControl()) {
// Transfer the reference count of element to the returned value.
element.forget();
return content;
return element;
}
return nsnull;
}
already_AddRefed<nsIContent>
nsHTMLLabelElement::GetFirstFormControl(nsIContent *current)
Element*
nsHTMLLabelElement::GetFirstDescendantFormControl()
{
PRUint32 numNodes = current->GetChildCount();
for (PRUint32 i = 0; i < numNodes; i++) {
nsIContent *child = current->GetChildAt(i);
if (!child) {
continue;
}
nsCOMPtr<nsIFormControl> element = do_QueryInterface(child);
// Have to cast do disambiguate GetFirstChild from the DOM method of that name
for (nsINode* cur = static_cast<nsINode*>(this)->GetFirstChild();
cur;
cur = cur->GetNextNode(this)) {
nsCOMPtr<nsIFormControl> element = do_QueryInterface(cur);
if (element && element->IsLabelableControl()) {
NS_ADDREF(child);
return child;
}
nsIContent* content = GetFirstFormControl(child).get();
if (content) {
return content;
NS_ASSERTION(cur->IsElement(), "How did that happen?");
return cur->AsElement();
}
}