mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 523666. Make nsGenericHTMLFormElement::mForm an nsHTMLFormElement. r=sicking
This commit is contained in:
parent
c3c7d9b6fb
commit
9e062e31dd
@ -43,7 +43,6 @@
|
||||
class nsIFormControl;
|
||||
class nsISimpleEnumerator;
|
||||
class nsIURI;
|
||||
template<class T> class nsTArray;
|
||||
|
||||
#define NS_FORM_METHOD_GET 0
|
||||
#define NS_FORM_METHOD_POST 1
|
||||
@ -53,13 +52,12 @@ template<class T> class nsTArray;
|
||||
|
||||
// IID for the nsIForm interface
|
||||
#define NS_IFORM_IID \
|
||||
{ 0x6e8456c2, 0xcf49, 0x4b6d, \
|
||||
{ 0xb5, 0xfe, 0x80, 0x0d, 0x03, 0x4f, 0x55, 0x33 } }
|
||||
{ 0x27f1ff6c, 0xeb78, 0x405b, \
|
||||
{ 0xa6, 0xeb, 0xf0, 0xce, 0xa8, 0x30, 0x85, 0x58 } }
|
||||
|
||||
/**
|
||||
* This interface provides a complete set of methods dealing with
|
||||
* elements which belong to a form element. When nsIDOMHTMLCollection
|
||||
* allows write operations
|
||||
* This interface provides some methods that can be used to access the
|
||||
* guts of a form. It's being slowly phased out.
|
||||
*/
|
||||
|
||||
class nsIForm : public nsISupports
|
||||
@ -67,27 +65,6 @@ class nsIForm : public nsISupports
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFORM_IID)
|
||||
|
||||
/**
|
||||
* Add an element to end of this form's list of elements
|
||||
*
|
||||
* @param aElement the element to add
|
||||
* @param aNotify If true, send nsIDocumentObserver notifications as needed.
|
||||
* @return NS_OK if the element was successfully added
|
||||
*/
|
||||
NS_IMETHOD AddElement(nsIFormControl* aElement,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Add an element to the lookup table mainted by the form.
|
||||
*
|
||||
* We can't fold this method into AddElement() because when
|
||||
* AddElement() is called, the form control has no
|
||||
* attributes. The name or id attributes of the form control
|
||||
* are used as a key into the table.
|
||||
*/
|
||||
NS_IMETHOD AddElementToTable(nsIFormControl* aElement,
|
||||
const nsAString& aName) = 0;
|
||||
|
||||
/**
|
||||
* Get the element at a specified index position in form.elements
|
||||
*
|
||||
@ -95,7 +72,7 @@ public:
|
||||
* @param aElement the element at that index
|
||||
* @return NS_OK if there was an element at that position, -1 otherwise
|
||||
*/
|
||||
NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const = 0;
|
||||
NS_IMETHOD_(nsIFormControl*) GetElementAt(PRInt32 aIndex) const = 0;
|
||||
|
||||
/**
|
||||
* Get the number of elements in form.elements
|
||||
@ -105,30 +82,6 @@ public:
|
||||
*/
|
||||
NS_IMETHOD_(PRUint32) GetElementCount() const = 0;
|
||||
|
||||
/**
|
||||
* Remove an element from this form's list of elements
|
||||
*
|
||||
* @param aElement the element to remove
|
||||
* @param aNotify If true, send nsIDocumentObserver notifications as needed.
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
NS_IMETHOD RemoveElement(nsIFormControl* aElement,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Remove an element from the lookup table mainted by the form.
|
||||
* We can't fold this method into RemoveElement() because when
|
||||
* RemoveElement() is called it doesn't know if the element is
|
||||
* removed because the id attribute has changed, or bacause the
|
||||
* name attribute has changed.
|
||||
*
|
||||
* @param aElement the element to remove
|
||||
* @param aName the name or id of the element to remove
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
|
||||
const nsAString& aName) = 0;
|
||||
|
||||
/**
|
||||
* Resolve a name in the scope of the form object, this means find
|
||||
* form controls in this form with the correct value in the name
|
||||
@ -147,68 +100,11 @@ public:
|
||||
*/
|
||||
NS_IMETHOD_(PRInt32) IndexOfControl(nsIFormControl* aControl) = 0;
|
||||
|
||||
/**
|
||||
* Flag the form to know that a button or image triggered scripted form
|
||||
* submission. In that case the form will defer the submission until the
|
||||
* script handler returns and the return value is known.
|
||||
*/
|
||||
NS_IMETHOD OnSubmitClickBegin() = 0;
|
||||
NS_IMETHOD OnSubmitClickEnd() = 0;
|
||||
|
||||
/**
|
||||
* Flush a possible pending submission. If there was a scripted submission
|
||||
* triggered by a button or image, the submission was defered. This method
|
||||
* forces the pending submission to be submitted. (happens when the handler
|
||||
* returns false or there is an action/target change in the script)
|
||||
*/
|
||||
NS_IMETHOD FlushPendingSubmission() = 0;
|
||||
/**
|
||||
* Forget a possible pending submission. Same as above but this time we
|
||||
* get rid of the pending submission cause the handler returned true
|
||||
* so we will rebuild the submission with the name/value of the triggering
|
||||
* element
|
||||
*/
|
||||
NS_IMETHOD ForgetPendingSubmission() = 0;
|
||||
|
||||
/**
|
||||
* Get the full URL to submit to. Do not submit if the returned URL is null.
|
||||
*
|
||||
* @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
|
||||
*/
|
||||
NS_IMETHOD GetActionURL(nsIURI** aActionURL) = 0;
|
||||
|
||||
/**
|
||||
* Get the list of all the form's controls in document order.
|
||||
* This list contains all form control elements, not just those
|
||||
* returned by form.elements in JS. The controls in this list do
|
||||
* not have additional references added.
|
||||
*
|
||||
* @param aControls Sorted list of form controls [out].
|
||||
* @return NS_OK if the list was successfully created.
|
||||
*/
|
||||
NS_IMETHOD GetSortedControls(nsTArray<nsIFormControl*>& aControls) const = 0;
|
||||
|
||||
/**
|
||||
* Get the default submit element. If there's no default submit element,
|
||||
* return null.
|
||||
*/
|
||||
NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const = 0;
|
||||
|
||||
/**
|
||||
* Check whether a given nsIFormControl is the default submit
|
||||
* element. This is different from just comparing to
|
||||
* GetDefaultSubmitElement() in certain situations inside an update
|
||||
* when GetDefaultSubmitElement() might not be up to date. aControl
|
||||
* is expected to not be null.
|
||||
*/
|
||||
NS_IMETHOD_(PRBool) IsDefaultSubmitElement(const nsIFormControl* aControl) const = 0;
|
||||
|
||||
/**
|
||||
* Return whether there is one and only one input text control.
|
||||
*
|
||||
* @return Whether there is exactly one input text control.
|
||||
*/
|
||||
NS_IMETHOD_(PRBool) HasSingleTextControl() const = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIForm, NS_IFORM_IID)
|
||||
|
@ -98,6 +98,7 @@
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
#include "nsFocusManager.h"
|
||||
|
||||
#include "nsMutationEvent.h"
|
||||
@ -897,8 +898,8 @@ nsGenericHTMLElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
nsGenericElement::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMHTMLFormElement>
|
||||
nsGenericHTMLElement::FindForm(nsIForm* aCurrentForm)
|
||||
nsHTMLFormElement*
|
||||
nsGenericHTMLElement::FindForm(nsHTMLFormElement* aCurrentForm)
|
||||
{
|
||||
// Make sure we don't end up finding a form that's anonymous from
|
||||
// our point of view.
|
||||
@ -921,10 +922,7 @@ nsGenericHTMLElement::FindForm(nsIForm* aCurrentForm)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nsIDOMHTMLFormElement* form;
|
||||
CallQueryInterface(content, &form);
|
||||
|
||||
return form;
|
||||
return static_cast<nsHTMLFormElement*>(content);
|
||||
}
|
||||
|
||||
nsIContent *prevContent = content;
|
||||
@ -938,19 +936,9 @@ nsGenericHTMLElement::FindForm(nsIForm* aCurrentForm)
|
||||
// we're one of those inputs-in-a-table that have a hacked mForm pointer
|
||||
// and a subtree containing both us and the form got removed from the
|
||||
// DOM.
|
||||
nsCOMPtr<nsIContent> formCOMPtr = do_QueryInterface(aCurrentForm);
|
||||
NS_ASSERTION(formCOMPtr, "aCurrentForm isn't an nsIContent?");
|
||||
// Use an nsIContent temporary to reduce addref/releasing as we go up the
|
||||
// tree
|
||||
nsINode* iter = formCOMPtr;
|
||||
do {
|
||||
iter = iter->GetNodeParent();
|
||||
if (iter == prevContent) {
|
||||
nsIDOMHTMLFormElement* form;
|
||||
CallQueryInterface(aCurrentForm, &form);
|
||||
return form;
|
||||
}
|
||||
} while (iter);
|
||||
if (nsContentUtils::ContentIsDescendantOf(aCurrentForm, prevContent)) {
|
||||
return aCurrentForm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2265,9 +2253,9 @@ nsGenericHTMLElement::SetContentEditable(const nsAString& aContentEditable)
|
||||
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsGenericHTMLFrameElement, TabIndex, tabindex, 0)
|
||||
|
||||
nsGenericHTMLFormElement::nsGenericHTMLFormElement(nsINodeInfo *aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mForm(nsnull)
|
||||
{
|
||||
mForm = nsnull;
|
||||
}
|
||||
|
||||
nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
|
||||
@ -2302,8 +2290,7 @@ nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
|
||||
"We don't support switching from one non-null form to another.");
|
||||
|
||||
// keep a *weak* ref to the form here
|
||||
CallQueryInterface(aForm, &mForm);
|
||||
mForm->Release();
|
||||
mForm = static_cast<nsHTMLFormElement*>(aForm);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2341,12 +2328,7 @@ NS_IMETHODIMP
|
||||
nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aForm);
|
||||
*aForm = nsnull;
|
||||
|
||||
if (mForm) {
|
||||
CallQueryInterface(mForm, aForm);
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aForm = mForm);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2434,10 +2416,7 @@ nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
|
||||
// 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_.
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form = FindForm();
|
||||
if (form) {
|
||||
SetForm(form);
|
||||
}
|
||||
mForm = FindForm();
|
||||
}
|
||||
|
||||
if (mForm && !HasFlag(ADDED_TO_FORM)) {
|
||||
@ -2476,8 +2455,7 @@ nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
ClearForm(PR_TRUE, PR_TRUE);
|
||||
} else {
|
||||
// Recheck whether we should still have an mForm.
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form = FindForm(mForm);
|
||||
if (!form) {
|
||||
if (!FindForm(mForm)) {
|
||||
ClearForm(PR_TRUE, PR_TRUE);
|
||||
} else {
|
||||
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
|
@ -62,6 +62,7 @@ class nsILayoutHistoryState;
|
||||
class nsIEditor;
|
||||
struct nsRect;
|
||||
struct nsSize;
|
||||
class nsHTMLFormElement;
|
||||
|
||||
typedef nsMappedAttributeElement nsGenericHTMLElementBase;
|
||||
|
||||
@ -506,7 +507,7 @@ public:
|
||||
* returned. This is needed to handle cases when HTML elements have a
|
||||
* current form that they're not descendants of.
|
||||
*/
|
||||
already_AddRefed<nsIDOMHTMLFormElement> FindForm(nsIForm* aCurrentForm = nsnull);
|
||||
nsHTMLFormElement* FindForm(nsHTMLFormElement* aCurrentForm = nsnull);
|
||||
|
||||
virtual void RecompileScriptEventListeners();
|
||||
|
||||
@ -855,7 +856,7 @@ protected:
|
||||
FocusTristate FocusState();
|
||||
|
||||
/** The form that contains this control */
|
||||
nsIForm* mForm;
|
||||
nsHTMLFormElement* mForm;
|
||||
};
|
||||
|
||||
// If this flag is set on an nsGenericHTMLFormElement, that means that we have
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "nsPresState.h"
|
||||
#include "nsLayoutErrors.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
|
||||
#define NS_IN_SUBMIT_CLICK (1 << 0)
|
||||
#define NS_OUTER_ACTIVATE_EVENT (1 << 1)
|
||||
@ -464,8 +465,9 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
// Using presShell to dispatch the event. It makes sure that
|
||||
// event is not handled if the window is being destroyed.
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIContent> form(do_QueryInterface(mForm));
|
||||
presShell->HandleDOMEventWithTarget(form, &event, &status);
|
||||
// Hold a strong ref while dispatching
|
||||
nsRefPtr<nsHTMLFormElement> form(mForm);
|
||||
presShell->HandleDOMEventWithTarget(mForm, &event, &status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,16 +34,10 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMNSHTMLFormElement.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIDOMNSHTMLFormControlList.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsStyleConsts.h"
|
||||
@ -63,28 +57,23 @@
|
||||
|
||||
// form submission
|
||||
#include "nsIFormSubmitObserver.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
|
||||
// radio buttons
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIRadioControlElement.h"
|
||||
#include "nsIRadioVisitor.h"
|
||||
#include "nsIRadioGroupContainer.h"
|
||||
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
@ -92,280 +81,8 @@
|
||||
|
||||
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
|
||||
|
||||
class nsFormControlList;
|
||||
|
||||
/**
|
||||
* hashkey wrapper using nsAString KeyType
|
||||
*
|
||||
* @see nsTHashtable::EntryType for specification
|
||||
*/
|
||||
class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef const nsAString& KeyType;
|
||||
typedef const nsAString* KeyTypePointer;
|
||||
nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
|
||||
nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
|
||||
~nsStringCaseInsensitiveHashKey() { }
|
||||
|
||||
KeyType GetKey() const { return mStr; }
|
||||
PRBool KeyEquals(const KeyTypePointer aKey) const
|
||||
{
|
||||
return mStr.Equals(*aKey,nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey)
|
||||
{
|
||||
nsAutoString tmKey(*aKey);
|
||||
ToLowerCase(tmKey);
|
||||
return HashString(tmKey);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = PR_TRUE };
|
||||
|
||||
private:
|
||||
const nsString mStr;
|
||||
};
|
||||
|
||||
|
||||
// nsHTMLFormElement
|
||||
|
||||
class nsHTMLFormElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLFormElement,
|
||||
public nsIDOMNSHTMLFormElement,
|
||||
public nsIWebProgressListener,
|
||||
public nsIForm,
|
||||
public nsIRadioGroupContainer
|
||||
{
|
||||
public:
|
||||
nsHTMLFormElement(nsINodeInfo *aNodeInfo);
|
||||
virtual ~nsHTMLFormElement();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMNode
|
||||
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
|
||||
|
||||
// nsIDOMElement
|
||||
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
|
||||
|
||||
// nsIDOMHTMLElement
|
||||
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
|
||||
|
||||
// nsIDOMHTMLFormElement
|
||||
NS_DECL_NSIDOMHTMLFORMELEMENT
|
||||
|
||||
// nsIDOMNSHTMLFormElement
|
||||
NS_DECL_NSIDOMNSHTMLFORMELEMENT
|
||||
|
||||
// nsIWebProgressListener
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
||||
// nsIForm
|
||||
NS_IMETHOD AddElement(nsIFormControl* aElement,
|
||||
PRBool aNotify);
|
||||
NS_IMETHOD AddElementToTable(nsIFormControl* aChild,
|
||||
const nsAString& aName);
|
||||
NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const;
|
||||
NS_IMETHOD_(PRUint32) GetElementCount() const;
|
||||
NS_IMETHOD RemoveElement(nsIFormControl* aElement,
|
||||
PRBool aNotify);
|
||||
NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
|
||||
const nsAString& aName);
|
||||
NS_IMETHOD_(already_AddRefed<nsISupports>) ResolveName(const nsAString& aName);
|
||||
NS_IMETHOD_(PRInt32) IndexOfControl(nsIFormControl* aControl);
|
||||
NS_IMETHOD OnSubmitClickBegin();
|
||||
NS_IMETHOD OnSubmitClickEnd();
|
||||
NS_IMETHOD FlushPendingSubmission();
|
||||
NS_IMETHOD ForgetPendingSubmission();
|
||||
NS_IMETHOD GetActionURL(nsIURI** aActionURL);
|
||||
NS_IMETHOD GetSortedControls(nsTArray<nsIFormControl*>& aControls) const;
|
||||
NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const;
|
||||
NS_IMETHOD_(PRBool) IsDefaultSubmitElement(const nsIFormControl* aControl) const;
|
||||
NS_IMETHOD_(PRBool) HasSingleTextControl() const;
|
||||
|
||||
// nsIRadioGroupContainer
|
||||
NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
|
||||
nsIDOMHTMLInputElement* aRadio);
|
||||
NS_IMETHOD GetCurrentRadioButton(const nsAString& aName,
|
||||
nsIDOMHTMLInputElement** aRadio);
|
||||
NS_IMETHOD GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
|
||||
PRInt32 *aPositionIndex,
|
||||
PRInt32 *aItemsInGroup);
|
||||
NS_IMETHOD GetNextRadioButton(const nsAString& aName,
|
||||
const PRBool aPrevious,
|
||||
nsIDOMHTMLInputElement* aFocusedRadio,
|
||||
nsIDOMHTMLInputElement** aRadioOut);
|
||||
NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
|
||||
PRBool aFlushContent);
|
||||
NS_IMETHOD AddToRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
NS_IMETHOD RemoveFromRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
|
||||
// nsIContent
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
nsAttrValue& aResult);
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||
virtual nsresult WillHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString& aValue, PRBool aNotify)
|
||||
{
|
||||
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
|
||||
}
|
||||
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Forget all information about the current submission (and the fact that we
|
||||
* are currently submitting at all).
|
||||
*/
|
||||
void ForgetCurrentSubmission();
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
protected:
|
||||
class RemoveElementRunnable;
|
||||
friend class RemoveElementRunnable;
|
||||
|
||||
class RemoveElementRunnable : public nsRunnable {
|
||||
public:
|
||||
RemoveElementRunnable(nsHTMLFormElement* aForm, PRBool aNotify):
|
||||
mForm(aForm), mNotify(aNotify)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mForm->HandleDefaultSubmitRemoval(mNotify);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsHTMLFormElement> mForm;
|
||||
PRBool mNotify;
|
||||
};
|
||||
|
||||
nsresult DoSubmitOrReset(nsEvent* aEvent,
|
||||
PRInt32 aMessage);
|
||||
nsresult DoReset();
|
||||
|
||||
// Async callback to handle removal of our default submit
|
||||
void HandleDefaultSubmitRemoval(PRBool aNotify);
|
||||
|
||||
//
|
||||
// Submit Helpers
|
||||
//
|
||||
//
|
||||
/**
|
||||
* Attempt to submit (submission might be deferred)
|
||||
* (called by DoSubmitOrReset)
|
||||
*
|
||||
* @param aPresContext the presentation context
|
||||
* @param aEvent the DOM event that was passed to us for the submit
|
||||
*/
|
||||
nsresult DoSubmit(nsEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Prepare the submission object (called by DoSubmit)
|
||||
*
|
||||
* @param aFormSubmission the submission object
|
||||
* @param aEvent the DOM event that was passed to us for the submit
|
||||
*/
|
||||
nsresult BuildSubmission(nsCOMPtr<nsIFormSubmission>& aFormSubmission,
|
||||
nsEvent* aEvent);
|
||||
/**
|
||||
* Perform the submission (called by DoSubmit and FlushPendingSubmission)
|
||||
*
|
||||
* @param aFormSubmission the submission object
|
||||
*/
|
||||
nsresult SubmitSubmission(nsIFormSubmission* aFormSubmission);
|
||||
/**
|
||||
* Walk over the form elements and call SubmitNamesValues() on them to get
|
||||
* their data pumped into the FormSubmitter.
|
||||
*
|
||||
* @param aFormSubmission the form submission object
|
||||
* @param aSubmitElement the element that was clicked on (nsnull if none)
|
||||
*/
|
||||
nsresult WalkFormElements(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
/**
|
||||
* Notify any submit observers of the submit.
|
||||
*
|
||||
* @param aActionURL the URL being submitted to
|
||||
* @param aCancelSubmit out param where submit observers can specify that the
|
||||
* submit should be cancelled.
|
||||
*/
|
||||
nsresult NotifySubmitObservers(nsIURI* aActionURL, PRBool* aCancelSubmit,
|
||||
PRBool aEarlyNotify);
|
||||
|
||||
/**
|
||||
* Just like ResolveName(), but takes an arg for whether to flush
|
||||
*/
|
||||
already_AddRefed<nsISupports> DoResolveName(const nsAString& aName, PRBool aFlushContent);
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
/** The list of controls (form.elements as well as stuff not in elements) */
|
||||
nsRefPtr<nsFormControlList> mControls;
|
||||
/** The currently selected radio button of each group */
|
||||
nsInterfaceHashtable<nsStringCaseInsensitiveHashKey,nsIDOMHTMLInputElement> mSelectedRadioButtons;
|
||||
/** Whether we are currently processing a submit event or not */
|
||||
PRPackedBool mGeneratingSubmit;
|
||||
/** Whether we are currently processing a reset event or not */
|
||||
PRPackedBool mGeneratingReset;
|
||||
/** Whether we are submitting currently */
|
||||
PRPackedBool mIsSubmitting;
|
||||
/** Whether the submission is to be deferred in case a script triggers it */
|
||||
PRPackedBool mDeferSubmission;
|
||||
/** Whether we notified NS_FORMSUBMIT_SUBJECT listeners already */
|
||||
PRPackedBool mNotifiedObservers;
|
||||
/** If we notified the listeners early, what was the result? */
|
||||
PRPackedBool mNotifiedObserversResult;
|
||||
/** Keep track of what the popup state was when the submit was initiated */
|
||||
PopupControlState mSubmitPopupState;
|
||||
/** Keep track of whether a submission was user-initiated or not */
|
||||
PRBool mSubmitInitiatedFromUserInput;
|
||||
|
||||
/** The pending submission object */
|
||||
nsCOMPtr<nsIFormSubmission> mPendingSubmission;
|
||||
/** The request currently being submitted */
|
||||
nsCOMPtr<nsIRequest> mSubmittingRequest;
|
||||
/** The web progress object we are currently listening to */
|
||||
nsWeakPtr mWebProgress;
|
||||
|
||||
/** The default submit element -- WEAK */
|
||||
nsIFormControl* mDefaultSubmitElement;
|
||||
|
||||
/** The first submit element in mElements -- WEAK */
|
||||
nsIFormControl* mFirstSubmitInElements;
|
||||
|
||||
/** The first submit element in mNotInElements -- WEAK */
|
||||
nsIFormControl* mFirstSubmitNotInElements;
|
||||
|
||||
protected:
|
||||
/** Detection of first form to notify observers */
|
||||
static PRBool gFirstFormSubmitted;
|
||||
/** Detection of first password input to initialize the password manager */
|
||||
static PRBool gPasswordManagerInitialized;
|
||||
};
|
||||
|
||||
PRBool nsHTMLFormElement::gFirstFormSubmitted = PR_FALSE;
|
||||
PRBool nsHTMLFormElement::gPasswordManagerInitialized = PR_FALSE;
|
||||
|
||||
@ -396,7 +113,8 @@ public:
|
||||
|
||||
*aResult = NS_OK;
|
||||
|
||||
return mElements.SafeElementAt(aIndex, nsnull);
|
||||
// XXXbz this should start returning nsINode* or something!
|
||||
return static_cast<nsIFormControl*>(mElements.SafeElementAt(aIndex, nsnull));
|
||||
}
|
||||
virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult)
|
||||
{
|
||||
@ -405,9 +123,9 @@ public:
|
||||
return NamedItemInternal(aName, PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult AddElementToTable(nsIFormControl* aChild,
|
||||
nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
nsresult RemoveElementFromTable(nsIFormControl* aChild,
|
||||
nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
nsresult IndexOfControl(nsIFormControl* aControl,
|
||||
PRInt32* aIndex);
|
||||
@ -423,18 +141,18 @@ public:
|
||||
* @param aControls The list of sorted controls[out].
|
||||
* @return NS_OK or NS_ERROR_OUT_OF_MEMORY.
|
||||
*/
|
||||
nsresult GetSortedControls(nsTArray<nsIFormControl*>& aControls) const;
|
||||
nsresult GetSortedControls(nsTArray<nsGenericHTMLFormElement*>& aControls) const;
|
||||
|
||||
nsHTMLFormElement* mForm; // WEAK - the form owns me
|
||||
|
||||
nsTArray<nsIFormControl*> mElements; // Holds WEAK references - bug 36639
|
||||
nsTArray<nsGenericHTMLFormElement*> mElements; // Holds WEAK references - bug 36639
|
||||
|
||||
// This array holds on to all form controls that are not contained
|
||||
// in mElements (form.elements in JS, see ShouldBeInFormControl()).
|
||||
// This is needed to properly clean up the bi-directional references
|
||||
// (both weak and strong) between the form and its form controls.
|
||||
|
||||
nsTArray<nsIFormControl*> mNotInElements; // Holds WEAK references
|
||||
nsTArray<nsGenericHTMLFormElement*> mNotInElements; // Holds WEAK references
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
|
||||
|
||||
@ -751,18 +469,16 @@ nsHTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
}
|
||||
|
||||
static void
|
||||
MarkOrphans(const nsTArray<nsIFormControl*> aArray)
|
||||
MarkOrphans(const nsTArray<nsGenericHTMLFormElement*> aArray)
|
||||
{
|
||||
PRUint32 length = aArray.Length();
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aArray[i]);
|
||||
NS_ASSERTION(node, "Form control must be nsINode");
|
||||
node->SetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
aArray[i]->SetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsIFormControl*> aArray
|
||||
CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsGenericHTMLFormElement*> aArray
|
||||
#ifdef DEBUG
|
||||
, nsIDOMHTMLFormElement* aThisForm
|
||||
#endif
|
||||
@ -771,9 +487,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsIFormControl*> aArray
|
||||
// Walk backwards so that if we remove elements we can just keep iterating
|
||||
PRUint32 length = aArray.Length();
|
||||
for (PRUint32 i = length; i > 0; --i) {
|
||||
nsIFormControl* control = aArray[i-1];
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(control);
|
||||
NS_ASSERTION(node, "Form control must be nsINode");
|
||||
nsGenericHTMLFormElement* node = aArray[i-1];
|
||||
|
||||
// Now if MAYBE_ORPHAN_FORM_ELEMENT is not set, that would mean that the
|
||||
// node is in fact a descendant of the form and hence should stay in the
|
||||
@ -786,7 +500,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsIFormControl*> aArray
|
||||
if (node->HasFlag(MAYBE_ORPHAN_FORM_ELEMENT)) {
|
||||
node->UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
if (!nsContentUtils::ContentIsDescendantOf(node, aRemovalRoot)) {
|
||||
control->ClearForm(PR_TRUE, PR_TRUE);
|
||||
node->ClearForm(PR_TRUE, PR_TRUE);
|
||||
#ifdef DEBUG
|
||||
removed = PR_TRUE;
|
||||
#endif
|
||||
@ -796,7 +510,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsIFormControl*> aArray
|
||||
#ifdef DEBUG
|
||||
if (!removed) {
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form;
|
||||
control->GetForm(getter_AddRefs(form));
|
||||
node->GetForm(getter_AddRefs(form));
|
||||
NS_ASSERTION(form == aThisForm, "How did that happen?");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
@ -964,8 +678,8 @@ nsHTMLFormElement::DoReset()
|
||||
// JBK walk the elements[] array instead of form frame controls - bug 34297
|
||||
PRUint32 numElements = GetElementCount();
|
||||
for (PRUint32 elementX = 0; (elementX < numElements); elementX++) {
|
||||
nsCOMPtr<nsIFormControl> controlNode;
|
||||
GetElementAt(elementX, getter_AddRefs(controlNode));
|
||||
// Hold strong ref in case the reset does something weird
|
||||
nsCOMPtr<nsIFormControl> controlNode = GetElementAt(elementX);
|
||||
if (controlNode) {
|
||||
controlNode->Reset();
|
||||
}
|
||||
@ -1236,7 +950,7 @@ nsresult
|
||||
nsHTMLFormElement::WalkFormElements(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
nsTArray<nsIFormControl*> sortedControls;
|
||||
nsTArray<nsGenericHTMLFormElement*> sortedControls;
|
||||
nsresult rv = mControls->GetSortedControls(sortedControls);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -1262,19 +976,10 @@ nsHTMLFormElement::GetElementCount() const
|
||||
return count;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::GetElementAt(PRInt32 aIndex,
|
||||
nsIFormControl** aFormControl) const
|
||||
NS_IMETHODIMP_(nsIFormControl*)
|
||||
nsHTMLFormElement::GetElementAt(PRInt32 aIndex) const
|
||||
{
|
||||
// Converting to unsigned int will handle negative indices.
|
||||
if (PRUint32(aIndex) >= mControls->mElements.Length()) {
|
||||
*aFormControl = nsnull;
|
||||
} else {
|
||||
*aFormControl = mControls->mElements[aIndex];
|
||||
NS_ADDREF(*aFormControl);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return mControls->mElements.SafeElementAt(aIndex, nsnull);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1286,21 +991,17 @@ nsHTMLFormElement::GetElementAt(PRInt32 aIndex,
|
||||
* > 0 if aControl1 is after aControl2,
|
||||
* 0 otherwise
|
||||
*/
|
||||
static PRInt32 CompareFormControlPosition(nsIFormControl *aControl1,
|
||||
nsIFormControl *aControl2,
|
||||
const nsIContent* aForm)
|
||||
static inline PRInt32
|
||||
CompareFormControlPosition(nsGenericHTMLFormElement *aControl1,
|
||||
nsGenericHTMLFormElement *aControl2,
|
||||
const nsIContent* aForm)
|
||||
{
|
||||
NS_ASSERTION(aControl1 != aControl2, "Comparing a form control to itself");
|
||||
|
||||
nsCOMPtr<nsIContent> content1 = do_QueryInterface(aControl1);
|
||||
nsCOMPtr<nsIContent> content2 = do_QueryInterface(aControl2);
|
||||
|
||||
NS_ASSERTION(content1 && content2,
|
||||
"We should be able to QI to nsIContent here!");
|
||||
NS_ASSERTION(content1->GetParent() && content2->GetParent(),
|
||||
NS_ASSERTION(aControl1->GetParent() && aControl2->GetParent(),
|
||||
"Form controls should always have parents");
|
||||
|
||||
return nsLayoutUtils::CompareTreePosition(content1, content2, aForm);
|
||||
return nsLayoutUtils::CompareTreePosition(aControl1, aControl2, aForm);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1312,7 +1013,7 @@ static PRInt32 CompareFormControlPosition(nsIFormControl *aControl1,
|
||||
* @param aForm Parent form of the controls.
|
||||
*/
|
||||
static void
|
||||
AssertDocumentOrder(const nsTArray<nsIFormControl*>& aControls,
|
||||
AssertDocumentOrder(const nsTArray<nsGenericHTMLFormElement*>& aControls,
|
||||
nsIContent* aForm)
|
||||
{
|
||||
// Only iterate if aControls is not empty, since otherwise
|
||||
@ -1328,29 +1029,23 @@ AssertDocumentOrder(const nsTArray<nsIFormControl*>& aControls,
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::AddElement(nsIFormControl* aChild,
|
||||
nsresult
|
||||
nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
PRBool aNotify)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aChild);
|
||||
NS_ASSERTION(content->GetParent(),
|
||||
"Form control should have a parent");
|
||||
}
|
||||
#endif
|
||||
NS_ASSERTION(aChild->GetParent(), "Form control should have a parent");
|
||||
|
||||
// Determine whether to add the new element to the elements or
|
||||
// the not-in-elements list.
|
||||
PRBool childInElements = ShouldBeInElements(aChild);
|
||||
nsTArray<nsIFormControl*>& controlList = childInElements ?
|
||||
nsTArray<nsGenericHTMLFormElement*>& controlList = childInElements ?
|
||||
mControls->mElements : mControls->mNotInElements;
|
||||
|
||||
NS_ASSERTION(controlList.IndexOf(aChild) == controlList.NoIndex,
|
||||
"Form control already in form");
|
||||
|
||||
PRUint32 count = controlList.Length();
|
||||
nsCOMPtr<nsIFormControl> element;
|
||||
nsGenericHTMLFormElement* element;
|
||||
|
||||
// Optimize most common case where we insert at the end.
|
||||
PRBool lastElement = PR_FALSE;
|
||||
@ -1396,7 +1091,8 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
|
||||
//
|
||||
PRInt32 type = aChild->GetType();
|
||||
if (type == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIRadioControlElement> radio = do_QueryInterface(aChild);
|
||||
nsCOMPtr<nsIRadioControlElement> radio;
|
||||
CallQueryInterface(aChild, getter_AddRefs(radio));
|
||||
nsresult rv = radio->AddedToRadioGroup();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1418,7 +1114,7 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
|
||||
// Update mDefaultSubmitElement, mFirstSubmitInElements,
|
||||
// mFirstSubmitNotInElements.
|
||||
|
||||
nsIFormControl** firstSubmitSlot =
|
||||
nsGenericHTMLFormElement** firstSubmitSlot =
|
||||
childInElements ? &mFirstSubmitInElements : &mFirstSubmitNotInElements;
|
||||
|
||||
// The new child is the new first submit in its list if the firstSubmitSlot
|
||||
@ -1469,16 +1165,16 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild,
|
||||
nsresult
|
||||
nsHTMLFormElement::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName)
|
||||
{
|
||||
return mControls->AddElementToTable(aChild, aName);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
|
||||
nsresult
|
||||
nsHTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
|
||||
PRBool aNotify)
|
||||
{
|
||||
//
|
||||
@ -1486,7 +1182,8 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
|
||||
//
|
||||
nsresult rv = NS_OK;
|
||||
if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIRadioControlElement> radio = do_QueryInterface(aChild);
|
||||
nsCOMPtr<nsIRadioControlElement> radio;
|
||||
CallQueryInterface(aChild, getter_AddRefs(radio));
|
||||
rv = radio->WillRemoveFromRadioGroup();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@ -1494,7 +1191,7 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
|
||||
// Determine whether to remove the child from the elements list
|
||||
// or the not in elements list.
|
||||
PRBool childInElements = ShouldBeInElements(aChild);
|
||||
nsTArray<nsIFormControl*>& controls = childInElements ?
|
||||
nsTArray<nsGenericHTMLFormElement*>& controls = childInElements ?
|
||||
mControls->mElements : mControls->mNotInElements;
|
||||
|
||||
// Find the index of the child. This will be used later if necessary
|
||||
@ -1505,7 +1202,7 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
|
||||
controls.RemoveElementAt(index);
|
||||
|
||||
// Update our mFirstSubmit* values.
|
||||
nsIFormControl** firstSubmitSlot =
|
||||
nsGenericHTMLFormElement** firstSubmitSlot =
|
||||
childInElements ? &mFirstSubmitInElements : &mFirstSubmitNotInElements;
|
||||
if (aChild == *firstSubmitSlot) {
|
||||
*firstSubmitSlot = nsnull;
|
||||
@ -1513,7 +1210,7 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
|
||||
// We are removing the first submit in this list, find the new first submit
|
||||
PRUint32 length = controls.Length();
|
||||
for (PRUint32 i = index; i < length; ++i) {
|
||||
nsIFormControl* currentControl = controls[i];
|
||||
nsGenericHTMLFormElement* currentControl = controls[i];
|
||||
if (currentControl->IsSubmitControl()) {
|
||||
*firstSubmitSlot = currentControl;
|
||||
break;
|
||||
@ -1567,15 +1264,14 @@ nsHTMLFormElement::HandleDefaultSubmitRemoval(PRBool aNotify)
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
nsCOMPtr<nsIContent> newElement(do_QueryInterface(mDefaultSubmitElement));
|
||||
document->ContentStatesChanged(newElement, nsnull,
|
||||
document->ContentStatesChanged(mDefaultSubmitElement, nsnull,
|
||||
NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::RemoveElementFromTable(nsIFormControl* aElement,
|
||||
nsresult
|
||||
nsHTMLFormElement::RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
|
||||
const nsAString& aName)
|
||||
{
|
||||
return mControls->RemoveElementFromTable(aElement, aName);
|
||||
@ -1596,7 +1292,7 @@ nsHTMLFormElement::DoResolveName(const nsAString& aName,
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsHTMLFormElement::OnSubmitClickBegin()
|
||||
{
|
||||
mDeferSubmission = PR_TRUE;
|
||||
@ -1609,7 +1305,7 @@ nsHTMLFormElement::OnSubmitClickBegin()
|
||||
|
||||
rv = GetActionURL(getter_AddRefs(actionURI));
|
||||
if (NS_FAILED(rv) || !actionURI)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
//
|
||||
// Notify observers of submit
|
||||
@ -1620,24 +1316,21 @@ nsHTMLFormElement::OnSubmitClickBegin()
|
||||
mNotifiedObservers = PR_TRUE;
|
||||
mNotifiedObserversResult = cancelSubmit;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsHTMLFormElement::OnSubmitClickEnd()
|
||||
{
|
||||
mDeferSubmission = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsHTMLFormElement::FlushPendingSubmission()
|
||||
{
|
||||
nsCOMPtr<nsIFormSubmission> kunkFuDeathGrip(mPendingSubmission);
|
||||
|
||||
if (!mPendingSubmission) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
@ -1647,18 +1340,16 @@ nsHTMLFormElement::FlushPendingSubmission()
|
||||
|
||||
// now delete the pending submission object
|
||||
mPendingSubmission = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsHTMLFormElement::ForgetPendingSubmission()
|
||||
{
|
||||
// just delete the pending submission
|
||||
mPendingSubmission = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
@ -1736,12 +1427,6 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::GetSortedControls(nsTArray<nsIFormControl*>& aControls) const
|
||||
{
|
||||
return mControls->GetSortedControls(aControls);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIFormControl*)
|
||||
nsHTMLFormElement::GetDefaultSubmitElement() const
|
||||
{
|
||||
@ -1752,7 +1437,7 @@ nsHTMLFormElement::GetDefaultSubmitElement() const
|
||||
return mDefaultSubmitElement;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
PRBool
|
||||
nsHTMLFormElement::IsDefaultSubmitElement(const nsIFormControl* aControl) const
|
||||
{
|
||||
NS_PRECONDITION(aControl, "Unexpected call");
|
||||
@ -1787,7 +1472,7 @@ nsHTMLFormElement::IsDefaultSubmitElement(const nsIFormControl* aControl) const
|
||||
return aControl == defaultSubmit;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
PRBool
|
||||
nsHTMLFormElement::HasSingleTextControl() const
|
||||
{
|
||||
// Input text controls are always in the elements list.
|
||||
@ -1938,12 +1623,8 @@ nsHTMLFormElement::GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
|
||||
nsCOMPtr<nsISupports> itemWithName;
|
||||
itemWithName = ResolveName(name);
|
||||
NS_ENSURE_TRUE(itemWithName, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDOMNodeList> radioNodeList(do_QueryInterface(itemWithName));
|
||||
nsCOMPtr<nsINodeList> radioGroup(do_QueryInterface(itemWithName));
|
||||
|
||||
// XXX If ResolveName could return an nsContentList instead then we
|
||||
// could get an nsContentList instead of using this hacky upcast
|
||||
nsBaseContentList *radioGroup =
|
||||
static_cast<nsBaseContentList *>((nsIDOMNodeList *)radioNodeList);
|
||||
NS_ASSERTION(radioGroup, "No such radio group in this container");
|
||||
if (!radioGroup) {
|
||||
return NS_OK;
|
||||
@ -1951,7 +1632,7 @@ nsHTMLFormElement::GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
|
||||
|
||||
nsCOMPtr<nsIContent> currentRadioNode(do_QueryInterface(aRadio));
|
||||
NS_ASSERTION(currentRadioNode, "No nsIContent for current radio button");
|
||||
*aPositionIndex = radioGroup->IndexOf(currentRadioNode, PR_TRUE);
|
||||
*aPositionIndex = radioGroup->IndexOf(currentRadioNode);
|
||||
NS_ASSERTION(*aPositionIndex >= 0, "Radio button not found in its own group");
|
||||
PRUint32 itemsInGroup;
|
||||
radioGroup->GetLength(&itemsInGroup);
|
||||
@ -1979,20 +1660,15 @@ nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> itemWithName = ResolveName(aName);
|
||||
nsCOMPtr<nsIDOMNodeList> radioNodeList(do_QueryInterface(itemWithName));
|
||||
nsCOMPtr<nsINodeList> radioGroup(do_QueryInterface(itemWithName));
|
||||
|
||||
// XXX If ResolveName could return an nsContentList instead then we
|
||||
// could get an nsContentList instead of using this hacky upcast
|
||||
|
||||
nsBaseContentList *radioGroup =
|
||||
static_cast<nsBaseContentList *>((nsIDOMNodeList *)radioNodeList);
|
||||
if (!radioGroup) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> currentRadioNode(do_QueryInterface(currentRadio));
|
||||
NS_ASSERTION(currentRadioNode, "No nsIContent for current radio button");
|
||||
PRInt32 index = radioGroup->IndexOf(currentRadioNode, PR_TRUE);
|
||||
PRInt32 index = radioGroup->IndexOf(currentRadioNode);
|
||||
if (index < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -2001,7 +1677,6 @@ nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
|
||||
radioGroup->GetLength(&numRadios);
|
||||
PRBool disabled = PR_TRUE;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> radio;
|
||||
nsCOMPtr<nsIDOMNode> radioDOMNode;
|
||||
nsCOMPtr<nsIFormControl> formControl;
|
||||
|
||||
do {
|
||||
@ -2013,11 +1688,11 @@ nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
|
||||
else if (++index >= (PRInt32)numRadios) {
|
||||
index = 0;
|
||||
}
|
||||
radioGroup->Item(index, getter_AddRefs(radioDOMNode));
|
||||
radio = do_QueryInterface(radioDOMNode);
|
||||
radio = do_QueryInterface(radioGroup->GetNodeAt(index));
|
||||
if (!radio)
|
||||
continue;
|
||||
|
||||
// XXXbz why is this formControl check needed, exactly?
|
||||
formControl = do_QueryInterface(radio);
|
||||
if (!formControl || formControl->GetType() != NS_FORM_INPUT_RADIO)
|
||||
continue;
|
||||
@ -2046,7 +1721,7 @@ nsHTMLFormElement::WalkRadioGroup(const nsAString& aName,
|
||||
nsCOMPtr<nsIFormControl> control;
|
||||
PRUint32 len = GetElementCount();
|
||||
for (PRUint32 i=0; i<len; i++) {
|
||||
GetElementAt(i, getter_AddRefs(control));
|
||||
control = GetElementAt(i);
|
||||
if (control->GetType() == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIContent> controlContent(do_QueryInterface(control));
|
||||
if (controlContent) {
|
||||
@ -2292,7 +1967,7 @@ nsFormControlList::NamedItemInternal(const nsAString& aName,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFormControlList::AddElementToTable(nsIFormControl* aChild,
|
||||
nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName)
|
||||
{
|
||||
if (!ShouldBeInElements(aChild)) {
|
||||
@ -2304,20 +1979,19 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
|
||||
|
||||
if (!supports) {
|
||||
// No entry found, add the form control
|
||||
nsCOMPtr<nsISupports> child(do_QueryInterface(aChild));
|
||||
|
||||
NS_ENSURE_TRUE( mNameLookupTable.Put(aName, child), NS_ERROR_FAILURE );
|
||||
NS_ENSURE_TRUE( mNameLookupTable.Put(aName,
|
||||
NS_ISUPPORTS_CAST(nsIContent*, aChild)),
|
||||
NS_ERROR_FAILURE );
|
||||
} else {
|
||||
// Found something in the hash, check its type
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(supports));
|
||||
nsCOMPtr<nsIContent> newChild(do_QueryInterface(aChild));
|
||||
|
||||
if (content) {
|
||||
// Check if the new content is the same as the one we found in the
|
||||
// hash, if it is then we leave it in the hash as it is, this will
|
||||
// happen if a form control has both a name and an id with the same
|
||||
// value
|
||||
if (content == newChild) {
|
||||
if (content == aChild) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2329,10 +2003,10 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
|
||||
NS_ASSERTION(content->GetParent(), "Item in list without parent");
|
||||
|
||||
// Determine the ordering between the new and old element.
|
||||
PRBool newFirst = nsContentUtils::PositionIsBefore(newChild, content);
|
||||
PRBool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
|
||||
|
||||
list->AppendElement(newFirst ? newChild : content);
|
||||
list->AppendElement(newFirst ? content : newChild);
|
||||
list->AppendElement(newFirst ? aChild : content);
|
||||
list->AppendElement(newFirst ? content : aChild);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupports> listSupports =
|
||||
@ -2353,8 +2027,8 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
|
||||
NS_ASSERTION(list->Length() > 1,
|
||||
"List should have been converted back to a single element");
|
||||
|
||||
if(nsContentUtils::PositionIsBefore(list->GetNodeAt(list->Length() - 1), newChild)) {
|
||||
list->AppendElement(newChild);
|
||||
if(nsContentUtils::PositionIsBefore(list->GetNodeAt(list->Length() - 1), aChild)) {
|
||||
list->AppendElement(aChild);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2368,13 +2042,13 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild,
|
||||
while (last != first) {
|
||||
mid = (first + last) / 2;
|
||||
|
||||
if (nsContentUtils::PositionIsBefore(newChild, list->GetNodeAt(mid)))
|
||||
if (nsContentUtils::PositionIsBefore(aChild, list->GetNodeAt(mid)))
|
||||
last = mid;
|
||||
else
|
||||
first = mid + 1;
|
||||
}
|
||||
|
||||
list->InsertElementAt(newChild, first);
|
||||
list->InsertElementAt(aChild, first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2395,18 +2069,13 @@ nsFormControlList::IndexOfControl(nsIFormControl* aControl,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
|
||||
nsFormControlList::RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName)
|
||||
{
|
||||
if (!ShouldBeInElements(aChild)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aChild);
|
||||
if (!content) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
|
||||
if (!mNameLookupTable.Get(aName, getter_AddRefs(supports)))
|
||||
@ -2431,7 +2100,7 @@ nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
|
||||
nsBaseContentList *list = static_cast<nsBaseContentList *>
|
||||
((nsIDOMNodeList *)nodeList.get());
|
||||
|
||||
list->RemoveElement(content);
|
||||
list->RemoveElement(aChild);
|
||||
|
||||
PRUint32 length = 0;
|
||||
list->GetLength(&length);
|
||||
@ -2443,12 +2112,9 @@ nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
|
||||
} else if (length == 1) {
|
||||
// Only one element left, replace the list in the hash with the
|
||||
// single element.
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
list->Item(0, getter_AddRefs(node));
|
||||
|
||||
nsIContent* node = list->GetNodeAt(0);
|
||||
if (node) {
|
||||
nsCOMPtr<nsISupports> tmp(do_QueryInterface(node));
|
||||
NS_ENSURE_TRUE(mNameLookupTable.Put(aName, tmp),NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(mNameLookupTable.Put(aName, node),NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2456,7 +2122,7 @@ nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFormControlList::GetSortedControls(nsTArray<nsIFormControl*>& aControls) const
|
||||
nsFormControlList::GetSortedControls(nsTArray<nsGenericHTMLFormElement*>& aControls) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
AssertDocumentOrder(mElements, mForm);
|
||||
@ -2507,7 +2173,7 @@ nsFormControlList::GetSortedControls(nsTArray<nsIFormControl*>& aControls) const
|
||||
"Should have remaining elements");
|
||||
// Determine which of the two elements should be ordered
|
||||
// first and add it to the end of the list.
|
||||
nsIFormControl* elementToAdd;
|
||||
nsGenericHTMLFormElement* elementToAdd;
|
||||
if (CompareFormControlPosition(mElements[elementsIdx],
|
||||
mNotInElements[notInElementsIdx],
|
||||
mForm) < 0) {
|
||||
|
394
content/html/content/src/nsHTMLFormElement.h
Normal file
394
content/html/content/src/nsHTMLFormElement.h
Normal file
@ -0,0 +1,394 @@
|
||||
/* -*- Mode: C++; 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 Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* 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 "nsCOMPtr.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMNSHTMLFormElement.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIRadioGroupContainer.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsFormControlList;
|
||||
|
||||
/**
|
||||
* hashkey wrapper using nsAString KeyType
|
||||
*
|
||||
* @see nsTHashtable::EntryType for specification
|
||||
*/
|
||||
class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef const nsAString& KeyType;
|
||||
typedef const nsAString* KeyTypePointer;
|
||||
nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
|
||||
nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
|
||||
~nsStringCaseInsensitiveHashKey() { }
|
||||
|
||||
KeyType GetKey() const { return mStr; }
|
||||
PRBool KeyEquals(const KeyTypePointer aKey) const
|
||||
{
|
||||
return mStr.Equals(*aKey,nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey)
|
||||
{
|
||||
nsAutoString tmKey(*aKey);
|
||||
ToLowerCase(tmKey);
|
||||
return HashString(tmKey);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = PR_TRUE };
|
||||
|
||||
private:
|
||||
const nsString mStr;
|
||||
};
|
||||
|
||||
class nsHTMLFormElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLFormElement,
|
||||
public nsIDOMNSHTMLFormElement,
|
||||
public nsIWebProgressListener,
|
||||
public nsIForm,
|
||||
public nsIRadioGroupContainer
|
||||
{
|
||||
public:
|
||||
nsHTMLFormElement(nsINodeInfo *aNodeInfo);
|
||||
virtual ~nsHTMLFormElement();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMNode
|
||||
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
|
||||
|
||||
// nsIDOMElement
|
||||
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
|
||||
|
||||
// nsIDOMHTMLElement
|
||||
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
|
||||
|
||||
// nsIDOMHTMLFormElement
|
||||
NS_DECL_NSIDOMHTMLFORMELEMENT
|
||||
|
||||
// nsIDOMNSHTMLFormElement
|
||||
NS_DECL_NSIDOMNSHTMLFORMELEMENT
|
||||
|
||||
// nsIWebProgressListener
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
||||
// nsIForm
|
||||
NS_IMETHOD_(nsIFormControl*) GetElementAt(PRInt32 aIndex) const;
|
||||
NS_IMETHOD_(PRUint32) GetElementCount() const;
|
||||
NS_IMETHOD_(already_AddRefed<nsISupports>) ResolveName(const nsAString& aName);
|
||||
NS_IMETHOD_(PRInt32) IndexOfControl(nsIFormControl* aControl);
|
||||
NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const;
|
||||
|
||||
// nsIRadioGroupContainer
|
||||
NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
|
||||
nsIDOMHTMLInputElement* aRadio);
|
||||
NS_IMETHOD GetCurrentRadioButton(const nsAString& aName,
|
||||
nsIDOMHTMLInputElement** aRadio);
|
||||
NS_IMETHOD GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
|
||||
PRInt32 *aPositionIndex,
|
||||
PRInt32 *aItemsInGroup);
|
||||
NS_IMETHOD GetNextRadioButton(const nsAString& aName,
|
||||
const PRBool aPrevious,
|
||||
nsIDOMHTMLInputElement* aFocusedRadio,
|
||||
nsIDOMHTMLInputElement** aRadioOut);
|
||||
NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
|
||||
PRBool aFlushContent);
|
||||
NS_IMETHOD AddToRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
NS_IMETHOD RemoveFromRadioGroup(const nsAString& aName,
|
||||
nsIFormControl* aRadio);
|
||||
|
||||
// nsIContent
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
nsAttrValue& aResult);
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||
virtual nsresult WillHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString& aValue, PRBool aNotify)
|
||||
{
|
||||
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
|
||||
}
|
||||
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Forget all information about the current submission (and the fact that we
|
||||
* are currently submitting at all).
|
||||
*/
|
||||
void ForgetCurrentSubmission();
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
/**
|
||||
* Remove an element from this form's list of elements
|
||||
*
|
||||
* @param aElement the element to remove
|
||||
* @param aNotify If true, send nsIDocumentObserver notifications as needed.
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
nsresult RemoveElement(nsGenericHTMLFormElement* aElement, PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Remove an element from the lookup table mainted by the form.
|
||||
* We can't fold this method into RemoveElement() because when
|
||||
* RemoveElement() is called it doesn't know if the element is
|
||||
* removed because the id attribute has changed, or bacause the
|
||||
* name attribute has changed.
|
||||
*
|
||||
* @param aElement the element to remove
|
||||
* @param aName the name or id of the element to remove
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
|
||||
const nsAString& aName);
|
||||
/**
|
||||
* Add an element to end of this form's list of elements
|
||||
*
|
||||
* @param aElement the element to add
|
||||
* @param aNotify If true, send nsIDocumentObserver notifications as needed.
|
||||
* @return NS_OK if the element was successfully added
|
||||
*/
|
||||
nsresult AddElement(nsGenericHTMLFormElement* aElement, PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Add an element to the lookup table mainted by the form.
|
||||
*
|
||||
* We can't fold this method into AddElement() because when
|
||||
* AddElement() is called, the form control has no
|
||||
* attributes. The name or id attributes of the form control
|
||||
* are used as a key into the table.
|
||||
*/
|
||||
nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
/**
|
||||
* Return whether there is one and only one input text control.
|
||||
*
|
||||
* @return Whether there is exactly one input text control.
|
||||
*/
|
||||
PRBool HasSingleTextControl() const;
|
||||
|
||||
/**
|
||||
* Check whether a given nsIFormControl is the default submit
|
||||
* element. This is different from just comparing to
|
||||
* GetDefaultSubmitElement() in certain situations inside an update
|
||||
* when GetDefaultSubmitElement() might not be up to date. aControl
|
||||
* is expected to not be null.
|
||||
*/
|
||||
PRBool IsDefaultSubmitElement(const nsIFormControl* aControl) const;
|
||||
|
||||
/**
|
||||
* Flag the form to know that a button or image triggered scripted form
|
||||
* submission. In that case the form will defer the submission until the
|
||||
* script handler returns and the return value is known.
|
||||
*/
|
||||
void OnSubmitClickBegin();
|
||||
void OnSubmitClickEnd();
|
||||
|
||||
protected:
|
||||
class RemoveElementRunnable;
|
||||
friend class RemoveElementRunnable;
|
||||
|
||||
class RemoveElementRunnable : public nsRunnable {
|
||||
public:
|
||||
RemoveElementRunnable(nsHTMLFormElement* aForm, PRBool aNotify):
|
||||
mForm(aForm), mNotify(aNotify)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mForm->HandleDefaultSubmitRemoval(mNotify);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsHTMLFormElement> mForm;
|
||||
PRBool mNotify;
|
||||
};
|
||||
|
||||
nsresult DoSubmitOrReset(nsEvent* aEvent,
|
||||
PRInt32 aMessage);
|
||||
nsresult DoReset();
|
||||
|
||||
// Async callback to handle removal of our default submit
|
||||
void HandleDefaultSubmitRemoval(PRBool aNotify);
|
||||
|
||||
//
|
||||
// Submit Helpers
|
||||
//
|
||||
//
|
||||
/**
|
||||
* Attempt to submit (submission might be deferred)
|
||||
* (called by DoSubmitOrReset)
|
||||
*
|
||||
* @param aPresContext the presentation context
|
||||
* @param aEvent the DOM event that was passed to us for the submit
|
||||
*/
|
||||
nsresult DoSubmit(nsEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Prepare the submission object (called by DoSubmit)
|
||||
*
|
||||
* @param aFormSubmission the submission object
|
||||
* @param aEvent the DOM event that was passed to us for the submit
|
||||
*/
|
||||
nsresult BuildSubmission(nsCOMPtr<nsIFormSubmission>& aFormSubmission,
|
||||
nsEvent* aEvent);
|
||||
/**
|
||||
* Perform the submission (called by DoSubmit and FlushPendingSubmission)
|
||||
*
|
||||
* @param aFormSubmission the submission object
|
||||
*/
|
||||
nsresult SubmitSubmission(nsIFormSubmission* aFormSubmission);
|
||||
/**
|
||||
* Walk over the form elements and call SubmitNamesValues() on them to get
|
||||
* their data pumped into the FormSubmitter.
|
||||
*
|
||||
* @param aFormSubmission the form submission object
|
||||
* @param aSubmitElement the element that was clicked on (nsnull if none)
|
||||
*/
|
||||
nsresult WalkFormElements(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
/**
|
||||
* Notify any submit observers of the submit.
|
||||
*
|
||||
* @param aActionURL the URL being submitted to
|
||||
* @param aCancelSubmit out param where submit observers can specify that the
|
||||
* submit should be cancelled.
|
||||
*/
|
||||
nsresult NotifySubmitObservers(nsIURI* aActionURL, PRBool* aCancelSubmit,
|
||||
PRBool aEarlyNotify);
|
||||
|
||||
/**
|
||||
* Just like ResolveName(), but takes an arg for whether to flush
|
||||
*/
|
||||
already_AddRefed<nsISupports> DoResolveName(const nsAString& aName, PRBool aFlushContent);
|
||||
|
||||
/**
|
||||
* Get the full URL to submit to. Do not submit if the returned URL is null.
|
||||
*
|
||||
* @param aActionURL the full, unadulterated URL you'll be submitting to [OUT]
|
||||
*/
|
||||
nsresult GetActionURL(nsIURI** aActionURL);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Flush a possible pending submission. If there was a scripted submission
|
||||
* triggered by a button or image, the submission was defered. This method
|
||||
* forces the pending submission to be submitted. (happens when the handler
|
||||
* returns false or there is an action/target change in the script)
|
||||
*/
|
||||
void FlushPendingSubmission();
|
||||
protected:
|
||||
/**
|
||||
* Forget a possible pending submission. Same as above but this time we
|
||||
* get rid of the pending submission because the handler returned true
|
||||
* so we will rebuild the submission with the name/value of the triggering
|
||||
* element
|
||||
*/
|
||||
void ForgetPendingSubmission();
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
/** The list of controls (form.elements as well as stuff not in elements) */
|
||||
nsRefPtr<nsFormControlList> mControls;
|
||||
/** The currently selected radio button of each group */
|
||||
nsInterfaceHashtable<nsStringCaseInsensitiveHashKey,nsIDOMHTMLInputElement> mSelectedRadioButtons;
|
||||
/** Whether we are currently processing a submit event or not */
|
||||
PRPackedBool mGeneratingSubmit;
|
||||
/** Whether we are currently processing a reset event or not */
|
||||
PRPackedBool mGeneratingReset;
|
||||
/** Whether we are submitting currently */
|
||||
PRPackedBool mIsSubmitting;
|
||||
/** Whether the submission is to be deferred in case a script triggers it */
|
||||
PRPackedBool mDeferSubmission;
|
||||
/** Whether we notified NS_FORMSUBMIT_SUBJECT listeners already */
|
||||
PRPackedBool mNotifiedObservers;
|
||||
/** If we notified the listeners early, what was the result? */
|
||||
PRPackedBool mNotifiedObserversResult;
|
||||
/** Keep track of what the popup state was when the submit was initiated */
|
||||
PopupControlState mSubmitPopupState;
|
||||
/** Keep track of whether a submission was user-initiated or not */
|
||||
PRBool mSubmitInitiatedFromUserInput;
|
||||
|
||||
/** The pending submission object */
|
||||
nsCOMPtr<nsIFormSubmission> mPendingSubmission;
|
||||
/** The request currently being submitted */
|
||||
nsCOMPtr<nsIRequest> mSubmittingRequest;
|
||||
/** The web progress object we are currently listening to */
|
||||
nsWeakPtr mWebProgress;
|
||||
|
||||
/** The default submit element -- WEAK */
|
||||
nsGenericHTMLFormElement* mDefaultSubmitElement;
|
||||
|
||||
/** The first submit element in mElements -- WEAK */
|
||||
nsGenericHTMLFormElement* mFirstSubmitInElements;
|
||||
|
||||
/** The first submit element in mNotInElements -- WEAK */
|
||||
nsGenericHTMLFormElement* mFirstSubmitNotInElements;
|
||||
|
||||
protected:
|
||||
/** Detection of first form to notify observers */
|
||||
static PRBool gFirstFormSubmitted;
|
||||
/** Detection of first password input to initialize the password manager */
|
||||
static PRBool gPasswordManagerInitialized;
|
||||
};
|
@ -115,6 +115,7 @@
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
|
||||
// XXX align=left, hspace, vspace, border? other nav4 attrs
|
||||
|
||||
@ -1341,10 +1342,11 @@ nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
|
||||
shell->HandleDOMEventWithTarget(submitContent, &event, &status);
|
||||
} else if (mForm->HasSingleTextControl()) {
|
||||
// If there's only one text control, just submit the form
|
||||
nsCOMPtr<nsIContent> form = do_QueryInterface(mForm);
|
||||
// Hold strong ref across the event
|
||||
nsRefPtr<nsHTMLFormElement> form(mForm);
|
||||
nsFormEvent event(PR_TRUE, NS_FORM_SUBMIT);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
shell->HandleDOMEventWithTarget(form, &event, &status);
|
||||
shell->HandleDOMEventWithTarget(mForm, &event, &status);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2050,8 +2052,9 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
// handling the event the pres context will return a null
|
||||
// pres shell. See bug 125624.
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIContent> form(do_QueryInterface(mForm));
|
||||
presShell->HandleDOMEventWithTarget(form, &event, &status);
|
||||
// Hold a strong ref while dispatching
|
||||
nsRefPtr<nsHTMLFormElement> form(mForm);
|
||||
presShell->HandleDOMEventWithTarget(mForm, &event, &status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsRuleData.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
|
||||
// XXX nav4 has type= start= (same as OL/UL)
|
||||
extern nsAttrValue::EnumTable kListTypeTable[];
|
||||
@ -203,7 +204,7 @@ NS_IMPL_INT_ATTR(nsHTMLSharedElement, Size, size)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLSharedElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
||||
{
|
||||
*aForm = FindForm().get();
|
||||
NS_IF_ADDREF(*aForm = FindForm());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -9207,8 +9207,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
|
||||
PRInt32 n = GetArrayIndexFromId(cx, id);
|
||||
|
||||
if (n >= 0) {
|
||||
nsCOMPtr<nsIFormControl> control;
|
||||
form->GetElementAt(n, getter_AddRefs(control));
|
||||
nsIFormControl* control = form->GetElementAt(n);
|
||||
|
||||
if (control) {
|
||||
nsresult rv = WrapNative(cx, obj, control, PR_TRUE, vp);
|
||||
@ -9256,8 +9255,7 @@ nsHTMLFormElementSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
|
||||
PRUint32 count = form->GetElementCount();
|
||||
|
||||
if ((PRUint32)index < count) {
|
||||
nsCOMPtr<nsIFormControl> controlNode;
|
||||
form->GetElementAt(index, getter_AddRefs(controlNode));
|
||||
nsIFormControl* controlNode = form->GetElementAt(index);
|
||||
NS_ENSURE_TRUE(controlNode, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(controlNode);
|
||||
|
Loading…
Reference in New Issue
Block a user