mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-03 15:26:07 +00:00
Implement the :default CSS3 pseudo-class. Bug 302186, patch by Allan Beaufour
<allan@beaufour.dk> and jpl24 <jlurz24@gmail.com>, r+sr=bzbarsky
This commit is contained in:
parent
b3167d713e
commit
a3a40f6eb5
@ -170,18 +170,19 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventStateManager, NS_IEVENTSTATEMANAGER_IID)
|
||||
// these two are temporary (see bug 302188)
|
||||
#define NS_EVENT_STATE_MOZ_READONLY 0x00008000 // CSS3-UI
|
||||
#define NS_EVENT_STATE_MOZ_READWRITE 0x00010000 // CSS3-UI
|
||||
#define NS_EVENT_STATE_DEFAULT 0x00020000 // CSS3-UI
|
||||
|
||||
// Content could not be rendered (image/object/etc).
|
||||
#define NS_EVENT_STATE_BROKEN 0x00020000
|
||||
#define NS_EVENT_STATE_BROKEN 0x00040000
|
||||
// Content disabled by the user (images turned off, say)
|
||||
#define NS_EVENT_STATE_USERDISABLED 0x00040000
|
||||
#define NS_EVENT_STATE_USERDISABLED 0x00080000
|
||||
// Content suppressed by the user (ad blocking, etc)
|
||||
#define NS_EVENT_STATE_SUPPRESSED 0x00080000
|
||||
#define NS_EVENT_STATE_SUPPRESSED 0x00100000
|
||||
// Content is still loading such that there is nothing to show the
|
||||
// user (eg an image which hasn't started coming in yet)
|
||||
#define NS_EVENT_STATE_LOADING 0x00100000
|
||||
#define NS_EVENT_STATE_LOADING 0x00200000
|
||||
// Content is of a type that gecko can't handle
|
||||
#define NS_EVENT_STATE_TYPE_UNSUPPORTED \
|
||||
0x00200000
|
||||
0x00400000
|
||||
|
||||
#endif // nsIEventStateManager_h__
|
||||
|
@ -55,8 +55,8 @@ class nsIURI;
|
||||
|
||||
// IID for the nsIFormManager interface
|
||||
#define NS_IFORM_IID \
|
||||
{ 0xb7e94510, 0x4c19, 0x11d2, \
|
||||
{ 0x80, 0x3f, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } }
|
||||
{ 0xab592735, 0x31d6, 0x4e28, \
|
||||
{0xaa, 0x1c, 0x77, 0x10, 0xf6, 0x01, 0xb8, 0x45} }
|
||||
|
||||
|
||||
/**
|
||||
@ -74,9 +74,11 @@ public:
|
||||
* 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) = 0;
|
||||
NS_IMETHOD AddElement(nsIFormControl* aElement,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Add an element to the lookup table mainted by the form.
|
||||
@ -110,9 +112,11 @@ public:
|
||||
* 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) = 0;
|
||||
NS_IMETHOD RemoveElement(nsIFormControl* aElement,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Remove an element from the lookup table mainted by the form.
|
||||
@ -184,6 +188,11 @@ public:
|
||||
*/
|
||||
NS_IMETHOD GetActionURL(nsIURI** aActionURL) = 0;
|
||||
|
||||
/**
|
||||
* Get the default submit element. If there's no default submit element,
|
||||
* return null.
|
||||
*/
|
||||
NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIForm, NS_IFORM_IID)
|
||||
|
@ -69,8 +69,8 @@ class nsIFormSubmission;
|
||||
#define NS_FORM_OBJECT 21
|
||||
|
||||
#define NS_IFORMCONTROL_IID \
|
||||
{ 0xfcf27549, 0xbd77, 0x455a, \
|
||||
{0x8c, 0x3e, 0xbb, 0x20, 0xc5, 0xaf, 0x7b, 0x86} }
|
||||
{ 0x119c5ce8, 0xf4b0, 0x456c, \
|
||||
{0x83, 0x4d, 0xb1, 0x90, 0x3d, 0x99, 0x9f, 0xb3} }
|
||||
|
||||
|
||||
/**
|
||||
@ -95,9 +95,11 @@ public:
|
||||
* @param aForm the form
|
||||
* @param aRemoveFromForm set false if you do not want this element removed
|
||||
* from the form. (Used by nsFormControlList::Clear())
|
||||
* @param aNofify If true, send nsIDocumentObserver notifications as needed.
|
||||
*/
|
||||
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm,
|
||||
PRBool aRemoveFromForm = PR_TRUE) = 0;
|
||||
PRBool aRemoveFromForm,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Get the type of this control as an int (see NS_FORM_* above)
|
||||
@ -141,6 +143,13 @@ public:
|
||||
virtual PRBool RestoreState(nsPresState* aState) = 0;
|
||||
|
||||
virtual PRBool AllowDrop() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if this is a control which submits the form when
|
||||
* activated by the user.
|
||||
* @return Whether this is a submit control.
|
||||
*/
|
||||
virtual PRBool IsSubmitControl() const = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFormControl, NS_IFORMCONTROL_IID)
|
||||
|
@ -3015,8 +3015,14 @@ nsGenericHTMLFormElement::nsGenericHTMLFormElement(nsINodeInfo *aNodeInfo)
|
||||
|
||||
nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
|
||||
{
|
||||
// Check that this element is still not the default content
|
||||
// of its parent form.
|
||||
NS_ASSERTION(!mForm || mForm->GetDefaultSubmitElement() != this,
|
||||
"Content being destroyed is the default content");
|
||||
|
||||
// Clean up. Set the form to nsnull so it knows we went away.
|
||||
SetForm(nsnull);
|
||||
// Do not notify as the content is being destroyed.
|
||||
SetForm(nsnull, PR_TRUE, PR_FALSE);
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsGenericHTMLFormElement)
|
||||
@ -3032,7 +3038,8 @@ nsGenericHTMLFormElement::IsNodeOfType(PRUint32 aFlags) const
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm,
|
||||
PRBool aRemoveFromForm)
|
||||
PRBool aRemoveFromForm,
|
||||
PRBool aNotify)
|
||||
{
|
||||
nsAutoString nameVal, idVal;
|
||||
|
||||
@ -3042,7 +3049,7 @@ nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm,
|
||||
}
|
||||
|
||||
if (mForm && aRemoveFromForm) {
|
||||
mForm->RemoveElement(this);
|
||||
mForm->RemoveElement(this, aNotify);
|
||||
|
||||
if (!nameVal.IsEmpty()) {
|
||||
mForm->RemoveElementFromTable(this, nameVal);
|
||||
@ -3062,7 +3069,7 @@ nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm,
|
||||
}
|
||||
|
||||
if (mForm) {
|
||||
mForm->AddElement(this);
|
||||
mForm->AddElement(this, aNotify);
|
||||
|
||||
if (!nameVal.IsEmpty()) {
|
||||
mForm->AddElementToTable(this, nameVal);
|
||||
@ -3182,12 +3189,12 @@ nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
// Might need to unset mForm
|
||||
if (aNullParent) {
|
||||
// No more parent means no more form
|
||||
SetForm(nsnull);
|
||||
SetForm(nsnull, PR_TRUE, PR_TRUE);
|
||||
} else {
|
||||
// Recheck whether we should still have an mForm.
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form = FindForm(mForm);
|
||||
if (!form) {
|
||||
SetForm(nsnull);
|
||||
SetForm(nsnull, PR_TRUE, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3225,7 +3232,7 @@ nsGenericHTMLFormElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
mForm->RemoveElementFromTable(this, tmp);
|
||||
}
|
||||
|
||||
mForm->RemoveElement(this);
|
||||
mForm->RemoveElement(this, aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3262,7 +3269,7 @@ nsGenericHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
mForm->AddElementToTable(this, tmp);
|
||||
}
|
||||
|
||||
mForm->AddElement(this);
|
||||
mForm->AddElement(this, aNotify);
|
||||
}
|
||||
|
||||
// And notify on content state changes, if any
|
||||
@ -3306,12 +3313,21 @@ nsGenericHTMLFormElement::CanBeDisabled() const
|
||||
type != NS_FORM_OBJECT;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGenericHTMLFormElement::IsSubmitControl() const
|
||||
{
|
||||
PRInt32 type = GetType();
|
||||
return type == NS_FORM_INPUT_SUBMIT ||
|
||||
type == NS_FORM_BUTTON_SUBMIT ||
|
||||
type == NS_FORM_INPUT_IMAGE;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::FindAndSetForm()
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form = FindForm();
|
||||
if (form) {
|
||||
SetForm(form); // always succeeds
|
||||
SetForm(form, PR_TRUE, PR_TRUE); // always succeeds
|
||||
}
|
||||
}
|
||||
|
||||
@ -3332,6 +3348,13 @@ nsGenericHTMLFormElement::IntrinsicState() const
|
||||
state |= NS_EVENT_STATE_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (mForm && mForm->GetDefaultSubmitElement() == this) {
|
||||
NS_ASSERTION(IsSubmitControl(),
|
||||
"Default submit element that isn't a submit control.");
|
||||
// We are the default submit element (:default)
|
||||
state |= NS_EVENT_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
@ -788,7 +788,9 @@ public:
|
||||
// nsIFormControl
|
||||
NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm);
|
||||
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm,
|
||||
PRBool aRemoveFromForm = PR_TRUE);
|
||||
PRBool aRemoveFromForm,
|
||||
PRBool aNotify);
|
||||
|
||||
NS_IMETHOD SaveState()
|
||||
{
|
||||
return NS_OK;
|
||||
@ -801,6 +803,8 @@ public:
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
virtual PRBool IsSubmitControl() const;
|
||||
|
||||
// nsIContent
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
@ -164,12 +164,14 @@ public:
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
||||
// nsIForm
|
||||
NS_IMETHOD AddElement(nsIFormControl* aElement);
|
||||
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 GetElementCount(PRUint32* aCount) const;
|
||||
NS_IMETHOD RemoveElement(nsIFormControl* aElement);
|
||||
NS_IMETHOD RemoveElement(nsIFormControl* aElement,
|
||||
PRBool aNotify);
|
||||
NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
|
||||
const nsAString& aName);
|
||||
NS_IMETHOD ResolveName(const nsAString& aName,
|
||||
@ -181,6 +183,7 @@ public:
|
||||
NS_IMETHOD FlushPendingSubmission();
|
||||
NS_IMETHOD ForgetPendingSubmission();
|
||||
NS_IMETHOD GetActionURL(nsIURI** aActionURL);
|
||||
NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const;
|
||||
|
||||
// nsIRadioGroupContainer
|
||||
NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
|
||||
@ -304,6 +307,18 @@ protected:
|
||||
*/
|
||||
nsresult DoResolveName(const nsAString& aName, PRBool aFlushContent,
|
||||
nsISupports** aReturn);
|
||||
|
||||
/**
|
||||
* Reset the default submit element after the previous default submit control
|
||||
* is removed.
|
||||
*
|
||||
* Note that this, in the worst case, needs to run through all the form's
|
||||
* controls.
|
||||
*
|
||||
* @param aNotify If true, send nsIDocumentObserver notifications on the
|
||||
* new and previous default elements.
|
||||
*/
|
||||
nsresult ResetDefaultSubmitElement(PRBool aNotify);
|
||||
|
||||
//
|
||||
// Data members
|
||||
@ -336,6 +351,9 @@ protected:
|
||||
/** The web progress object we are currently listening to */
|
||||
nsCOMPtr<nsIWebProgress> mWebProgress;
|
||||
|
||||
/** The default submit element -- WEAK */
|
||||
nsIFormControl* mDefaultSubmitElement;
|
||||
|
||||
friend class nsFormControlEnumerator;
|
||||
|
||||
protected:
|
||||
@ -494,7 +512,8 @@ nsHTMLFormElement::nsHTMLFormElement(nsINodeInfo *aNodeInfo)
|
||||
mSubmitPopupState(openAbused),
|
||||
mSubmitInitiatedFromUserInput(PR_FALSE),
|
||||
mPendingSubmission(nsnull),
|
||||
mSubmittingRequest(nsnull)
|
||||
mSubmittingRequest(nsnull),
|
||||
mDefaultSubmitElement(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1196,8 +1215,10 @@ static PRInt32 CompareFormControlPosition(nsIFormControl *control1, nsIFormContr
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::AddElement(nsIFormControl* aChild)
|
||||
nsHTMLFormElement::AddElement(nsIFormControl* aChild,
|
||||
PRBool aNotify)
|
||||
{
|
||||
PRBool lastElement = PR_FALSE;
|
||||
if (ShouldBeInElements(aChild)) {
|
||||
PRUint32 count = ElementCount();
|
||||
|
||||
@ -1216,6 +1237,7 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild)
|
||||
if (position >= 0 || count == 0) {
|
||||
// WEAK - don't addref
|
||||
mControls->mElements.AppendElement(aChild);
|
||||
lastElement = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
PRInt32 low = 0, mid, high;
|
||||
@ -1261,6 +1283,34 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild)
|
||||
nsnull,
|
||||
NS_PASSWORDMANAGER_CATEGORY);
|
||||
}
|
||||
|
||||
// Default submit element handling
|
||||
if (aChild->IsSubmitControl()) {
|
||||
// The new child is the default submit if there was not previously
|
||||
// a default submit element, or if the new child is before the old
|
||||
// default submit element. To speed up parsing, the special case
|
||||
// of the last element in a form that already has a default submit
|
||||
// element is ignored as it cannot be the default submit element.
|
||||
nsIFormControl* oldControl = mDefaultSubmitElement;
|
||||
if (!mDefaultSubmitElement || (!lastElement &&
|
||||
CompareFormControlPosition(aChild, mDefaultSubmitElement) < 0)) {
|
||||
mDefaultSubmitElement = aChild;
|
||||
}
|
||||
|
||||
// Notify that the states of the new default submit and the previous
|
||||
// default submit element have changed if the element which is the
|
||||
// default submit element has changed.
|
||||
if (aNotify && oldControl != mDefaultSubmitElement) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
nsCOMPtr<nsIContent> oldElement(do_QueryInterface(oldControl));
|
||||
nsCOMPtr<nsIContent> newElement(do_QueryInterface(mDefaultSubmitElement));
|
||||
document->ContentStatesChanged(oldElement, newElement,
|
||||
NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1274,14 +1324,16 @@ nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild,
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::RemoveElement(nsIFormControl* aChild)
|
||||
nsHTMLFormElement::RemoveElement(nsIFormControl* aChild,
|
||||
PRBool aNotify)
|
||||
{
|
||||
//
|
||||
// Remove it from the radio group if it's a radio button
|
||||
//
|
||||
nsresult rv = NS_OK;
|
||||
if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIRadioControlElement> radio = do_QueryInterface(aChild);
|
||||
nsresult rv = radio->WillRemoveFromRadioGroup();
|
||||
rv = radio->WillRemoveFromRadioGroup();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -1291,9 +1343,58 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild)
|
||||
mControls->mNotInElements.RemoveElement(aChild);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
if (aChild == mDefaultSubmitElement) {
|
||||
// We are removing the default submit, find the new default
|
||||
rv = ResetDefaultSubmitElement(aNotify);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::ResetDefaultSubmitElement(PRBool aNotify)
|
||||
{
|
||||
nsIFormControl* oldDefaultSubmit = mDefaultSubmitElement;
|
||||
mDefaultSubmitElement = nsnull;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> formControls;
|
||||
GetControlEnumerator(getter_AddRefs(formControls));
|
||||
|
||||
nsCOMPtr<nsISupports> currentControlSupports;
|
||||
nsCOMPtr<nsIFormControl> currentControl;
|
||||
|
||||
// Find default submit element
|
||||
PRBool hasMoreElements;
|
||||
nsresult rv;
|
||||
while (NS_SUCCEEDED(rv = formControls->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
rv = formControls->GetNext(getter_AddRefs(currentControlSupports));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
currentControl = do_QueryInterface(currentControlSupports);
|
||||
if (currentControl && currentControl->IsSubmitControl()) {
|
||||
mDefaultSubmitElement = currentControl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Inform about change.
|
||||
if (aNotify && (oldDefaultSubmit || mDefaultSubmitElement)) {
|
||||
NS_ASSERTION(mDefaultSubmitElement != oldDefaultSubmit,
|
||||
"Notifying but elements haven't changed.");
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
nsCOMPtr<nsIContent> oldElement(do_QueryInterface(oldDefaultSubmit));
|
||||
nsCOMPtr<nsIContent> newElement(do_QueryInterface(mDefaultSubmitElement));
|
||||
document->ContentStatesChanged(oldElement, newElement,
|
||||
NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::RemoveElementFromTable(nsIFormControl* aElement,
|
||||
const nsAString& aName)
|
||||
@ -1457,6 +1558,12 @@ nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIFormControl*)
|
||||
nsHTMLFormElement::GetDefaultSubmitElement() const
|
||||
{
|
||||
return mDefaultSubmitElement;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::GetEncoding(nsAString& aEncoding)
|
||||
{
|
||||
@ -1826,7 +1933,7 @@ nsFormControlList::Clear()
|
||||
nsIFormControl* f = NS_STATIC_CAST(nsIFormControl *,
|
||||
mElements.ElementAt(i));
|
||||
if (f) {
|
||||
f->SetForm(nsnull, PR_FALSE);
|
||||
f->SetForm(nsnull, PR_FALSE, PR_TRUE);
|
||||
}
|
||||
}
|
||||
mElements.Clear();
|
||||
@ -1835,7 +1942,7 @@ nsFormControlList::Clear()
|
||||
nsIFormControl* f = NS_STATIC_CAST(nsIFormControl*,
|
||||
mNotInElements.ElementAt(i));
|
||||
if (f) {
|
||||
f->SetForm(nsnull, PR_FALSE);
|
||||
f->SetForm(nsnull, PR_FALSE, PR_TRUE);
|
||||
}
|
||||
}
|
||||
mNotInElements.Clear();
|
||||
|
@ -517,18 +517,28 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
//
|
||||
// Checked must be set no matter what type of control it is, since
|
||||
// GetChecked() must reflect the new value
|
||||
//
|
||||
if (aName == nsHTMLAtoms::checked &&
|
||||
!GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)) {
|
||||
// Delay setting checked if the parser is creating this element
|
||||
// (wait until everything is set)
|
||||
if (GET_BOOLBIT(mBitField, BF_PARSER_CREATING)) {
|
||||
SET_BOOLBIT(mBitField, BF_SHOULD_INIT_CHECKED, PR_TRUE);
|
||||
} else {
|
||||
PRBool defaultChecked;
|
||||
GetDefaultChecked(&defaultChecked);
|
||||
DoSetChecked(defaultChecked);
|
||||
SetCheckedChanged(PR_FALSE);
|
||||
if (aName == nsHTMLAtoms::checked) {
|
||||
if (aNotify &&
|
||||
(mType == NS_FORM_INPUT_RADIO || mType == NS_FORM_INPUT_CHECKBOX)) {
|
||||
// the checked attribute being changed, no matter the current checked
|
||||
// state, influences the :default state, so notify about changes
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
|
||||
document->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
if (!GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)) {
|
||||
// Delay setting checked if the parser is creating this element (wait
|
||||
// until everything is set)
|
||||
if (GET_BOOLBIT(mBitField, BF_PARSER_CREATING)) {
|
||||
SET_BOOLBIT(mBitField, BF_SHOULD_INIT_CHECKED, PR_TRUE);
|
||||
} else {
|
||||
PRBool defaultChecked;
|
||||
GetDefaultChecked(&defaultChecked);
|
||||
DoSetChecked(defaultChecked);
|
||||
SetCheckedChanged(PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1012,53 +1022,48 @@ nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the first submit control in elements[]
|
||||
// and also check how many text controls we have in the form
|
||||
nsCOMPtr<nsIContent> submitControl;
|
||||
PRInt32 numTextControlsFound = 0;
|
||||
nsIPresShell* shell = aPresContext->GetPresShell();
|
||||
if (!shell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> formControls;
|
||||
mForm->GetControlEnumerator(getter_AddRefs(formControls));
|
||||
// Get the default submit element
|
||||
nsIFormControl* submitControl = mForm->GetDefaultSubmitElement();
|
||||
if (submitControl) {
|
||||
nsCOMPtr<nsIContent> submitContent(do_QueryInterface(submitControl));
|
||||
NS_ASSERTION(submitContent, "Form control not implementing nsIContent?!");
|
||||
// Fire the button's onclick handler and let the button handle
|
||||
// submitting the form.
|
||||
nsMouseEvent event(PR_TRUE, NS_MOUSE_LEFT_CLICK, nsnull,
|
||||
nsMouseEvent::eReal);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
shell->HandleDOMEventWithTarget(submitContent, &event, &status);
|
||||
} else {
|
||||
PRInt32 numTextControlsFound = 0;
|
||||
// No default submit, find the number of text controls.
|
||||
nsCOMPtr<nsISimpleEnumerator> formControls;
|
||||
mForm->GetControlEnumerator(getter_AddRefs(formControls));
|
||||
|
||||
nsCOMPtr<nsISupports> currentControlSupports;
|
||||
nsCOMPtr<nsIFormControl> currentControl;
|
||||
PRBool hasMoreElements;
|
||||
nsresult rv;
|
||||
while (NS_SUCCEEDED(rv = formControls->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
rv = formControls->GetNext(getter_AddRefs(currentControlSupports));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsISupports> currentControlSupports;
|
||||
nsCOMPtr<nsIFormControl> currentControl;
|
||||
PRBool hasMoreElements;
|
||||
nsresult rv;
|
||||
while (NS_SUCCEEDED(rv = formControls->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements && numTextControlsFound < 2) {
|
||||
rv = formControls->GetNext(getter_AddRefs(currentControlSupports));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
currentControl = do_QueryInterface(currentControlSupports);
|
||||
if (currentControl) {
|
||||
PRInt32 type = currentControl->GetType();
|
||||
if (!submitControl &&
|
||||
(type == NS_FORM_INPUT_SUBMIT ||
|
||||
type == NS_FORM_BUTTON_SUBMIT ||
|
||||
type == NS_FORM_INPUT_IMAGE)) {
|
||||
submitControl = do_QueryInterface(currentControl);
|
||||
// We know as soon as we find a submit control that it no
|
||||
// longer matters how many text controls there are--we are
|
||||
// going to fire the onClick handler.
|
||||
break;
|
||||
} else if (type == NS_FORM_INPUT_TEXT ||
|
||||
type == NS_FORM_INPUT_PASSWORD) {
|
||||
numTextControlsFound++;
|
||||
currentControl = do_QueryInterface(currentControlSupports);
|
||||
if (currentControl) {
|
||||
PRInt32 type = currentControl->GetType();
|
||||
if (type == NS_FORM_INPUT_TEXT ||
|
||||
type == NS_FORM_INPUT_PASSWORD) {
|
||||
numTextControlsFound++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIPresShell* shell = aPresContext->GetPresShell();
|
||||
if (shell) {
|
||||
if (submitControl) {
|
||||
// Fire the button's onclick handler and let the button handle
|
||||
// submitting the form.
|
||||
nsMouseEvent event(PR_TRUE, NS_MOUSE_LEFT_CLICK, nsnull,
|
||||
nsMouseEvent::eReal);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
shell->HandleDOMEventWithTarget(submitControl, &event, &status);
|
||||
} else if (numTextControlsFound == 1) {
|
||||
|
||||
if (numTextControlsFound == 1) {
|
||||
// If there's only one text control, just submit the form
|
||||
nsCOMPtr<nsIContent> form = do_QueryInterface(mForm);
|
||||
nsFormEvent event(PR_TRUE, NS_FORM_SUBMIT);
|
||||
@ -2561,13 +2566,24 @@ PRInt32
|
||||
nsHTMLInputElement::IntrinsicState() const
|
||||
{
|
||||
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
|
||||
if (GET_BOOLBIT(mBitField, BF_CHECKED) &&
|
||||
(mType == NS_FORM_INPUT_CHECKBOX ||
|
||||
mType == NS_FORM_INPUT_RADIO)) {
|
||||
state |= NS_EVENT_STATE_CHECKED;
|
||||
if (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) {
|
||||
// Check current checked state (:checked)
|
||||
if (GET_BOOLBIT(mBitField, BF_CHECKED)) {
|
||||
state |= NS_EVENT_STATE_CHECKED;
|
||||
}
|
||||
|
||||
// Check whether we are the default checked element (:default)
|
||||
// The call is to an interface function, which makes it non-const, so we
|
||||
// use a nasty hack :(
|
||||
PRBool defaultState = PR_FALSE;
|
||||
NS_CONST_CAST(nsHTMLInputElement*, this)->GetDefaultChecked(&defaultState);
|
||||
if (defaultState) {
|
||||
state |= NS_EVENT_STATE_DEFAULT;
|
||||
}
|
||||
} else if (mType == NS_FORM_INPUT_IMAGE) {
|
||||
state |= nsImageLoadingContent::ImageState();
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -427,6 +427,12 @@ nsHTMLOptionElement::IntrinsicState() const
|
||||
state |= NS_EVENT_STATE_CHECKED;
|
||||
}
|
||||
|
||||
// Also calling a non-const interface method (for :default)
|
||||
NS_CONST_CAST(nsHTMLOptionElement*, this)->GetDefaultSelected(&selected);
|
||||
if (selected) {
|
||||
state |= NS_EVENT_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
PRBool disabled;
|
||||
GetBoolAttr(nsHTMLAtoms::disabled, &disabled);
|
||||
if (disabled) {
|
||||
@ -463,12 +469,18 @@ nsHTMLOptionElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
if (aNotify && aNameSpaceID == kNameSpaceID_None &&
|
||||
aName == nsHTMLAtoms::disabled) {
|
||||
(aName == nsHTMLAtoms::disabled || aName == nsHTMLAtoms::selected)) {
|
||||
PRInt32 states;
|
||||
if (aName == nsHTMLAtoms::disabled) {
|
||||
states = NS_EVENT_STATE_DISABLED | NS_EVENT_STATE_ENABLED;
|
||||
} else {
|
||||
states = NS_EVENT_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
document->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_DISABLED |
|
||||
NS_EVENT_STATE_ENABLED);
|
||||
document->ContentStatesChanged(this, nsnull, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,7 +765,7 @@ MaybeSetForm(nsGenericHTMLElement* aContent, nsHTMLTag aNodeType,
|
||||
NS_ASSERTION(!form || formElement,
|
||||
"nsGenericHTMLElement didn't implement nsIDOMHTMLFormElement");
|
||||
|
||||
formControl->SetForm(formElement);
|
||||
formControl->SetForm(formElement, PR_TRUE, PR_FALSE);
|
||||
}
|
||||
|
||||
static already_AddRefed<nsGenericHTMLElement>
|
||||
|
@ -96,5 +96,6 @@ CSS_PSEUDO_CLASS(valid, ":valid")
|
||||
CSS_PSEUDO_CLASS(invalid, ":invalid")
|
||||
CSS_PSEUDO_CLASS(inRange, ":in-range")
|
||||
CSS_PSEUDO_CLASS(outOfRange, ":out-of-range")
|
||||
CSS_PSEUDO_CLASS(defaultPseudo, ":default")
|
||||
CSS_PSEUDO_CLASS(mozReadOnly, ":-moz-read-only")
|
||||
CSS_PSEUDO_CLASS(mozReadWrite, ":-moz-read-write")
|
||||
|
@ -1229,6 +1229,9 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
else if (nsCSSPseudoClasses::mozTypeUnsupported == pseudoClass->mAtom) {
|
||||
stateToCheck = NS_EVENT_STATE_TYPE_UNSUPPORTED;
|
||||
}
|
||||
else if (nsCSSPseudoClasses::defaultPseudo == pseudoClass->mAtom) {
|
||||
stateToCheck = NS_EVENT_STATE_DEFAULT;
|
||||
}
|
||||
else if (nsCSSPseudoClasses::required == pseudoClass->mAtom) {
|
||||
stateToCheck = NS_EVENT_STATE_REQUIRED;
|
||||
}
|
||||
@ -1827,7 +1830,8 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
|
||||
(pseudoClass->mAtom == nsCSSPseudoClasses::inRange) ||
|
||||
(pseudoClass->mAtom == nsCSSPseudoClasses::outOfRange) ||
|
||||
(pseudoClass->mAtom == nsCSSPseudoClasses::mozReadOnly) ||
|
||||
(pseudoClass->mAtom == nsCSSPseudoClasses::mozReadWrite)) {
|
||||
(pseudoClass->mAtom == nsCSSPseudoClasses::mozReadWrite) ||
|
||||
(pseudoClass->mAtom == nsCSSPseudoClasses::defaultPseudo)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user