зеркало из https://github.com/mozilla/pjs.git
Bug 562932 - "Implement control attribute for label element" [r=sicking sr=smaug]
This commit is contained in:
Родитель
ac24ebce4f
Коммит
095c2fe26e
|
@ -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;
|
||||
};
|
Загрузка…
Ссылка в новой задаче