зеркало из https://github.com/mozilla/gecko-dev.git
Bug 641720 - Make nsHTMLInputElement::GetRadioGroupContainer saner. r=sicking,bz
This commit is contained in:
Родитель
fc2edaedef
Коммит
9f9b93131e
|
@ -71,6 +71,7 @@
|
||||||
#include "nsIEditor.h"
|
#include "nsIEditor.h"
|
||||||
#include "nsGUIEvent.h"
|
#include "nsGUIEvent.h"
|
||||||
#include "nsIIOService.h"
|
#include "nsIIOService.h"
|
||||||
|
#include "nsDocument.h"
|
||||||
|
|
||||||
#include "nsPresState.h"
|
#include "nsPresState.h"
|
||||||
#include "nsLayoutErrors.h"
|
#include "nsLayoutErrors.h"
|
||||||
|
@ -909,12 +910,13 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
||||||
nsCOMPtr<nsIRadioGroupContainer> c = GetRadioGroupContainer();
|
nsIRadioGroupContainer* c = GetRadioGroupContainer();
|
||||||
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
|
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
|
||||||
do_QueryInterface(c);
|
do_QueryInterface(c);
|
||||||
nsAutoString name;
|
|
||||||
|
|
||||||
if (container && GetNameIfExists(name)) {
|
if (container) {
|
||||||
|
nsAutoString name;
|
||||||
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
container->RadioRequiredChanged(name, this);
|
container->RadioRequiredChanged(name, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1576,12 +1578,11 @@ nsHTMLInputElement::DoSetChecked(PRBool aChecked, PRBool aNotify,
|
||||||
if (aChecked) {
|
if (aChecked) {
|
||||||
rv = RadioSetChecked(aNotify);
|
rv = RadioSetChecked(aNotify);
|
||||||
} else {
|
} else {
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
if (container) {
|
if (container) {
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
if (GetNameIfExists(name)) {
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
container->SetCurrentRadioButton(name, nsnull);
|
container->SetCurrentRadioButton(name, nsnull);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// SetCheckedInternal is going to ask all radios to update their
|
// SetCheckedInternal is going to ask all radios to update their
|
||||||
// validity state. We have to be sure the radio group container knows
|
// validity state. We have to be sure the radio group container knows
|
||||||
|
@ -1618,9 +1619,10 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
|
||||||
//
|
//
|
||||||
// Let the group know that we are now the One True Radio Button
|
// Let the group know that we are now the One True Radio Button
|
||||||
//
|
//
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
nsAutoString name;
|
if (container) {
|
||||||
if (container && GetNameIfExists(name)) {
|
nsAutoString name;
|
||||||
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
rv = container->SetCurrentRadioButton(name, this);
|
rv = container->SetCurrentRadioButton(name, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1634,35 +1636,38 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ already_AddRefed<nsIRadioGroupContainer>
|
nsIRadioGroupContainer*
|
||||||
nsHTMLInputElement::GetRadioGroupContainer()
|
nsHTMLInputElement::GetRadioGroupContainer() const
|
||||||
{
|
{
|
||||||
nsIRadioGroupContainer* retval = nsnull;
|
NS_ASSERTION(mType == NS_FORM_INPUT_RADIO,
|
||||||
if (mForm) {
|
"GetRadioGroupContainer should only be called when type='radio'");
|
||||||
CallQueryInterface(mForm, &retval);
|
|
||||||
} else {
|
nsAutoString name;
|
||||||
nsIDocument* currentDoc = GetCurrentDoc();
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
if (currentDoc) {
|
|
||||||
CallQueryInterface(currentDoc, &retval);
|
if (name.IsEmpty()) {
|
||||||
}
|
return nsnull;
|
||||||
}
|
}
|
||||||
return retval;
|
|
||||||
|
if (mForm) {
|
||||||
|
return mForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<nsDocument*>(GetCurrentDoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIDOMHTMLInputElement>
|
already_AddRefed<nsIDOMHTMLInputElement>
|
||||||
nsHTMLInputElement::GetSelectedRadioButton()
|
nsHTMLInputElement::GetSelectedRadioButton()
|
||||||
{
|
{
|
||||||
nsIDOMHTMLInputElement* selected;
|
nsIDOMHTMLInputElement* selected;
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
|
|
||||||
if (!container) {
|
if (!container) {
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
if (!GetNameIfExists(name)) {
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
return nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
container->GetCurrentRadioButton(name, &selected);
|
container->GetCurrentRadioButton(name, &selected);
|
||||||
return selected;
|
return selected;
|
||||||
|
@ -2279,29 +2284,28 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||||
case NS_VK_DOWN:
|
case NS_VK_DOWN:
|
||||||
case NS_VK_RIGHT:
|
case NS_VK_RIGHT:
|
||||||
// Arrow key pressed, focus+select prev/next radio button
|
// Arrow key pressed, focus+select prev/next radio button
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
if (container) {
|
if (container) {
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
if (GetNameIfExists(name)) {
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
|
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
|
||||||
container->GetNextRadioButton(name, isMovingBack, this,
|
container->GetNextRadioButton(name, isMovingBack, this,
|
||||||
getter_AddRefs(selectedRadioButton));
|
getter_AddRefs(selectedRadioButton));
|
||||||
nsCOMPtr<nsIContent> radioContent =
|
nsCOMPtr<nsIContent> radioContent =
|
||||||
do_QueryInterface(selectedRadioButton);
|
do_QueryInterface(selectedRadioButton);
|
||||||
if (radioContent) {
|
if (radioContent) {
|
||||||
rv = selectedRadioButton->Focus();
|
rv = selectedRadioButton->Focus();
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
|
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
|
||||||
|
NS_MOUSE_CLICK, nsnull,
|
||||||
|
nsMouseEvent::eReal);
|
||||||
|
event.inputSource = nsIDOMNSMouseEvent::MOZ_SOURCE_KEYBOARD;
|
||||||
|
rv = nsEventDispatcher::Dispatch(radioContent,
|
||||||
|
aVisitor.mPresContext,
|
||||||
|
&event, nsnull, &status);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||||
nsMouseEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
|
|
||||||
NS_MOUSE_CLICK, nsnull,
|
|
||||||
nsMouseEvent::eReal);
|
|
||||||
event.inputSource = nsIDOMNSMouseEvent::MOZ_SOURCE_KEYBOARD;
|
|
||||||
rv = nsEventDispatcher::Dispatch(radioContent,
|
|
||||||
aVisitor.mPresContext,
|
|
||||||
&event, nsnull, &status);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3406,69 +3410,40 @@ nsHTMLInputElement::AddedToRadioGroup()
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
||||||
if (container) {
|
if (container) {
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
if (GetNameIfExists(name)) {
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
container->AddToRadioGroup(name, static_cast<nsIFormControl*>(this));
|
container->AddToRadioGroup(name, static_cast<nsIFormControl*>(this));
|
||||||
|
|
||||||
// We initialize the validity of the element to the validity of the group
|
// We initialize the validity of the element to the validity of the group
|
||||||
// because we assume UpdateValueMissingState() will be called after.
|
// because we assume UpdateValueMissingState() will be called after.
|
||||||
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container2 =
|
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container2 =
|
||||||
do_QueryInterface(container);
|
do_QueryInterface(container);
|
||||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING,
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING,
|
||||||
container2->GetValueMissingState(name));
|
container2->GetValueMissingState(name));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHTMLInputElement::WillRemoveFromRadioGroup()
|
nsHTMLInputElement::WillRemoveFromRadioGroup()
|
||||||
{
|
{
|
||||||
//
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
// If the input element is not in a form and
|
if (!container) {
|
||||||
// not in a document, we just need to return.
|
|
||||||
//
|
|
||||||
if (!mForm && !(IsInDoc() && GetParent())) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
nsAutoString name;
|
||||||
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
|
|
||||||
// If this button was checked, we need to notify the group that there is no
|
// If this button was checked, we need to notify the group that there is no
|
||||||
// longer a selected radio button
|
// longer a selected radio button
|
||||||
//
|
|
||||||
nsAutoString name;
|
|
||||||
PRBool gotName = PR_FALSE;
|
|
||||||
if (GetChecked()) {
|
if (GetChecked()) {
|
||||||
if (!gotName) {
|
container->SetCurrentRadioButton(name, nsnull);
|
||||||
if (!GetNameIfExists(name)) {
|
|
||||||
// If the name doesn't exist, nothing is going to happen anyway
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gotName = PR_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
|
||||||
if (container) {
|
|
||||||
container->SetCurrentRadioButton(name, nsnull);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Remove this radio from its group in the container.
|
||||||
// Remove this radio from its group in the container
|
// We need to call UpdateValueMissingValidityStateForRadio before to make sure
|
||||||
//
|
// the group validity is updated (with this element being ignored).
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
UpdateValueMissingValidityStateForRadio(true);
|
||||||
if (container) {
|
container->RemoveFromRadioGroup(name, static_cast<nsIFormControl*>(this));
|
||||||
if (!gotName) {
|
|
||||||
if (!GetNameIfExists(name)) {
|
|
||||||
// If the name doesn't exist, nothing is going to happen anyway
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gotName = PR_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateValueMissingValidityStateForRadio(true);
|
|
||||||
|
|
||||||
container->RemoveFromRadioGroup(name,
|
|
||||||
static_cast<nsIFormControl*>(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -3529,13 +3504,15 @@ nsHTMLInputElement::IsHTMLFocusable(PRBool aWithMouse, PRBool *aIsFocusable, PRI
|
||||||
|
|
||||||
// Current radio button is not selected.
|
// Current radio button is not selected.
|
||||||
// But make it tabbable if nothing in group is selected.
|
// But make it tabbable if nothing in group is selected.
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
nsAutoString name;
|
if (!container) {
|
||||||
if (!container || !GetNameIfExists(name)) {
|
|
||||||
*aIsFocusable = defaultFocusable;
|
*aIsFocusable = defaultFocusable;
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoString name;
|
||||||
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
|
nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
|
||||||
container->GetCurrentRadioButton(name, getter_AddRefs(currentRadio));
|
container->GetCurrentRadioButton(name, getter_AddRefs(currentRadio));
|
||||||
if (currentRadio) {
|
if (currentRadio) {
|
||||||
|
@ -3548,19 +3525,15 @@ nsHTMLInputElement::IsHTMLFocusable(PRBool aWithMouse, PRBool *aIsFocusable, PRI
|
||||||
nsresult
|
nsresult
|
||||||
nsHTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, PRBool aFlushContent)
|
nsHTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor, PRBool aFlushContent)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
|
||||||
if (container) {
|
if (container) {
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
if (GetNameIfExists(name)) {
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
rv = container->WalkRadioGroup(name, aVisitor, aFlushContent);
|
return container->WalkRadioGroup(name, aVisitor, aFlushContent);
|
||||||
} else {
|
|
||||||
aVisitor->Visit(this);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
aVisitor->Visit(this);
|
|
||||||
}
|
}
|
||||||
return rv;
|
|
||||||
|
aVisitor->Visit(this);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsHTMLInputElement::ValueModeType
|
nsHTMLInputElement::ValueModeType
|
||||||
|
@ -3839,15 +3812,21 @@ nsHTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
||||||
: HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
: HasAttr(kNameSpaceID_None, nsGkAtoms::required);
|
||||||
bool valueMissing = false;
|
bool valueMissing = false;
|
||||||
|
|
||||||
nsCOMPtr<nsIRadioGroupContainer> c = GetRadioGroupContainer();
|
nsIRadioGroupContainer* c = GetRadioGroupContainer();
|
||||||
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
|
nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
|
||||||
do_QueryInterface(c);
|
do_QueryInterface(c);
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING, required && !selected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
GetNameIfExists(name);
|
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||||
|
|
||||||
// If the current radio is required and not ignored, we can assume the entire
|
// If the current radio is required and not ignored, we can assume the entire
|
||||||
// group is required.
|
// group is required.
|
||||||
if (!required && container && !name.IsEmpty()) {
|
if (!required) {
|
||||||
required = (aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required))
|
required = (aIgnoreSelf && HasAttr(kNameSpaceID_None, nsGkAtoms::required))
|
||||||
? container->GetRequiredRadioCount(name) - 1
|
? container->GetRequiredRadioCount(name) - 1
|
||||||
: container->GetRequiredRadioCount(name);
|
: container->GetRequiredRadioCount(name);
|
||||||
|
@ -3855,18 +3834,14 @@ nsHTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
||||||
|
|
||||||
valueMissing = required && !selected;
|
valueMissing = required && !selected;
|
||||||
|
|
||||||
if (container && !name.IsEmpty()) {
|
if (container->GetValueMissingState(name) != valueMissing) {
|
||||||
if (container->GetValueMissingState(name) != valueMissing) {
|
container->SetValueMissingState(name, valueMissing);
|
||||||
container->SetValueMissingState(name, valueMissing);
|
|
||||||
|
|
||||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRadioVisitor> visitor =
|
|
||||||
new nsRadioSetValueMissingState(this, valueMissing, notify);
|
|
||||||
VisitGroup(visitor, notify);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING, valueMissing);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRadioVisitor> visitor =
|
||||||
|
new nsRadioSetValueMissingState(this, valueMissing, notify);
|
||||||
|
VisitGroup(visitor, notify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,11 +225,6 @@ public:
|
||||||
}
|
}
|
||||||
void AddedToRadioGroup();
|
void AddedToRadioGroup();
|
||||||
void WillRemoveFromRadioGroup();
|
void WillRemoveFromRadioGroup();
|
||||||
/**
|
|
||||||
* Get the radio group container for this button (form or document)
|
|
||||||
* @return the radio group container (or null if no form or document)
|
|
||||||
*/
|
|
||||||
virtual already_AddRefed<nsIRadioGroupContainer> GetRadioGroupContainer();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function returning the currently selected button in the radio group.
|
* Helper function returning the currently selected button in the radio group.
|
||||||
|
@ -567,6 +562,14 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the radio group container if the element has one, null otherwise.
|
||||||
|
* The radio group container will be the form owner if there is one.
|
||||||
|
* The current document otherwise.
|
||||||
|
* @return the radio group container if the element has one, null otherwise.
|
||||||
|
*/
|
||||||
|
nsIRadioGroupContainer* GetRadioGroupContainer() const;
|
||||||
|
|
||||||
nsCOMPtr<nsIControllers> mControllers;
|
nsCOMPtr<nsIControllers> mControllers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче