mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1358448 - Add radio back to a radio group after moving out of a form. r=smaug
The container of a radio group is the form, if it belongs to a form, or the document object otherwise. When moving a radio out of a form, we should add it back to a radio group. Similary, before moving the radio to a form, we should remove it from the original radio group. MozReview-Commit-ID: 22WsEhz2SXH --HG-- extra : rebase_source : 68dbd50da523b734086d8e5de6e6ae179b0b4af0
This commit is contained in:
parent
fbc92ea6ed
commit
57c042eeb9
@ -332,7 +332,7 @@ nsNodeUtils::LastRelease(nsINode* aNode)
|
|||||||
aNode->HasFlag(ADDED_TO_FORM)) {
|
aNode->HasFlag(ADDED_TO_FORM)) {
|
||||||
// Tell the form (if any) this node is going away. Don't
|
// Tell the form (if any) this node is going away. Don't
|
||||||
// notify, since we're being destroyed in any case.
|
// notify, since we're being destroyed in any case.
|
||||||
static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(true);
|
static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aNode->IsHTMLElement(nsGkAtoms::img) &&
|
if (aNode->IsHTMLElement(nsGkAtoms::img) &&
|
||||||
|
@ -100,12 +100,12 @@ HTMLFormControlsCollection::Clear()
|
|||||||
{
|
{
|
||||||
// Null out childrens' pointer to me. No refcounting here
|
// Null out childrens' pointer to me. No refcounting here
|
||||||
for (int32_t i = mElements.Length() - 1; i >= 0; i--) {
|
for (int32_t i = mElements.Length() - 1; i >= 0; i--) {
|
||||||
mElements[i]->ClearForm(false);
|
mElements[i]->ClearForm(false, false);
|
||||||
}
|
}
|
||||||
mElements.Clear();
|
mElements.Clear();
|
||||||
|
|
||||||
for (int32_t i = mNotInElements.Length() - 1; i >= 0; i--) {
|
for (int32_t i = mNotInElements.Length() - 1; i >= 0; i--) {
|
||||||
mNotInElements[i]->ClearForm(false);
|
mNotInElements[i]->ClearForm(false, false);
|
||||||
}
|
}
|
||||||
mNotInElements.Clear();
|
mNotInElements.Clear();
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ CollectOrphans(nsINode* aRemovalRoot,
|
|||||||
if (node->HasFlag(MAYBE_ORPHAN_FORM_ELEMENT)) {
|
if (node->HasFlag(MAYBE_ORPHAN_FORM_ELEMENT)) {
|
||||||
node->UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
node->UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||||
if (!nsContentUtils::ContentIsDescendantOf(node, aRemovalRoot)) {
|
if (!nsContentUtils::ContentIsDescendantOf(node, aRemovalRoot)) {
|
||||||
node->ClearForm(true);
|
node->ClearForm(true, false);
|
||||||
|
|
||||||
// When a form control loses its form owner, its state can change.
|
// When a form control loses its form owner, its state can change.
|
||||||
node->UpdateState(true);
|
node->UpdateState(true);
|
||||||
|
@ -1550,6 +1550,27 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||||||
aValue, aNotify);
|
aValue, aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLInputElement::BeforeSetForm(bool aBindToTree)
|
||||||
|
{
|
||||||
|
// No need to remove from radio group if we are just binding to tree.
|
||||||
|
if (mType == NS_FORM_INPUT_RADIO && !aBindToTree) {
|
||||||
|
WillRemoveFromRadioGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLInputElement::AfterClearForm(bool aUnbindOrDelete)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mForm);
|
||||||
|
|
||||||
|
// Do not add back to radio group if we are releasing or unbinding from tree.
|
||||||
|
if (mType == NS_FORM_INPUT_RADIO && !aUnbindOrDelete) {
|
||||||
|
AddedToRadioGroup();
|
||||||
|
UpdateValueMissingValidityStateForRadio(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// nsIDOMHTMLInputElement
|
// nsIDOMHTMLInputElement
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -984,6 +984,10 @@ protected:
|
|||||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAttrValue* aValue, bool aNotify) override;
|
const nsAttrValue* aValue, bool aNotify) override;
|
||||||
|
|
||||||
|
virtual void BeforeSetForm(bool aBindToTree) override;
|
||||||
|
|
||||||
|
virtual void AfterClearForm(bool aUnbindOrDelete) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch a select event. Returns true if the event was not cancelled.
|
* Dispatch a select event. Returns true if the event was not cancelled.
|
||||||
*/
|
*/
|
||||||
|
@ -1760,12 +1760,21 @@ nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
|
|||||||
NS_ASSERTION(!mForm,
|
NS_ASSERTION(!mForm,
|
||||||
"We don't support switching from one non-null form to another.");
|
"We don't support switching from one non-null form to another.");
|
||||||
|
|
||||||
|
SetForm(static_cast<HTMLFormElement*>(aForm), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsGenericHTMLFormElement::SetForm(HTMLFormElement* aForm, bool aBindToTree)
|
||||||
|
{
|
||||||
|
if (aForm) {
|
||||||
|
BeforeSetForm(aBindToTree);
|
||||||
|
}
|
||||||
|
|
||||||
// keep a *weak* ref to the form here
|
// keep a *weak* ref to the form here
|
||||||
mForm = static_cast<HTMLFormElement*>(aForm);
|
mForm = aForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm)
|
nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete)
|
||||||
{
|
{
|
||||||
NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
|
NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
|
||||||
"Form control should have had flag set correctly");
|
"Form control should have had flag set correctly");
|
||||||
@ -1792,6 +1801,8 @@ nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm)
|
|||||||
|
|
||||||
UnsetFlags(ADDED_TO_FORM);
|
UnsetFlags(ADDED_TO_FORM);
|
||||||
mForm = nullptr;
|
mForm = nullptr;
|
||||||
|
|
||||||
|
AfterClearForm(aUnbindOrDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element*
|
Element*
|
||||||
@ -1876,12 +1887,12 @@ nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
|||||||
// Might need to unset mForm
|
// Might need to unset mForm
|
||||||
if (aNullParent) {
|
if (aNullParent) {
|
||||||
// No more parent means no more form
|
// No more parent means no more form
|
||||||
ClearForm(true);
|
ClearForm(true, true);
|
||||||
} else {
|
} else {
|
||||||
// Recheck whether we should still have an mForm.
|
// Recheck whether we should still have an mForm.
|
||||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
||||||
!FindAncestorForm(mForm)) {
|
!FindAncestorForm(mForm)) {
|
||||||
ClearForm(true);
|
ClearForm(true, true);
|
||||||
} else {
|
} else {
|
||||||
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||||
}
|
}
|
||||||
@ -2269,7 +2280,7 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
|||||||
bool needStateUpdate = false;
|
bool needStateUpdate = false;
|
||||||
if (!aBindToTree) {
|
if (!aBindToTree) {
|
||||||
needStateUpdate = mForm && mForm->IsDefaultSubmitElement(this);
|
needStateUpdate = mForm && mForm->IsDefaultSubmitElement(this);
|
||||||
ClearForm(true);
|
ClearForm(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMLFormElement *oldForm = mForm;
|
HTMLFormElement *oldForm = mForm;
|
||||||
@ -2295,7 +2306,7 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
|||||||
"associated with the id in @form!");
|
"associated with the id in @form!");
|
||||||
|
|
||||||
if (element && element->IsHTMLElement(nsGkAtoms::form)) {
|
if (element && element->IsHTMLElement(nsGkAtoms::form)) {
|
||||||
mForm = static_cast<HTMLFormElement*>(element);
|
SetForm(static_cast<HTMLFormElement*>(element), aBindToTree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2305,7 +2316,7 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
|||||||
// it to the right value. Also note that even if being bound here didn't
|
// it to the right value. Also note that even if being bound here didn't
|
||||||
// change our parent, we still need to search, since our parent chain
|
// change our parent, we still need to search, since our parent chain
|
||||||
// probably changed _somewhere_.
|
// probably changed _somewhere_.
|
||||||
mForm = FindAncestorForm();
|
SetForm(FindAncestorForm(), aBindToTree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1226,7 @@ public:
|
|||||||
return mForm;
|
return mForm;
|
||||||
}
|
}
|
||||||
virtual void SetForm(nsIDOMHTMLFormElement* aForm) override;
|
virtual void SetForm(nsIDOMHTMLFormElement* aForm) override;
|
||||||
virtual void ClearForm(bool aRemoveFromForm) override;
|
virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override;
|
||||||
|
|
||||||
nsresult GetForm(nsIDOMHTMLFormElement** aForm);
|
nsresult GetForm(nsIDOMHTMLFormElement** aForm);
|
||||||
|
|
||||||
@ -1303,6 +1303,12 @@ protected:
|
|||||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAttrValue* aValue, bool aNotify) override;
|
const nsAttrValue* aValue, bool aNotify) override;
|
||||||
|
|
||||||
|
virtual void BeforeSetForm(bool aBindToTree) {}
|
||||||
|
|
||||||
|
virtual void AfterClearForm(bool aUnbindOrDelete) {}
|
||||||
|
|
||||||
|
void SetForm(mozilla::dom::HTMLFormElement* aForm, bool aBindToTree);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will update the form owner, using @form or looking to a parent.
|
* This method will update the form owner, using @form or looking to a parent.
|
||||||
*
|
*
|
||||||
|
@ -127,8 +127,10 @@ public:
|
|||||||
*
|
*
|
||||||
* @param aRemoveFromForm set false if you do not want this element removed
|
* @param aRemoveFromForm set false if you do not want this element removed
|
||||||
* from the form. (Used by nsFormControlList::Clear())
|
* from the form. (Used by nsFormControlList::Clear())
|
||||||
|
* @param aUnbindOrDelete set true if the element is being deleted or unbound
|
||||||
|
* from tree.
|
||||||
*/
|
*/
|
||||||
virtual void ClearForm(bool aRemoveFromForm) = 0;
|
virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the type of this control as an int (see NS_FORM_* above)
|
* Get the type of this control as an int (see NS_FORM_* above)
|
||||||
|
Loading…
Reference in New Issue
Block a user