Bug 562932 - "Implement control attribute for label element" [r=sicking sr=smaug]

This commit is contained in:
Mounir Lamouri 2010-05-19 22:28:10 -04:00
Родитель ac24ebce4f
Коммит 095c2fe26e
8 изменённых файлов: 146 добавлений и 45 удалений

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

@ -1358,6 +1358,15 @@ public:
virtual void ResetScrolledToRefAlready() = 0;
virtual void SetChangeScrollPosWhenScrollingToRef(PRBool aValue) = 0;
/**
* This method is similar to GetElementById() from nsIDOMDocument but it
* returns a mozilla::dom::Element instead of a nsIDOMElement.
* It prevents converting nsIDOMElement to mozill:dom::Element which is
* already converted from mozilla::dom::Element.
*/
virtual mozilla::dom::Element* GetElementById(const nsAString& aElementId,
nsresult* aResult) = 0;
protected:
~nsIDocument()
{

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

@ -174,6 +174,12 @@ public:
* @return Whether this is a single line text control.
*/
virtual PRBool IsSingleLineTextControl(PRBool aExcludePassword) const = 0;
/**
* Returns true if this is a labelable form control.
* @return Whether this is a labelable form control.
*/
virtual PRBool IsLabelableControl() const = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFormControl, NS_IFORMCONTROL_IID)

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

@ -2686,6 +2686,20 @@ nsGenericHTMLFormElement::IsSingleLineTextControl(PRBool aExcludePassword) const
(!aExcludePassword && type == NS_FORM_INPUT_PASSWORD);
}
PRBool
nsGenericHTMLFormElement::IsLabelableControl() const
{
// Check for non-labelable form controls as they are not numerous.
// TODO: datalist should be added to this list.
PRInt32 type = GetType();
return type != NS_FORM_FIELDSET &&
type != NS_FORM_LABEL &&
type != NS_FORM_OPTION &&
type != NS_FORM_OPTGROUP &&
type != NS_FORM_OBJECT &&
type != NS_FORM_LEGEND;
}
PRInt32
nsGenericHTMLFormElement::IntrinsicState() const
{

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

@ -793,6 +793,8 @@ public:
PRBool IsSingleLineTextControl(PRBool aExcludePassword) const;
PRBool IsLabelableControl() const;
// nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,

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

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIDOMHTMLLabelElement.h"
#include "nsIDOMNSHTMLLabelElement.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
@ -53,7 +54,8 @@
#include "nsFocusManager.h"
class nsHTMLLabelElement : public nsGenericHTMLFormElement,
public nsIDOMHTMLLabelElement
public nsIDOMHTMLLabelElement,
public nsIDOMNSHTMLLabelElement
{
public:
nsHTMLLabelElement(nsINodeInfo *aNodeInfo);
@ -74,6 +76,9 @@ public:
// nsIDOMHTMLLabelElement
NS_DECL_NSIDOMHTMLLABELELEMENT
// nsIDOMNSHTMLLabelElement
NS_DECL_NSIDOMNSHTMLLABELELEMENT
// nsIFormControl
NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_LABEL; }
NS_IMETHOD Reset();
@ -106,7 +111,7 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
already_AddRefed<nsIContent> GetForContent();
already_AddRefed<nsIContent> GetControlContent();
already_AddRefed<nsIContent> GetFirstFormControl(nsIContent *current);
// XXX It would be nice if we could use an event flag instead.
@ -140,7 +145,9 @@ DOMCI_DATA(HTMLLabelElement, nsHTMLLabelElement)
// QueryInterface implementation for nsHTMLLabelElement
NS_INTERFACE_TABLE_HEAD(nsHTMLLabelElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLLabelElement, nsIDOMHTMLLabelElement)
NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLLabelElement,
nsIDOMHTMLLabelElement,
nsIDOMNSHTMLLabelElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLLabelElement,
nsGenericHTMLFormElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLLabelElement)
@ -158,6 +165,18 @@ nsHTMLLabelElement::GetForm(nsIDOMHTMLFormElement** aForm)
return nsGenericHTMLFormElement::GetForm(aForm);
}
NS_IMETHODIMP
nsHTMLLabelElement::GetControl(nsIDOMHTMLElement** aElement)
{
*aElement = nsnull;
nsCOMPtr<nsIContent> content = GetControlContent();
nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(content);
element.swap(*aElement);
return NS_OK;
}
NS_IMPL_STRING_ATTR(nsHTMLLabelElement, AccessKey, accesskey)
NS_IMPL_STRING_ATTR(nsHTMLLabelElement, HtmlFor, _for)
@ -168,7 +187,8 @@ nsHTMLLabelElement::Focus()
// retarget the focus method at the for content
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIContent> content = GetForContent();
nsCOMPtr<nsIContent> content = GetControlContent();
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
if (elem)
fm->SetFocus(elem, 0);
@ -244,7 +264,8 @@ nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
return NS_OK;
}
nsCOMPtr<nsIContent> content = GetForContent();
nsCOMPtr<nsIContent> content = GetControlContent();
if (content && !EventTargetIn(aVisitor.mEvent, content, this)) {
mHandlingEvent = PR_TRUE;
switch (aVisitor.mEvent->message) {
@ -373,7 +394,7 @@ nsHTMLLabelElement::PerformAccesskey(PRBool aKeyCausesActivation,
PRBool aIsTrustedEvent)
{
if (!aKeyCausesActivation) {
nsCOMPtr<nsIContent> content = GetForContent();
nsCOMPtr<nsIContent> content = GetControlContent();
if (content)
content->PerformAccesskey(aKeyCausesActivation, aIsTrustedEvent);
} else {
@ -394,41 +415,37 @@ nsHTMLLabelElement::PerformAccesskey(PRBool aKeyCausesActivation,
}
}
inline PRBool IsNonLabelFormControl(nsIContent *aContent)
{
return aContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) &&
aContent->Tag() != nsGkAtoms::label;
}
already_AddRefed<nsIContent>
nsHTMLLabelElement::GetForContent()
nsHTMLLabelElement::GetControlContent()
{
nsresult rv;
// Get the element that this label is for
nsAutoString elementId;
rv = GetHtmlFor(elementId);
if (NS_SUCCEEDED(rv) && !elementId.IsEmpty()) {
// We have a FOR attribute.
nsCOMPtr<nsIDOMDocument> domDoc;
GetOwnerDocument(getter_AddRefs(domDoc));
if (domDoc) {
nsCOMPtr<nsIDOMElement> domElement;
domDoc->GetElementById(elementId, getter_AddRefs(domElement));
nsIContent *result = nsnull;
if (domElement) {
CallQueryInterface(domElement, &result);
if (result && !IsNonLabelFormControl(result)) {
NS_RELEASE(result); // assigns null
}
}
return result;
}
} else {
// No FOR attribute, we are a label for our first form control element.
// do a depth-first traversal to look for the first form control element
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);
}
// We have a @for. The id has to be linked to an element in the same document
// and this element should be a labelable form control.
nsIDocument* doc = GetCurrentDoc();
if (!doc) {
return nsnull;
}
nsresult rv;
nsIContent* content = doc->GetElementById(elementId, &rv);
NS_ENSURE_SUCCESS(rv, nsnull);
if (!content) {
return nsnull;
}
nsCOMPtr<nsIFormControl> element = do_QueryInterface(content);
if (element && element->IsLabelableControl()) {
NS_ADDREF(content);
return content;
}
return nsnull;
}
@ -439,18 +456,22 @@ nsHTMLLabelElement::GetFirstFormControl(nsIContent *current)
for (PRUint32 i = 0; i < numNodes; i++) {
nsIContent *child = current->GetChildAt(i);
if (child) {
if (IsNonLabelFormControl(child)) {
NS_ADDREF(child);
return child;
}
if (!child) {
continue;
}
nsIContent* content = GetFirstFormControl(child).get();
if (content) {
return content;
}
nsCOMPtr<nsIFormControl> element = do_QueryInterface(child);
if (element && element->IsLabelableControl()) {
NS_ADDREF(child);
return child;
}
nsIContent* content = GetFirstFormControl(child).get();
if (content) {
return content;
}
}
return nsnull;
}

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

@ -280,6 +280,7 @@
#include "nsIDOMHTMLIsIndexElement.h"
#include "nsIDOMHTMLLIElement.h"
#include "nsIDOMHTMLLabelElement.h"
#include "nsIDOMNSHTMLLabelElement.h"
#include "nsIDOMHTMLLegendElement.h"
#include "nsIDOMHTMLLinkElement.h"
#include "nsIDOMHTMLMapElement.h"
@ -2477,6 +2478,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(HTMLLabelElement, nsIDOMHTMLLabelElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLLabelElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLLabelElement)
DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
DOM_CLASSINFO_MAP_END

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

@ -128,6 +128,7 @@ XPIDLSRCS = \
nsIDOMNSHTMLHRElement.idl \
nsIDOMNSHTMLImageElement.idl \
nsIDOMNSHTMLInputElement.idl \
nsIDOMNSHTMLLabelElement.idl \
nsIDOMNSHTMLOptionCollectn.idl \
nsIDOMNSHTMLOptionElement.idl \
nsIDOMNSHTMLSelectElement.idl \

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

@ -0,0 +1,46 @@
/* -*- Mode: IDL; 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) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mounir Lamouri <mounir.lamouri@mozilla.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 "domstubs.idl"
interface nsIDOMHTMLElement;
[scriptable, uuid(93e8a513-6cef-44c3-875e-1bce83c3b1f0)]
interface nsIDOMNSHTMLLabelElement : nsISupports
{
readonly attribute nsIDOMHTMLElement control;
};