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:
bzbarsky%mit.edu 2006-08-16 03:20:19 +00:00
Родитель b3167d713e
Коммит a3a40f6eb5
11 изменённых файлов: 280 добавлений и 94 удалений

Просмотреть файл

@ -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;
}
}