mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1556351 - Part 5: Make nsGenericHTMLFormControlElement implement nsIFormControl; r=smaug
nsGenericHTMLFormElement doesn't implement nsIFormControl now as HTMLElement would inherit it to be able to be added into HTMLFormElement and HTMLFieldSetElement and support some common form feature. So some places that call the nsIFormControl method on nsGenericHTMLFormElement directly would need to queryInterface it to nsIFormControl first, this should be fine as those places are not in a hot path. Differential Revision: https://phabricator.services.mozilla.com/D124788
This commit is contained in:
parent
6be72297cc
commit
495e0b741d
@ -3079,7 +3079,7 @@ void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
|
||||
|
||||
if (appendedForm) {
|
||||
// Append the index of the control in the form
|
||||
int32_t index = formElement->IndexOfControl(control);
|
||||
int32_t index = formElement->IndexOfContent(aContent);
|
||||
|
||||
if (index > -1) {
|
||||
KeyAppendInt(index, aKey);
|
||||
|
@ -679,16 +679,16 @@ void nsINode::LastRelease() {
|
||||
document->RemoveAllPropertiesFor(this);
|
||||
}
|
||||
|
||||
// I wonder whether it's faster to do the HasFlag check first....
|
||||
if (IsNodeOfType(nsINode::eHTML_FORM_CONTROL) && HasFlag(ADDED_TO_FORM)) {
|
||||
// Tell the form (if any) this node is going away. Don't
|
||||
// notify, since we're being destroyed in any case.
|
||||
static_cast<nsGenericHTMLFormElement*>(this)->ClearForm(true, true);
|
||||
}
|
||||
|
||||
if (IsHTMLElement(nsGkAtoms::img) && HasFlag(ADDED_TO_FORM)) {
|
||||
HTMLImageElement* imageElem = static_cast<HTMLImageElement*>(this);
|
||||
imageElem->ClearForm(true);
|
||||
if (HasFlag(ADDED_TO_FORM)) {
|
||||
if (nsGenericHTMLFormControlElement* formControl =
|
||||
nsGenericHTMLFormControlElement::FromNode(this)) {
|
||||
// Tell the form (if any) this node is going away. Don't
|
||||
// notify, since we're being destroyed in any case.
|
||||
formControl->ClearForm(true, true);
|
||||
} else if (HTMLImageElement* imageElem =
|
||||
HTMLImageElement::FromNode(this)) {
|
||||
imageElem->ClearForm(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
UnsetFlags(NODE_HAS_PROPERTIES);
|
||||
|
@ -100,8 +100,6 @@ class HTMLButtonElement final : public nsGenericHTMLFormControlElementWithState,
|
||||
void SetDisabled(bool aDisabled, ErrorResult& aError) {
|
||||
SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aError);
|
||||
}
|
||||
// nsGenericHTMLFormElement::GetForm is fine.
|
||||
using nsGenericHTMLFormElement::GetForm;
|
||||
// GetFormAction implemented in superclass
|
||||
void SetFormAction(const nsAString& aFormAction, ErrorResult& aRv) {
|
||||
SetHTMLAttr(nsGkAtoms::formaction, aFormAction, aRv);
|
||||
|
@ -8,11 +8,12 @@
|
||||
|
||||
#include "mozilla/FlushType.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLFormControlsCollectionBinding.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "nsGenericHTMLElement.h" // nsGenericHTMLFormElement
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "RadioNodeList.h"
|
||||
#include "jsfriendapi.h"
|
||||
@ -89,12 +90,16 @@ void HTMLFormControlsCollection::DropFormReference() {
|
||||
void HTMLFormControlsCollection::Clear() {
|
||||
// Null out childrens' pointer to me. No refcounting here
|
||||
for (int32_t i = mElements.Length() - 1; i >= 0; i--) {
|
||||
mElements[i]->ClearForm(false, false);
|
||||
nsCOMPtr<nsIFormControl> formControl = do_QueryObject(mElements[i]);
|
||||
MOZ_ASSERT(formControl);
|
||||
formControl->ClearForm(false, false);
|
||||
}
|
||||
mElements.Clear();
|
||||
|
||||
for (int32_t i = mNotInElements.Length() - 1; i >= 0; i--) {
|
||||
mNotInElements[i]->ClearForm(false, false);
|
||||
nsCOMPtr<nsIFormControl> formControl = do_QueryObject(mNotInElements[i]);
|
||||
MOZ_ASSERT(formControl);
|
||||
formControl->ClearForm(false, false);
|
||||
}
|
||||
mNotInElements.Clear();
|
||||
|
||||
@ -138,27 +143,31 @@ nsISupports* HTMLFormControlsCollection::NamedItemInternal(
|
||||
|
||||
nsresult HTMLFormControlsCollection::AddElementToTable(
|
||||
nsGenericHTMLFormElement* aChild, const nsAString& aName) {
|
||||
if (!ShouldBeInElements(aChild)) {
|
||||
nsCOMPtr<nsIFormControl> formControl = do_QueryObject(aChild);
|
||||
MOZ_ASSERT(formControl);
|
||||
if (!ShouldBeInElements(formControl)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mForm->AddElementToTableInternal(mNameLookupTable, aChild, aName);
|
||||
}
|
||||
|
||||
nsresult HTMLFormControlsCollection::IndexOfControl(nsIFormControl* aControl,
|
||||
nsresult HTMLFormControlsCollection::IndexOfContent(nsIContent* aContent,
|
||||
int32_t* aIndex) {
|
||||
// Note -- not a DOM method; callers should handle flushing themselves
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aIndex);
|
||||
|
||||
*aIndex = mElements.IndexOf(aControl);
|
||||
*aIndex = mElements.IndexOf(aContent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult HTMLFormControlsCollection::RemoveElementFromTable(
|
||||
nsGenericHTMLFormElement* aChild, const nsAString& aName) {
|
||||
if (!ShouldBeInElements(aChild)) {
|
||||
nsCOMPtr<nsIFormControl> formControl = do_QueryObject(aChild);
|
||||
MOZ_ASSERT(formControl);
|
||||
if (!ShouldBeInElements(formControl)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsGenericHTMLFormElement;
|
||||
class nsIContent;
|
||||
class nsIFormControl;
|
||||
template <class T>
|
||||
class RefPtr;
|
||||
@ -56,7 +57,7 @@ class HTMLFormControlsCollection final : public nsIHTMLCollection,
|
||||
const nsAString& aName);
|
||||
nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
nsresult IndexOfControl(nsIFormControl* aControl, int32_t* aIndex);
|
||||
nsresult IndexOfContent(nsIContent* aContent, int32_t* aIndex);
|
||||
|
||||
nsISupports* NamedItemInternal(const nsAString& aName);
|
||||
|
||||
|
@ -382,7 +382,9 @@ static void CollectOrphans(nsINode* aRemovalRoot,
|
||||
if (node->HasFlag(MAYBE_ORPHAN_FORM_ELEMENT)) {
|
||||
node->UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
if (!node->IsInclusiveDescendantOf(aRemovalRoot)) {
|
||||
node->ClearForm(true, false);
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
|
||||
MOZ_ASSERT(fc);
|
||||
fc->ClearForm(true, false);
|
||||
|
||||
// When a form control loses its form owner, its state can change.
|
||||
node->UpdateState(true);
|
||||
@ -394,7 +396,9 @@ static void CollectOrphans(nsINode* aRemovalRoot,
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!removed) {
|
||||
HTMLFormElement* form = node->GetForm();
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
|
||||
MOZ_ASSERT(fc);
|
||||
HTMLFormElement* form = fc->GetForm();
|
||||
NS_ASSERTION(form == aThisForm, "How did that happen?");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
@ -603,8 +607,8 @@ nsresult HTMLFormElement::DoReset() {
|
||||
uint32_t numElements = mControls->Length();
|
||||
for (uint32_t elementX = 0; elementX < numElements; ++elementX) {
|
||||
// Hold strong ref in case the reset does something weird
|
||||
nsCOMPtr<nsIFormControl> controlNode =
|
||||
mControls->mElements.SafeElementAt(elementX, nullptr);
|
||||
nsCOMPtr<nsIFormControl> controlNode = do_QueryInterface(
|
||||
mControls->mElements.SafeElementAt(elementX, nullptr));
|
||||
if (controlNode) {
|
||||
controlNode->Reset();
|
||||
}
|
||||
@ -1017,8 +1021,10 @@ nsresult HTMLFormElement::ConstructEntryList(FormData* aFormData) {
|
||||
// Walk the list of nodes and call SubmitNamesValues() on the controls
|
||||
//
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(sortedControls[i]);
|
||||
MOZ_ASSERT(fc);
|
||||
// Tell the control to submit its name/value pairs to the submission
|
||||
sortedControls[i]->SubmitNamesValues(aFormData);
|
||||
fc->SubmitNamesValues(aFormData);
|
||||
}
|
||||
|
||||
FormDataEventInit init;
|
||||
@ -1254,10 +1260,11 @@ nsresult HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
NS_ASSERTION(aChild->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
||||
aChild->GetParent(),
|
||||
"Form control should have a parent");
|
||||
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryObject(aChild);
|
||||
MOZ_ASSERT(fc);
|
||||
// Determine whether to add the new element to the elements or
|
||||
// the not-in-elements list.
|
||||
bool childInElements = HTMLFormControlsCollection::ShouldBeInElements(aChild);
|
||||
bool childInElements = HTMLFormControlsCollection::ShouldBeInElements(fc);
|
||||
nsTArray<nsGenericHTMLFormElement*>& controlList =
|
||||
childInElements ? mControls->mElements : mControls->mNotInElements;
|
||||
|
||||
@ -1267,7 +1274,7 @@ nsresult HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
AssertDocumentOrder(controlList, this);
|
||||
#endif
|
||||
|
||||
auto type = aChild->ControlType();
|
||||
auto type = fc->ControlType();
|
||||
|
||||
// If it is a password control, inform the password manager.
|
||||
if (type == FormControlType::InputPassword) {
|
||||
@ -1280,7 +1287,7 @@ nsresult HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
}
|
||||
|
||||
// Default submit element handling
|
||||
if (aChild->IsSubmitControl()) {
|
||||
if (fc->IsSubmitControl()) {
|
||||
// Update mDefaultSubmitElement, mFirstSubmitInElements,
|
||||
// mFirstSubmitNotInElements.
|
||||
|
||||
@ -1359,14 +1366,16 @@ nsresult HTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
|
||||
// Remove it from the radio group if it's a radio button
|
||||
//
|
||||
nsresult rv = NS_OK;
|
||||
if (aChild->ControlType() == FormControlType::InputRadio) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(aChild);
|
||||
MOZ_ASSERT(fc);
|
||||
if (fc->ControlType() == FormControlType::InputRadio) {
|
||||
RefPtr<HTMLInputElement> radio = static_cast<HTMLInputElement*>(aChild);
|
||||
radio->WillRemoveFromRadioGroup();
|
||||
}
|
||||
|
||||
// Determine whether to remove the child from the elements list
|
||||
// or the not in elements list.
|
||||
bool childInElements = HTMLFormControlsCollection::ShouldBeInElements(aChild);
|
||||
bool childInElements = HTMLFormControlsCollection::ShouldBeInElements(fc);
|
||||
nsTArray<nsGenericHTMLFormElement*>& controls =
|
||||
childInElements ? mControls->mElements : mControls->mNotInElements;
|
||||
|
||||
@ -1386,9 +1395,10 @@ nsresult HTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
|
||||
// We are removing the first submit in this list, find the new first submit
|
||||
uint32_t length = controls.Length();
|
||||
for (uint32_t i = index; i < length; ++i) {
|
||||
nsGenericHTMLFormElement* currentControl = controls[i];
|
||||
nsCOMPtr<nsIFormControl> currentControl = do_QueryInterface(controls[i]);
|
||||
MOZ_ASSERT(currentControl);
|
||||
if (currentControl->IsSubmitControl()) {
|
||||
*firstSubmitSlot = currentControl;
|
||||
*firstSubmitSlot = controls[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1794,7 +1804,9 @@ bool HTMLFormElement::ImplicitSubmissionIsDisabled() const {
|
||||
uint32_t numDisablingControlsFound = 0;
|
||||
uint32_t length = mControls->mElements.Length();
|
||||
for (uint32_t i = 0; i < length && numDisablingControlsFound < 2; ++i) {
|
||||
if (mControls->mElements[i]->IsSingleLineTextControl(false)) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(mControls->mElements[i]);
|
||||
MOZ_ASSERT(fc);
|
||||
if (fc->IsSingleLineTextControl(false)) {
|
||||
numDisablingControlsFound++;
|
||||
}
|
||||
}
|
||||
@ -1806,8 +1818,10 @@ bool HTMLFormElement::IsLastActiveElement(
|
||||
MOZ_ASSERT(aElement, "Unexpected call");
|
||||
|
||||
for (auto* element : Reversed(mControls->mElements)) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(element);
|
||||
MOZ_ASSERT(fc);
|
||||
// XXX How about date/time control?
|
||||
if (element->IsTextControl(false) && !element->IsDisabled()) {
|
||||
if (fc->IsTextControl(false) && !element->IsDisabled()) {
|
||||
return element == aElement;
|
||||
}
|
||||
}
|
||||
@ -2015,7 +2029,9 @@ void HTMLFormElement::UpdateValidity(bool aElementValidity) {
|
||||
// Inform submit controls that the form validity has changed.
|
||||
for (uint32_t i = 0, length = mControls->mElements.Length(); i < length;
|
||||
++i) {
|
||||
if (mControls->mElements[i]->IsSubmitControl()) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(mControls->mElements[i]);
|
||||
MOZ_ASSERT(fc);
|
||||
if (fc->IsSubmitControl()) {
|
||||
mControls->mElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
@ -2024,7 +2040,10 @@ void HTMLFormElement::UpdateValidity(bool aElementValidity) {
|
||||
// so we have to check for controls not in elements too.
|
||||
uint32_t length = mControls->mNotInElements.Length();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
if (mControls->mNotInElements[i]->IsSubmitControl()) {
|
||||
nsCOMPtr<nsIFormControl> fc =
|
||||
do_QueryInterface(mControls->mNotInElements[i]);
|
||||
MOZ_ASSERT(fc);
|
||||
if (fc->IsSubmitControl()) {
|
||||
mControls->mNotInElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
@ -2032,9 +2051,9 @@ void HTMLFormElement::UpdateValidity(bool aElementValidity) {
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
int32_t HTMLFormElement::IndexOfControl(nsIFormControl* aControl) {
|
||||
int32_t HTMLFormElement::IndexOfContent(nsIContent* aContent) {
|
||||
int32_t index = 0;
|
||||
return mControls->IndexOfControl(aControl, &index) == NS_OK ? index : 0;
|
||||
return mControls->IndexOfContent(aContent, &index) == NS_OK ? index : 0;
|
||||
}
|
||||
|
||||
void HTMLFormElement::SetCurrentRadioButton(const nsAString& aName,
|
||||
|
@ -53,7 +53,7 @@ class HTMLFormElement final : public nsGenericHTMLElement,
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
int32_t IndexOfControl(nsIFormControl* aControl);
|
||||
int32_t IndexOfContent(nsIContent* aContent);
|
||||
nsGenericHTMLFormElement* GetDefaultSubmitElement() const;
|
||||
|
||||
// nsIRadioGroupContainer
|
||||
|
@ -1650,9 +1650,8 @@ bool nsGenericHTMLElement::IsFormControlDefaultFocusable(
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsGenericHTMLFormElement::nsGenericHTMLFormElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FormControlType aType)
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: nsGenericHTMLElement(std::move(aNodeInfo)),
|
||||
nsIFormControl(aType),
|
||||
mForm(nullptr),
|
||||
mFieldSet(nullptr) {
|
||||
// We should add the NS_EVENT_STATE_ENABLED bit here as needed, but
|
||||
@ -1669,31 +1668,6 @@ nsGenericHTMLFormElement::~nsGenericHTMLFormElement() {
|
||||
NS_ASSERTION(!mForm, "mForm should be null at this point!");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsGenericHTMLFormElement, nsGenericHTMLElement,
|
||||
nsIFormControl)
|
||||
|
||||
bool nsGenericHTMLFormElement::IsNodeOfType(uint32_t aFlags) const {
|
||||
return !(aFlags & ~eHTML_FORM_CONTROL);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormElement::SetForm(HTMLFormElement* aForm) {
|
||||
MOZ_ASSERT(aForm, "Don't pass null here");
|
||||
NS_ASSERTION(!mForm,
|
||||
"We don't support switching from one non-null form to another.");
|
||||
|
||||
SetForm(aForm, false);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormElement::SetForm(HTMLFormElement* aForm,
|
||||
bool aBindToTree) {
|
||||
if (aForm) {
|
||||
BeforeSetForm(aBindToTree);
|
||||
}
|
||||
|
||||
// keep a *weak* ref to the form here
|
||||
mForm = aForm;
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm,
|
||||
bool aUnbindOrDelete) {
|
||||
NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
|
||||
@ -1725,20 +1699,11 @@ void nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm,
|
||||
AfterClearForm(aUnbindOrDelete);
|
||||
}
|
||||
|
||||
HTMLFieldSetElement* nsGenericHTMLFormElement::GetFieldSet() {
|
||||
return mFieldSet;
|
||||
}
|
||||
|
||||
nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext,
|
||||
nsINode& aParent) {
|
||||
nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (IsAutofocusable() && HasAttr(nsGkAtoms::autofocus) &&
|
||||
aContext.AllowsAutoFocus()) {
|
||||
aContext.OwnerDoc().SetAutoFocusElement(this);
|
||||
}
|
||||
|
||||
// If @form is set, the element *has* to be in a composed document, otherwise
|
||||
// it wouldn't be possible to find an element with the corresponding id.
|
||||
// If @form isn't set, the element *has* to have a parent, otherwise it
|
||||
@ -1757,9 +1722,6 @@ nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext,
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormElement::UnbindFromTree(bool aNullParent) {
|
||||
// Save state before doing anything
|
||||
SaveState();
|
||||
|
||||
if (mForm) {
|
||||
// Might need to unset mForm
|
||||
if (aNullParent) {
|
||||
@ -2026,7 +1988,7 @@ void nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
||||
|
||||
if (element && element->IsHTMLElement(nsGkAtoms::form) &&
|
||||
nsContentUtils::IsInSameAnonymousTree(this, element)) {
|
||||
SetForm(static_cast<HTMLFormElement*>(element), aBindToTree);
|
||||
SetFormInternal(static_cast<HTMLFormElement*>(element), aBindToTree);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -2036,7 +1998,7 @@ void nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
||||
// 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
|
||||
// probably changed _somewhere_.
|
||||
SetForm(FindAncestorForm(), aBindToTree);
|
||||
SetFormInternal(FindAncestorForm(), aBindToTree);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2438,14 +2400,21 @@ void nsGenericHTMLElement::ChangeEditableState(int32_t aChange) {
|
||||
|
||||
nsGenericHTMLFormControlElement::nsGenericHTMLFormControlElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FormControlType aType)
|
||||
: nsGenericHTMLFormElement(std::move(aNodeInfo), aType) {}
|
||||
: nsGenericHTMLFormElement(std::move(aNodeInfo)), nsIFormControl(aType) {}
|
||||
|
||||
nsGenericHTMLFormControlElement::~nsGenericHTMLFormControlElement() = default;
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsGenericHTMLFormControlElement,
|
||||
nsGenericHTMLFormElement, nsIFormControl)
|
||||
|
||||
nsINode* nsGenericHTMLFormControlElement::GetScopeChainParent() const {
|
||||
return mForm ? mForm : nsGenericHTMLElement::GetScopeChainParent();
|
||||
}
|
||||
|
||||
bool nsGenericHTMLFormControlElement::IsNodeOfType(uint32_t aFlags) const {
|
||||
return !(aFlags & ~eHTML_FORM_CONTROL);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::SaveSubtreeState() {
|
||||
SaveState();
|
||||
|
||||
@ -2465,6 +2434,26 @@ nsIContent::IMEState nsGenericHTMLFormControlElement::GetDesiredIMEState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
nsresult nsGenericHTMLFormControlElement::BindToTree(BindContext& aContext,
|
||||
nsINode& aParent) {
|
||||
nsresult rv = nsGenericHTMLFormElement::BindToTree(aContext, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (IsAutofocusable() && HasAttr(nsGkAtoms::autofocus) &&
|
||||
aContext.AllowsAutoFocus()) {
|
||||
aContext.OwnerDoc().SetAutoFocusElement(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::UnbindFromTree(bool aNullParent) {
|
||||
// Save state before doing anything
|
||||
SaveState();
|
||||
|
||||
nsGenericHTMLFormElement::UnbindFromTree(aNullParent);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::GetAutocapitalize(
|
||||
nsAString& aValue) const {
|
||||
if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
|
||||
@ -2530,6 +2519,23 @@ nsresult nsGenericHTMLFormControlElement::PreHandleEvent(
|
||||
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
HTMLFieldSetElement* nsGenericHTMLFormControlElement::GetFieldSet() {
|
||||
return mFieldSet;
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::SetForm(HTMLFormElement* aForm) {
|
||||
MOZ_ASSERT(aForm, "Don't pass null here");
|
||||
NS_ASSERTION(!mForm,
|
||||
"We don't support switching from one non-null form to another.");
|
||||
|
||||
SetFormInternal(aForm, false);
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::ClearForm(bool aRemoveFromForm,
|
||||
bool aUnbindOrDelete) {
|
||||
nsGenericHTMLFormElement::ClearForm(aRemoveFromForm, aUnbindOrDelete);
|
||||
}
|
||||
|
||||
EventStates nsGenericHTMLFormControlElement::IntrinsicState() const {
|
||||
// If you add attribute-dependent states here, you need to add them them to
|
||||
// AfterSetAttr too. And add them to AfterSetAttr for all subclasses that
|
||||
@ -2610,6 +2616,16 @@ bool nsGenericHTMLFormControlElement::DoesReadOnlyApply() const {
|
||||
}
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::SetFormInternal(HTMLFormElement* aForm,
|
||||
bool aBindToTree) {
|
||||
if (aForm) {
|
||||
BeforeSetForm(aBindToTree);
|
||||
}
|
||||
|
||||
// keep a *weak* ref to the form here
|
||||
mForm = aForm;
|
||||
}
|
||||
|
||||
void nsGenericHTMLFormControlElement::UpdateRequiredState(bool aIsRequired,
|
||||
bool aNotify) {
|
||||
#ifdef DEBUG
|
||||
|
@ -959,37 +959,15 @@ ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
|
||||
/**
|
||||
* A helper class for form elements that can contain children
|
||||
*/
|
||||
class nsGenericHTMLFormElement : public nsGenericHTMLElement,
|
||||
public nsIFormControl {
|
||||
class nsGenericHTMLFormElement : public nsGenericHTMLElement {
|
||||
public:
|
||||
nsGenericHTMLFormElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
FormControlType);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual bool IsNodeOfType(uint32_t aFlags) const override;
|
||||
|
||||
// nsIFormControl
|
||||
virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() override;
|
||||
virtual mozilla::dom::HTMLFormElement* GetForm() const override {
|
||||
return mForm;
|
||||
}
|
||||
virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) override;
|
||||
virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override;
|
||||
|
||||
virtual bool AllowDrop() override { return true; }
|
||||
nsGenericHTMLFormElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
||||
// nsIContent
|
||||
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
||||
virtual void UnbindFromTree(bool aNullParent = true) override;
|
||||
|
||||
/**
|
||||
* Save to presentation state. The form control will determine whether it
|
||||
* has anything to save and if so, create an entry in the layout history for
|
||||
* its pres context.
|
||||
*/
|
||||
virtual void SaveState() {}
|
||||
|
||||
/**
|
||||
* This callback is called by a fieldest on all its elements whenever its
|
||||
* disabled attribute is changed so the element knows its disabled state
|
||||
@ -1018,6 +996,8 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement,
|
||||
*/
|
||||
void ForgetFieldSet(nsIContent* aFieldset);
|
||||
|
||||
void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete);
|
||||
|
||||
protected:
|
||||
virtual ~nsGenericHTMLFormElement();
|
||||
|
||||
@ -1035,7 +1015,8 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement,
|
||||
|
||||
virtual void AfterClearForm(bool aUnbindOrDelete) {}
|
||||
|
||||
void SetForm(mozilla::dom::HTMLFormElement* aForm, bool aBindToTree);
|
||||
virtual void SetFormInternal(mozilla::dom::HTMLFormElement* aForm,
|
||||
bool aBindToTree) {}
|
||||
|
||||
/**
|
||||
* This method will update the form owner, using @form or looking to a parent.
|
||||
@ -1097,17 +1078,26 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement,
|
||||
mozilla::dom::HTMLFieldSetElement* mFieldSet;
|
||||
};
|
||||
|
||||
class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement {
|
||||
class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
|
||||
public nsIFormControl {
|
||||
public:
|
||||
nsGenericHTMLFormControlElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FormControlType);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElement,
|
||||
IsNodeOfType(nsINode::eHTML_FORM_CONTROL))
|
||||
|
||||
// nsINode
|
||||
nsINode* GetScopeChainParent() const override;
|
||||
virtual bool IsNodeOfType(uint32_t aFlags) const override;
|
||||
|
||||
// nsIContent
|
||||
virtual void SaveSubtreeState() override;
|
||||
virtual IMEState GetDesiredIMEState() override;
|
||||
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
||||
virtual void UnbindFromTree(bool aNullParent = true) override;
|
||||
|
||||
// nsGenericHTMLElement
|
||||
// autocapitalize attribute support
|
||||
@ -1120,6 +1110,15 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement {
|
||||
virtual nsresult PreHandleEvent(
|
||||
mozilla::EventChainVisitor& aVisitor) override;
|
||||
|
||||
// nsIFormControl
|
||||
virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() override;
|
||||
virtual mozilla::dom::HTMLFormElement* GetForm() const override {
|
||||
return mForm;
|
||||
}
|
||||
virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) override;
|
||||
virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override;
|
||||
virtual bool AllowDrop() override { return true; }
|
||||
|
||||
protected:
|
||||
virtual ~nsGenericHTMLFormControlElement();
|
||||
|
||||
@ -1130,6 +1129,8 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement {
|
||||
// nsGenericHTMLFormElement
|
||||
bool CanBeDisabled() const override;
|
||||
bool DoesReadOnlyApply() const override;
|
||||
void SetFormInternal(mozilla::dom::HTMLFormElement* aForm,
|
||||
bool aBindToTree) override;
|
||||
|
||||
/**
|
||||
* Update our required/optional flags to match the given aIsRequired boolean.
|
||||
@ -1137,6 +1138,13 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement {
|
||||
void UpdateRequiredState(bool aIsRequired, bool aNotify);
|
||||
|
||||
bool IsAutocapitalizeInheriting() const;
|
||||
|
||||
/**
|
||||
* Save to presentation state. The form control will determine whether it
|
||||
* has anything to save and if so, create an entry in the layout history for
|
||||
* its pres context.
|
||||
*/
|
||||
virtual void SaveState() {}
|
||||
};
|
||||
|
||||
class nsGenericHTMLFormControlElementWithState
|
||||
|
Loading…
Reference in New Issue
Block a user