зеркало из https://github.com/mozilla/gecko-dev.git
Bug 558788 - Valid/Invalid form elements should change their state to use CSS3 pseudo-classes :valid and :invalid. f=ehsan r=sicking,dbaron sr=jst a2.0=blocking
This commit is contained in:
Родитель
3208373dd5
Коммит
8ddd08ad04
|
@ -97,4 +97,11 @@ NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
|
||||||
nsIFormControl* aExcludeElement,
|
nsIFormControl* aExcludeElement,
|
||||||
nsIRadioVisitor** aVisitor);
|
nsIRadioVisitor** aVisitor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This visitor will make sure all radio into the group updates their
|
||||||
|
* value missing validity state.
|
||||||
|
*/
|
||||||
|
nsIRadioVisitor*
|
||||||
|
NS_GetRadioUpdateValueMissingVisitor(PRBool aNotify);
|
||||||
|
|
||||||
#endif // nsIRadioVisitor_h___
|
#endif // nsIRadioVisitor_h___
|
||||||
|
|
|
@ -194,6 +194,11 @@ public:
|
||||||
*/
|
*/
|
||||||
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify) = 0;
|
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback called whenever the value is changed.
|
||||||
|
*/
|
||||||
|
NS_IMETHOD_(void) OnValueChanged(PRBool aNotify) = 0;
|
||||||
|
|
||||||
static const PRInt32 DEFAULT_COLS = 20;
|
static const PRInt32 DEFAULT_COLS = 20;
|
||||||
static const PRInt32 DEFAULT_ROWS = 1;
|
static const PRInt32 DEFAULT_ROWS = 1;
|
||||||
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;
|
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;
|
||||||
|
|
|
@ -40,6 +40,14 @@
|
||||||
#include "nsAString.h"
|
#include "nsAString.h"
|
||||||
#include "nsGenericHTMLElement.h"
|
#include "nsGenericHTMLElement.h"
|
||||||
#include "nsHTMLFormElement.h"
|
#include "nsHTMLFormElement.h"
|
||||||
|
#include "nsDOMValidityState.h"
|
||||||
|
|
||||||
|
|
||||||
|
nsConstraintValidation::nsConstraintValidation()
|
||||||
|
: mValidityBitField(0)
|
||||||
|
, mValidity(nsnull)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
nsConstraintValidation::~nsConstraintValidation()
|
nsConstraintValidation::~nsConstraintValidation()
|
||||||
{
|
{
|
||||||
|
@ -69,22 +77,22 @@ nsConstraintValidation::GetWillValidate(PRBool* aWillValidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsConstraintValidation::GetValidationMessage(nsAString & aValidationMessage,
|
nsConstraintValidation::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
nsGenericHTMLFormElement* aElement)
|
nsGenericHTMLFormElement* aElement)
|
||||||
{
|
{
|
||||||
aValidationMessage.Truncate();
|
aValidationMessage.Truncate();
|
||||||
|
|
||||||
if (IsCandidateForConstraintValidation(aElement) && !IsValid()) {
|
if (IsCandidateForConstraintValidation(aElement) && !IsValid()) {
|
||||||
if (!mCustomValidity.IsEmpty()) {
|
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
|
||||||
aValidationMessage.Assign(mCustomValidity);
|
aValidationMessage.Assign(mCustomValidity);
|
||||||
} else if (IsTooLong()) {
|
} else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
|
||||||
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_TOO_LONG);
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
|
||||||
} else if (IsValueMissing()) {
|
} else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) {
|
||||||
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_VALUE_MISSING);
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_VALUE_MISSING);
|
||||||
} else if (HasTypeMismatch()) {
|
} else if (GetValidityState(VALIDITY_STATE_TYPE_MISMATCH)) {
|
||||||
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_TYPE_MISMATCH);
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TYPE_MISMATCH);
|
||||||
} else if (HasPatternMismatch()) {
|
} else if (GetValidityState(VALIDITY_STATE_PATTERN_MISMATCH)) {
|
||||||
GetValidationMessage(aValidationMessage, VALIDATION_MESSAGE_PATTERN_MISMATCH);
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
|
||||||
} else {
|
} else {
|
||||||
// TODO: The other messages have not been written
|
// TODO: The other messages have not been written
|
||||||
// because related constraint validation are not implemented yet.
|
// because related constraint validation are not implemented yet.
|
||||||
|
@ -116,28 +124,15 @@ nsConstraintValidation::CheckValidity(PRBool* aValidity,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsConstraintValidation::SetCustomValidity(const nsAString & aError)
|
nsConstraintValidation::SetCustomValidity(const nsAString& aError)
|
||||||
{
|
{
|
||||||
mCustomValidity.Assign(aError);
|
mCustomValidity.Assign(aError);
|
||||||
|
SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, !mCustomValidity.IsEmpty());
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsConstraintValidation::HasCustomError() const
|
nsConstraintValidation::IsCandidateForConstraintValidation(const nsGenericHTMLFormElement* const aElement) const
|
||||||
{
|
|
||||||
return !mCustomValidity.IsEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsConstraintValidation::IsValid()
|
|
||||||
{
|
|
||||||
return !(IsValueMissing() || HasTypeMismatch() || HasPatternMismatch() ||
|
|
||||||
IsTooLong() || HasRangeUnderflow() || HasRangeOverflow() ||
|
|
||||||
HasStepMismatch() || HasCustomError());
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsConstraintValidation::IsCandidateForConstraintValidation(nsGenericHTMLFormElement* aElement)
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* An element is never candidate for constraint validation if:
|
* An element is never candidate for constraint validation if:
|
||||||
|
|
|
@ -38,71 +38,101 @@
|
||||||
#ifndef nsConstraintValidition_h___
|
#ifndef nsConstraintValidition_h___
|
||||||
#define nsConstraintValidition_h___
|
#define nsConstraintValidition_h___
|
||||||
|
|
||||||
#include "nsDOMValidityState.h"
|
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
|
||||||
|
class nsDOMValidityState;
|
||||||
|
class nsIDOMValidityState;
|
||||||
class nsGenericHTMLFormElement;
|
class nsGenericHTMLFormElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is used for form elements implementing the
|
* This interface is used for form elements implementing the
|
||||||
* validity constraint API.
|
* validity constraint API.
|
||||||
* See: http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
|
* See: http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
|
||||||
|
*
|
||||||
|
* This class has to be inherited by all elements implementing the API.
|
||||||
*/
|
*/
|
||||||
class nsConstraintValidation
|
class nsConstraintValidation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
friend class nsDOMValidityState;
|
||||||
|
|
||||||
virtual ~nsConstraintValidation();
|
virtual ~nsConstraintValidation();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
enum ValidityStateType
|
||||||
|
{
|
||||||
|
VALIDITY_STATE_VALUE_MISSING = 0x01, // 0b00000001
|
||||||
|
VALIDITY_STATE_TYPE_MISMATCH = 0x02, // 0b00000010
|
||||||
|
VALIDITY_STATE_PATTERN_MISMATCH = 0x04, // 0b00000100
|
||||||
|
VALIDITY_STATE_TOO_LONG = 0x08, // 0b00001000
|
||||||
|
VALIDITY_STATE_RANGE_UNDERFLOW = 0x10, // 0b00010000
|
||||||
|
VALIDITY_STATE_RANGE_OVERFLOW = 0x20, // 0b00100000
|
||||||
|
VALIDITY_STATE_STEP_MISMATCH = 0x40, // 0b01000000
|
||||||
|
VALIDITY_STATE_CUSTOM_ERROR = 0x80 // 0b10000000
|
||||||
|
};
|
||||||
|
|
||||||
|
// You can't instantiate an object from that class.
|
||||||
|
nsConstraintValidation();
|
||||||
|
|
||||||
nsresult GetValidity(nsIDOMValidityState** aValidity);
|
nsresult GetValidity(nsIDOMValidityState** aValidity);
|
||||||
nsresult GetWillValidate(PRBool* aWillValidate,
|
nsresult GetWillValidate(PRBool* aWillValidate,
|
||||||
nsGenericHTMLFormElement* aElement);
|
nsGenericHTMLFormElement* aElement);
|
||||||
nsresult GetValidationMessage(nsAString & aValidationMessage,
|
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
||||||
nsGenericHTMLFormElement* aElement);
|
nsGenericHTMLFormElement* aElement);
|
||||||
nsresult CheckValidity(PRBool* aValidity,
|
nsresult CheckValidity(PRBool* aValidity,
|
||||||
nsGenericHTMLFormElement* aElement);
|
nsGenericHTMLFormElement* aElement);
|
||||||
nsresult SetCustomValidity(const nsAString & aError);
|
nsresult SetCustomValidity(const nsAString& aError);
|
||||||
|
|
||||||
virtual PRBool IsValueMissing () { return PR_FALSE; }
|
PRBool IsValid() const { return mValidityBitField == 0; }
|
||||||
virtual PRBool HasTypeMismatch () { return PR_FALSE; }
|
|
||||||
virtual PRBool HasPatternMismatch() { return PR_FALSE; }
|
|
||||||
virtual PRBool IsTooLong () { return PR_FALSE; }
|
|
||||||
virtual PRBool HasRangeUnderflow () { return PR_FALSE; }
|
|
||||||
virtual PRBool HasRangeOverflow () { return PR_FALSE; }
|
|
||||||
virtual PRBool HasStepMismatch () { return PR_FALSE; }
|
|
||||||
PRBool HasCustomError () const;
|
|
||||||
PRBool IsValid ();
|
|
||||||
|
|
||||||
protected:
|
bool GetValidityState(ValidityStateType mState) const {
|
||||||
|
return mValidityBitField & mState;
|
||||||
|
}
|
||||||
|
|
||||||
enum ValidationMessageType
|
void SetValidityState(ValidityStateType mState, PRBool mValue) {
|
||||||
{
|
if (mValue) {
|
||||||
VALIDATION_MESSAGE_VALUE_MISSING,
|
mValidityBitField |= mState;
|
||||||
VALIDATION_MESSAGE_TYPE_MISMATCH,
|
} else {
|
||||||
VALIDATION_MESSAGE_PATTERN_MISMATCH,
|
mValidityBitField &= ~mState;
|
||||||
VALIDATION_MESSAGE_TOO_LONG,
|
}
|
||||||
VALIDATION_MESSAGE_RANGE_UNDERFLOW,
|
}
|
||||||
VALIDATION_MESSAGE_RANGE_OVERFLOW,
|
|
||||||
VALIDATION_MESSAGE_STEP_MISMATCH
|
PRBool IsCandidateForConstraintValidation(const nsGenericHTMLFormElement* const aElement) const;
|
||||||
};
|
|
||||||
|
virtual PRBool IsBarredFromConstraintValidation() const { return PR_FALSE; }
|
||||||
|
|
||||||
PRBool IsCandidateForConstraintValidation(nsGenericHTMLFormElement* aElement);
|
|
||||||
virtual PRBool IsBarredFromConstraintValidation() { return PR_FALSE; }
|
|
||||||
virtual nsresult GetValidationMessage(nsAString& aValidationMessage,
|
virtual nsresult GetValidationMessage(nsAString& aValidationMessage,
|
||||||
ValidationMessageType aType) {
|
ValidityStateType aType) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitfield representing the current validity state of the element.
|
||||||
|
* Each bit represent an error. All bits to zero means the element is valid.
|
||||||
|
*/
|
||||||
|
PRInt8 mValidityBitField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pointer to the ValidityState object.
|
||||||
|
*/
|
||||||
nsRefPtr<nsDOMValidityState> mValidity;
|
nsRefPtr<nsDOMValidityState> mValidity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string representing the custom error.
|
||||||
|
*/
|
||||||
nsString mCustomValidity;
|
nsString mCustomValidity;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this macro for class inherit from nsConstraintValidation to forward
|
* Use these macro for class inherit from nsConstraintValidation to forward
|
||||||
* functions to nsConstraintValidation.
|
* functions to nsConstraintValidation.
|
||||||
*/
|
*/
|
||||||
#define NS_FORWARD_NSCONSTRAINTVALIDATION \
|
#define NS_FORWARD_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY \
|
||||||
NS_IMETHOD GetValidity(nsIDOMValidityState** aValidity) { \
|
NS_IMETHOD GetValidity(nsIDOMValidityState** aValidity) { \
|
||||||
return nsConstraintValidation::GetValidity(aValidity); \
|
return nsConstraintValidation::GetValidity(aValidity); \
|
||||||
} \
|
} \
|
||||||
|
@ -112,16 +142,19 @@ protected:
|
||||||
NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage) { \
|
NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage) { \
|
||||||
return nsConstraintValidation::GetValidationMessage(aValidationMessage, this); \
|
return nsConstraintValidation::GetValidationMessage(aValidationMessage, this); \
|
||||||
} \
|
} \
|
||||||
NS_IMETHOD SetCustomValidity(const nsAString& aError) { \
|
|
||||||
return nsConstraintValidation::SetCustomValidity(aError); \
|
|
||||||
} \
|
|
||||||
NS_IMETHOD CheckValidity(PRBool* aValidity) { \
|
NS_IMETHOD CheckValidity(PRBool* aValidity) { \
|
||||||
return nsConstraintValidation::CheckValidity(aValidity, this); \
|
return nsConstraintValidation::CheckValidity(aValidity, this); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NS_FORWARD_NSCONSTRAINTVALIDATION \
|
||||||
|
NS_FORWARD_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY \
|
||||||
|
NS_IMETHOD SetCustomValidity(const nsAString& aError) { \
|
||||||
|
return nsConstraintValidation::SetCustomValidity(aError); \
|
||||||
|
}
|
||||||
|
|
||||||
/* Use this macro when class declares functions from nsConstraintValidation */
|
|
||||||
#define NS_IMPL_NSCONSTRAINTVALIDATION(_from) \
|
/* Use these macro when class declares functions from nsConstraintValidation */
|
||||||
|
#define NS_IMPL_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(_from) \
|
||||||
NS_IMETHODIMP _from::GetValidity(nsIDOMValidityState** aValidity) { \
|
NS_IMETHODIMP _from::GetValidity(nsIDOMValidityState** aValidity) { \
|
||||||
return nsConstraintValidation::GetValidity(aValidity); \
|
return nsConstraintValidation::GetValidity(aValidity); \
|
||||||
} \
|
} \
|
||||||
|
@ -131,13 +164,16 @@ protected:
|
||||||
NS_IMETHODIMP _from::GetValidationMessage(nsAString& aValidationMessage) { \
|
NS_IMETHODIMP _from::GetValidationMessage(nsAString& aValidationMessage) { \
|
||||||
return nsConstraintValidation::GetValidationMessage(aValidationMessage, this); \
|
return nsConstraintValidation::GetValidationMessage(aValidationMessage, this); \
|
||||||
} \
|
} \
|
||||||
NS_IMETHODIMP _from::SetCustomValidity(const nsAString& aError) { \
|
|
||||||
return nsConstraintValidation::SetCustomValidity(aError); \
|
|
||||||
} \
|
|
||||||
NS_IMETHODIMP _from::CheckValidity(PRBool* aValidity) { \
|
NS_IMETHODIMP _from::CheckValidity(PRBool* aValidity) { \
|
||||||
return nsConstraintValidation::CheckValidity(aValidity, this); \
|
return nsConstraintValidation::CheckValidity(aValidity, this); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NS_IMPL_NSCONSTRAINTVALIDATION(_from) \
|
||||||
|
NS_IMPL_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(_from) \
|
||||||
|
NS_IMETHODIMP _from::SetCustomValidity(const nsAString& aError) { \
|
||||||
|
return nsConstraintValidation::SetCustomValidity(aError); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // nsConstraintValidation_h___
|
#endif // nsConstraintValidation_h___
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "nsDOMValidityState.h"
|
#include "nsDOMValidityState.h"
|
||||||
|
|
||||||
#include "nsDOMClassInfo.h"
|
#include "nsDOMClassInfo.h"
|
||||||
#include "nsConstraintValidation.h"
|
|
||||||
|
|
||||||
|
|
||||||
DOMCI_DATA(ValidityState, nsDOMValidityState)
|
DOMCI_DATA(ValidityState, nsDOMValidityState)
|
||||||
|
@ -60,56 +59,56 @@ nsDOMValidityState::nsDOMValidityState(nsConstraintValidation* aConstraintValida
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetValueMissing(PRBool* aValueMissing)
|
nsDOMValidityState::GetValueMissing(PRBool* aValueMissing)
|
||||||
{
|
{
|
||||||
*aValueMissing = mConstraintValidation && mConstraintValidation->IsValueMissing();
|
*aValueMissing = GetValidityState(nsConstraintValidation::VALIDITY_STATE_VALUE_MISSING);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetTypeMismatch(PRBool* aTypeMismatch)
|
nsDOMValidityState::GetTypeMismatch(PRBool* aTypeMismatch)
|
||||||
{
|
{
|
||||||
*aTypeMismatch = mConstraintValidation && mConstraintValidation->HasTypeMismatch();
|
*aTypeMismatch = GetValidityState(nsConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetPatternMismatch(PRBool* aPatternMismatch)
|
nsDOMValidityState::GetPatternMismatch(PRBool* aPatternMismatch)
|
||||||
{
|
{
|
||||||
*aPatternMismatch = mConstraintValidation && mConstraintValidation->HasPatternMismatch();
|
*aPatternMismatch = GetValidityState(nsConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetTooLong(PRBool* aTooLong)
|
nsDOMValidityState::GetTooLong(PRBool* aTooLong)
|
||||||
{
|
{
|
||||||
*aTooLong = mConstraintValidation && mConstraintValidation->IsTooLong();
|
*aTooLong = GetValidityState(nsConstraintValidation::VALIDITY_STATE_TOO_LONG);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetRangeUnderflow(PRBool* aRangeUnderflow)
|
nsDOMValidityState::GetRangeUnderflow(PRBool* aRangeUnderflow)
|
||||||
{
|
{
|
||||||
*aRangeUnderflow = mConstraintValidation && mConstraintValidation->HasRangeUnderflow();
|
*aRangeUnderflow = GetValidityState(nsConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetRangeOverflow(PRBool* aRangeOverflow)
|
nsDOMValidityState::GetRangeOverflow(PRBool* aRangeOverflow)
|
||||||
{
|
{
|
||||||
*aRangeOverflow = mConstraintValidation && mConstraintValidation->HasRangeOverflow();
|
*aRangeOverflow = GetValidityState(nsConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetStepMismatch(PRBool* aStepMismatch)
|
nsDOMValidityState::GetStepMismatch(PRBool* aStepMismatch)
|
||||||
{
|
{
|
||||||
*aStepMismatch = mConstraintValidation && mConstraintValidation->HasStepMismatch();
|
*aStepMismatch = GetValidityState(nsConstraintValidation::VALIDITY_STATE_STEP_MISMATCH);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMValidityState::GetCustomError(PRBool* aCustomError)
|
nsDOMValidityState::GetCustomError(PRBool* aCustomError)
|
||||||
{
|
{
|
||||||
*aCustomError = mConstraintValidation && mConstraintValidation->HasCustomError();
|
*aCustomError = GetValidityState(nsConstraintValidation::VALIDITY_STATE_CUSTOM_ERROR);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
#define nsDOMValidityState_h__
|
#define nsDOMValidityState_h__
|
||||||
|
|
||||||
#include "nsIDOMValidityState.h"
|
#include "nsIDOMValidityState.h"
|
||||||
|
#include "nsConstraintValidation.h"
|
||||||
|
|
||||||
class nsConstraintValidation;
|
|
||||||
|
|
||||||
class nsDOMValidityState : public nsIDOMValidityState
|
class nsDOMValidityState : public nsIDOMValidityState
|
||||||
{
|
{
|
||||||
|
@ -51,14 +51,26 @@ public:
|
||||||
friend class nsConstraintValidation;
|
friend class nsConstraintValidation;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This function should be called by nsConstraintValidation
|
nsDOMValidityState(nsConstraintValidation* aConstraintValidation);
|
||||||
// to set mConstraintValidation to null to be sure it will not be called.
|
|
||||||
void Disconnect()
|
/**
|
||||||
|
* This function should be called by nsConstraintValidation
|
||||||
|
* to set mConstraintValidation to null to be sure
|
||||||
|
* it will not be used when the object is destroyed.
|
||||||
|
*/
|
||||||
|
inline void Disconnect()
|
||||||
{
|
{
|
||||||
mConstraintValidation = nsnull;
|
mConstraintValidation = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDOMValidityState(nsConstraintValidation* aConstraintValidation);
|
/**
|
||||||
|
* Helper function to get a validity state from constraint validation instance.
|
||||||
|
*/
|
||||||
|
inline PRBool GetValidityState(nsConstraintValidation::ValidityStateType aState) const
|
||||||
|
{
|
||||||
|
return mConstraintValidation &&
|
||||||
|
mConstraintValidation->GetValidityState(aState);
|
||||||
|
}
|
||||||
|
|
||||||
nsConstraintValidation* mConstraintValidation;
|
nsConstraintValidation* mConstraintValidation;
|
||||||
};
|
};
|
||||||
|
|
|
@ -134,7 +134,7 @@ public:
|
||||||
virtual nsXPCClassInfo* GetClassInfo();
|
virtual nsXPCClassInfo* GetClassInfo();
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
PRBool IsBarredFromConstraintValidation();
|
PRBool IsBarredFromConstraintValidation() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual PRBool AcceptAutofocus() const
|
virtual PRBool AcceptAutofocus() const
|
||||||
|
@ -190,7 +190,7 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLButtonElement)
|
||||||
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLButtonElement)
|
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLButtonElement)
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLButtonElement)
|
NS_IMPL_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLButtonElement)
|
||||||
|
|
||||||
// nsIDOMHTMLButtonElement
|
// nsIDOMHTMLButtonElement
|
||||||
|
|
||||||
|
@ -611,11 +611,21 @@ nsresult
|
||||||
nsHTMLButtonElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
nsHTMLButtonElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAString* aValue, PRBool aNotify)
|
const nsAString* aValue, PRBool aNotify)
|
||||||
{
|
{
|
||||||
if (!aValue && aNameSpaceID == kNameSpaceID_None &&
|
if (aNameSpaceID == kNameSpaceID_None &&
|
||||||
aName == nsGkAtoms::type) {
|
aName == nsGkAtoms::type) {
|
||||||
|
if (!aValue) {
|
||||||
mType = kButtonDefaultType->value;
|
mType = kButtonDefaultType->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aNotify) {
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull,
|
||||||
|
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
|
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
|
||||||
aValue, aNotify);
|
aValue, aNotify);
|
||||||
}
|
}
|
||||||
|
@ -651,13 +661,33 @@ nsHTMLButtonElement::RestoreState(nsPresState* aState)
|
||||||
PRInt32
|
PRInt32
|
||||||
nsHTMLButtonElement::IntrinsicState() const
|
nsHTMLButtonElement::IntrinsicState() const
|
||||||
{
|
{
|
||||||
return NS_EVENT_STATE_OPTIONAL | nsGenericHTMLFormElement::IntrinsicState();
|
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
|
||||||
|
|
||||||
|
if (IsCandidateForConstraintValidation(this)) {
|
||||||
|
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state | NS_EVENT_STATE_OPTIONAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLButtonElement::SetCustomValidity(const nsAString& aError)
|
||||||
|
{
|
||||||
|
nsresult rv = nsConstraintValidation::SetCustomValidity(aError);
|
||||||
|
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
|
||||||
|
NS_EVENT_STATE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLButtonElement::IsBarredFromConstraintValidation()
|
nsHTMLButtonElement::IsBarredFromConstraintValidation() const
|
||||||
{
|
{
|
||||||
return (mType == NS_FORM_BUTTON_BUTTON ||
|
return (mType == NS_FORM_BUTTON_BUTTON ||
|
||||||
mType == NS_FORM_BUTTON_RESET);
|
mType == NS_FORM_BUTTON_RESET);
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
virtual nsXPCClassInfo* GetClassInfo();
|
virtual nsXPCClassInfo* GetClassInfo();
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
PRBool IsBarredFromConstraintValidation() { return PR_TRUE; };
|
PRBool IsBarredFromConstraintValidation() const { return PR_TRUE; };
|
||||||
};
|
};
|
||||||
|
|
||||||
// construction, destruction
|
// construction, destruction
|
||||||
|
|
|
@ -1186,7 +1186,7 @@ nsHTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
|
||||||
if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
|
if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
|
||||||
nsRefPtr<nsHTMLInputElement> radio =
|
nsRefPtr<nsHTMLInputElement> radio =
|
||||||
static_cast<nsHTMLInputElement*>(aChild);
|
static_cast<nsHTMLInputElement*>(aChild);
|
||||||
radio->WillRemoveFromRadioGroup();
|
radio->WillRemoveFromRadioGroup(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether to remove the child from the elements list
|
// Determine whether to remove the child from the elements list
|
||||||
|
|
|
@ -311,7 +311,7 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement)
|
||||||
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLInputElement)
|
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLInputElement)
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLInputElement)
|
NS_IMPL_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLInputElement)
|
||||||
|
|
||||||
// nsIDOMNode
|
// nsIDOMNode
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ nsHTMLInputElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
(aName == nsGkAtoms::type && !mForm)) &&
|
(aName == nsGkAtoms::type && !mForm)) &&
|
||||||
mType == NS_FORM_INPUT_RADIO &&
|
mType == NS_FORM_INPUT_RADIO &&
|
||||||
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
|
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
|
||||||
WillRemoveFromRadioGroup();
|
WillRemoveFromRadioGroup(aNotify);
|
||||||
} else if (aNotify && aName == nsGkAtoms::src &&
|
} else if (aNotify && aName == nsGkAtoms::src &&
|
||||||
mType == NS_FORM_INPUT_IMAGE) {
|
mType == NS_FORM_INPUT_IMAGE) {
|
||||||
if (aValue) {
|
if (aValue) {
|
||||||
|
@ -410,6 +410,9 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAString* aValue,
|
const nsAString* aValue,
|
||||||
PRBool aNotify)
|
PRBool aNotify)
|
||||||
{
|
{
|
||||||
|
// States changes that have to be passed to ContentStatesChanged().
|
||||||
|
PRInt32 states = 0;
|
||||||
|
|
||||||
if (aNameSpaceID == kNameSpaceID_None) {
|
if (aNameSpaceID == kNameSpaceID_None) {
|
||||||
//
|
//
|
||||||
// When name or type changes, radio should be added to radio group.
|
// When name or type changes, radio should be added to radio group.
|
||||||
|
@ -449,13 +452,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aName == nsGkAtoms::type) {
|
if (aName == nsGkAtoms::type) {
|
||||||
// Changing type means notifying on state changes. Just start a batch
|
|
||||||
// now.
|
|
||||||
nsIDocument* document = GetCurrentDoc();
|
|
||||||
MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
|
|
||||||
|
|
||||||
UpdateEditableState();
|
|
||||||
|
|
||||||
if (!aValue) {
|
if (!aValue) {
|
||||||
// We're now a text input. Note that we have to handle this manually,
|
// We're now a text input. Note that we have to handle this manually,
|
||||||
// since removing an attribute (which is what happened, since aValue is
|
// since removing an attribute (which is what happened, since aValue is
|
||||||
|
@ -492,41 +488,53 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aNotify && document) {
|
|
||||||
// Changing type affects the applicability of some states. Just notify
|
// Changing type affects the applicability of some states. Just notify
|
||||||
// on them all now, just in case. Note that we can't rely on the
|
// on them all now, just in case. Note that we can't rely on the
|
||||||
// notifications LoadImage or CancelImageRequests might have sent,
|
// notifications LoadImage or CancelImageRequests might have sent, because
|
||||||
// because those didn't include all the possibly-changed states in the
|
// those didn't include all the possibly-changed states in the mask. We
|
||||||
// mask. We have to do this here because we just updated mType, so the
|
// have to do this here because we just updated mType, so the code in
|
||||||
// code in nsGenericElement::SetAttrAndNotify didn't see the new
|
// nsGenericElement::SetAttrAndNotify didn't see the new states.
|
||||||
// states.
|
states |= NS_EVENT_STATE_CHECKED |
|
||||||
document->ContentStatesChanged(this, nsnull,
|
|
||||||
NS_EVENT_STATE_CHECKED |
|
|
||||||
NS_EVENT_STATE_DEFAULT |
|
NS_EVENT_STATE_DEFAULT |
|
||||||
NS_EVENT_STATE_BROKEN |
|
NS_EVENT_STATE_BROKEN |
|
||||||
NS_EVENT_STATE_USERDISABLED |
|
NS_EVENT_STATE_USERDISABLED |
|
||||||
NS_EVENT_STATE_SUPPRESSED |
|
NS_EVENT_STATE_SUPPRESSED |
|
||||||
NS_EVENT_STATE_LOADING |
|
NS_EVENT_STATE_LOADING |
|
||||||
NS_EVENT_STATE_INDETERMINATE |
|
|
||||||
NS_EVENT_STATE_MOZ_READONLY |
|
NS_EVENT_STATE_MOZ_READONLY |
|
||||||
NS_EVENT_STATE_MOZ_READWRITE |
|
NS_EVENT_STATE_MOZ_READWRITE |
|
||||||
NS_EVENT_STATE_REQUIRED |
|
NS_EVENT_STATE_REQUIRED |
|
||||||
NS_EVENT_STATE_OPTIONAL);
|
NS_EVENT_STATE_OPTIONAL |
|
||||||
}
|
NS_EVENT_STATE_VALID |
|
||||||
|
NS_EVENT_STATE_INVALID |
|
||||||
|
NS_EVENT_STATE_INDETERMINATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If readonly is changed for single line text controls, we need to handle
|
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
||||||
// :read-only / :read-write
|
aName == nsGkAtoms::readonly) {
|
||||||
if (aNotify && aName == nsGkAtoms::readonly &&
|
UpdateValueMissingValidityState();
|
||||||
IsSingleLineTextControl(PR_FALSE)) {
|
states |= NS_EVENT_STATE_REQUIRED | NS_EVENT_STATE_OPTIONAL |
|
||||||
|
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
|
||||||
|
} else if (aName == nsGkAtoms::maxlength) {
|
||||||
|
UpdateTooLongValidityState();
|
||||||
|
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
|
||||||
|
} else if (aName == nsGkAtoms::pattern) {
|
||||||
|
UpdatePatternMismatchValidityState();
|
||||||
|
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aNotify) {
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||||
|
|
||||||
|
if (aName == nsGkAtoms::type) {
|
||||||
UpdateEditableState();
|
UpdateEditableState();
|
||||||
|
} else if (IsSingleLineTextControl(PR_FALSE) && aName == nsGkAtoms::readonly) {
|
||||||
|
UpdateEditableState();
|
||||||
|
states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
nsIDocument* document = GetCurrentDoc();
|
if (doc && states) {
|
||||||
if (document) {
|
doc->ContentStatesChanged(this, nsnull, states);
|
||||||
mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
|
|
||||||
document->ContentStatesChanged(this, nsnull,
|
|
||||||
NS_EVENT_STATE_MOZ_READONLY |
|
|
||||||
NS_EVENT_STATE_MOZ_READWRITE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -894,6 +902,7 @@ nsHTMLInputElement::SetFileNames(const nsTArray<nsString>& aFileNames)
|
||||||
UpdateFileList();
|
UpdateFileList();
|
||||||
|
|
||||||
SetValueChanged(PR_TRUE);
|
SetValueChanged(PR_TRUE);
|
||||||
|
UpdateAllValidityStates(PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1086,7 +1095,6 @@ nsHTMLInputElement::DoSetChecked(PRBool aChecked, PRBool aNotify,
|
||||||
if (aChecked) {
|
if (aChecked) {
|
||||||
rv = RadioSetChecked(aNotify);
|
rv = RadioSetChecked(aNotify);
|
||||||
} else {
|
} else {
|
||||||
rv = SetCheckedInternal(PR_FALSE, aNotify);
|
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
||||||
if (container) {
|
if (container) {
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
|
@ -1094,9 +1102,13 @@ nsHTMLInputElement::DoSetChecked(PRBool aChecked, PRBool aNotify,
|
||||||
container->SetCurrentRadioButton(name, nsnull);
|
container->SetCurrentRadioButton(name, nsnull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// SetCheckedInternal is going to ask all radios to update their
|
||||||
|
// validity state. We have to be sure the radio group container knows
|
||||||
|
// the currently selected radio.
|
||||||
|
SetCheckedInternal(PR_FALSE, aNotify);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rv = SetCheckedInternal(aChecked, aNotify);
|
SetCheckedInternal(aChecked, aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1118,27 +1130,26 @@ nsHTMLInputElement::RadioSetChecked(PRBool aNotify)
|
||||||
if (currentlySelected) {
|
if (currentlySelected) {
|
||||||
// Pass PR_TRUE for the aNotify parameter since the currently selected
|
// Pass PR_TRUE for the aNotify parameter since the currently selected
|
||||||
// button is already in the document.
|
// button is already in the document.
|
||||||
rv = static_cast<nsHTMLInputElement*>
|
static_cast<nsHTMLInputElement*>
|
||||||
(static_cast<nsIDOMHTMLInputElement*>(currentlySelected))->SetCheckedInternal(PR_FALSE, PR_TRUE);
|
(static_cast<nsIDOMHTMLInputElement*>(currentlySelected))->SetCheckedInternal(PR_FALSE, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Actually select this one
|
|
||||||
//
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
rv = SetCheckedInternal(PR_TRUE, aNotify);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Let the group know that we are now the One True Radio Button
|
// Let the group know that we are now the One True Radio Button
|
||||||
//
|
//
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
||||||
nsAutoString name;
|
nsAutoString name;
|
||||||
if (container && GetNameIfExists(name)) {
|
if (container && GetNameIfExists(name)) {
|
||||||
rv = container->SetCurrentRadioButton(name, this);
|
rv = container->SetCurrentRadioButton(name, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCheckedInternal is going to ask all radios to update their
|
||||||
|
// validity state. We have to be sure the radio group container knows
|
||||||
|
// the currently selected radio.
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
SetCheckedInternal(PR_TRUE, aNotify);
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1211,7 +1222,7 @@ nsHTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
void
|
||||||
nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
|
nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1239,7 +1250,16 @@ nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
if (mType == NS_FORM_INPUT_CHECKBOX) {
|
||||||
|
UpdateAllValidityStates(aNotify);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mType == NS_FORM_INPUT_RADIO) {
|
||||||
|
// OnValueChanged is going to be called for all radios in the radio group.
|
||||||
|
nsCOMPtr<nsIRadioVisitor> visitor =
|
||||||
|
NS_GetRadioUpdateValueMissingVisitor(aNotify);
|
||||||
|
VisitGroup(visitor, aNotify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2022,6 +2042,10 @@ nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
AddedToRadioGroup();
|
AddedToRadioGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An element can't suffer from value missing if it is not in a document.
|
||||||
|
// We have to check if we suffer from that as we are now in a document.
|
||||||
|
UpdateValueMissingValidityState();
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2034,10 +2058,14 @@ nsHTMLInputElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||||
// of the case where we're removing from the document and we don't
|
// of the case where we're removing from the document and we don't
|
||||||
// have a form
|
// have a form
|
||||||
if (!mForm && mType == NS_FORM_INPUT_RADIO) {
|
if (!mForm && mType == NS_FORM_INPUT_RADIO) {
|
||||||
WillRemoveFromRadioGroup();
|
WillRemoveFromRadioGroup(PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
|
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
|
||||||
|
|
||||||
|
// GetCurrentDoc is returning nsnull so we can update the value
|
||||||
|
// missing validity state to reflect we are no longer into a doc.
|
||||||
|
UpdateValueMissingValidityState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2068,6 +2096,9 @@ nsHTMLInputElement::HandleTypeChange(PRUint8 aNewType)
|
||||||
// SetValueInternal is going to sanitize the value.
|
// SetValueInternal is going to sanitize the value.
|
||||||
SetValueInternal(value, PR_FALSE, PR_FALSE);
|
SetValueInternal(value, PR_FALSE, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not notify, it will be done after if needed.
|
||||||
|
UpdateAllValidityStates(PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2760,6 +2791,10 @@ nsHTMLInputElement::IntrinsicState() const
|
||||||
state |= NS_EVENT_STATE_OPTIONAL;
|
state |= NS_EVENT_STATE_OPTIONAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsCandidateForConstraintValidation(this)) {
|
||||||
|
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2875,7 +2910,7 @@ nsHTMLInputElement::AddedToRadioGroup(PRBool aNotify)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHTMLInputElement::WillRemoveFromRadioGroup()
|
nsHTMLInputElement::WillRemoveFromRadioGroup(PRBool aNotify)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// If the input element is not in a form and
|
// If the input element is not in a form and
|
||||||
|
@ -2904,6 +2939,12 @@ nsHTMLInputElement::WillRemoveFromRadioGroup()
|
||||||
if (container) {
|
if (container) {
|
||||||
container->SetCurrentRadioButton(name, nsnull);
|
container->SetCurrentRadioButton(name, nsnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removing a checked radio from the group can change the validity state.
|
||||||
|
// Let's ask other radio to update their value missing validity state.
|
||||||
|
nsCOMPtr<nsIRadioVisitor> visitor =
|
||||||
|
NS_GetRadioUpdateValueMissingVisitor(aNotify);
|
||||||
|
VisitGroup(visitor, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -3138,6 +3179,20 @@ nsHTMLInputElement::DoesPatternApply() const
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLInputElement::SetCustomValidity(const nsAString& aError)
|
||||||
|
{
|
||||||
|
nsresult rv = nsConstraintValidation::SetCustomValidity(aError);
|
||||||
|
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
|
||||||
|
NS_EVENT_STATE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLInputElement::IsTooLong()
|
nsHTMLInputElement::IsTooLong()
|
||||||
{
|
{
|
||||||
|
@ -3151,7 +3206,7 @@ nsHTMLInputElement::IsTooLong()
|
||||||
GetMaxLength(&maxLength);
|
GetMaxLength(&maxLength);
|
||||||
GetTextLength(&textLength);
|
GetTextLength(&textLength);
|
||||||
|
|
||||||
return (maxLength >= 0) && (textLength > maxLength);
|
return maxLength >= 0 && textLength > maxLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -3168,52 +3223,49 @@ nsHTMLInputElement::IsValueMissing()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString value;
|
nsAutoString value;
|
||||||
nsresult rv = GetValue(value);
|
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
|
||||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
|
||||||
|
|
||||||
return value.IsEmpty();
|
return value.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType == NS_FORM_INPUT_CHECKBOX) {
|
switch (mType)
|
||||||
|
{
|
||||||
|
case NS_FORM_INPUT_CHECKBOX:
|
||||||
return !GetChecked();
|
return !GetChecked();
|
||||||
}
|
case NS_FORM_INPUT_RADIO:
|
||||||
|
{
|
||||||
if (mType == NS_FORM_INPUT_RADIO) {
|
|
||||||
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
|
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
|
||||||
return !selected;
|
return !selected;
|
||||||
}
|
}
|
||||||
|
case NS_FORM_INPUT_FILE:
|
||||||
if (mType == NS_FORM_INPUT_FILE) {
|
{
|
||||||
nsCOMArray<nsIFile> files;
|
nsCOMArray<nsIFile> files;
|
||||||
GetFileArray(files);
|
GetFileArray(files);
|
||||||
return !files.Count();
|
return !files.Count();
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLInputElement::HasTypeMismatch()
|
nsHTMLInputElement::HasTypeMismatch()
|
||||||
{
|
{
|
||||||
|
if (mType != NS_FORM_INPUT_EMAIL && mType != NS_FORM_INPUT_URL) {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString value;
|
||||||
|
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
|
||||||
|
|
||||||
|
if (value.IsEmpty()) {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (mType == NS_FORM_INPUT_EMAIL) {
|
if (mType == NS_FORM_INPUT_EMAIL) {
|
||||||
nsAutoString value;
|
return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)
|
||||||
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
|
? !IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
|
||||||
|
|
||||||
if (value.IsEmpty()) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
|
|
||||||
!IsValidEmailAddressList(value) :
|
|
||||||
!IsValidEmailAddress(value);
|
|
||||||
} else if (mType == NS_FORM_INPUT_URL) {
|
} else if (mType == NS_FORM_INPUT_URL) {
|
||||||
nsAutoString value;
|
|
||||||
NS_ENSURE_SUCCESS(GetValue(value), PR_FALSE);
|
|
||||||
|
|
||||||
if (value.IsEmpty()) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:
|
* TODO:
|
||||||
* The URL is not checked as the HTML5 specifications want it to be because
|
* The URL is not checked as the HTML5 specifications want it to be because
|
||||||
|
@ -3239,8 +3291,8 @@ PRBool
|
||||||
nsHTMLInputElement::HasPatternMismatch()
|
nsHTMLInputElement::HasPatternMismatch()
|
||||||
{
|
{
|
||||||
nsAutoString pattern;
|
nsAutoString pattern;
|
||||||
if (!DoesPatternApply() || !GetAttr(kNameSpaceID_None, nsGkAtoms::pattern,
|
if (!DoesPatternApply() ||
|
||||||
pattern)) {
|
!GetAttr(kNameSpaceID_None, nsGkAtoms::pattern, pattern)) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3259,8 +3311,49 @@ nsHTMLInputElement::HasPatternMismatch()
|
||||||
return !IsPatternMatching(value, pattern, doc);
|
return !IsPatternMatching(value, pattern, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLInputElement::UpdateTooLongValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLInputElement::UpdateValueMissingValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLInputElement::UpdateTypeMismatchValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_TYPE_MISMATCH, HasTypeMismatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLInputElement::UpdatePatternMismatchValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, HasPatternMismatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLInputElement::UpdateAllValidityStates(PRBool aNotify)
|
||||||
|
{
|
||||||
|
UpdateTooLongValidityState();
|
||||||
|
UpdateValueMissingValidityState();
|
||||||
|
UpdateTypeMismatchValidityState();
|
||||||
|
UpdatePatternMismatchValidityState();
|
||||||
|
|
||||||
|
if (aNotify) {
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull,
|
||||||
|
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLInputElement::IsBarredFromConstraintValidation()
|
nsHTMLInputElement::IsBarredFromConstraintValidation() const
|
||||||
{
|
{
|
||||||
return mType == NS_FORM_INPUT_HIDDEN ||
|
return mType == NS_FORM_INPUT_HIDDEN ||
|
||||||
mType == NS_FORM_INPUT_BUTTON ||
|
mType == NS_FORM_INPUT_BUTTON ||
|
||||||
|
@ -3270,13 +3363,13 @@ nsHTMLInputElement::IsBarredFromConstraintValidation()
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
ValidationMessageType aType)
|
ValidityStateType aType)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
switch (aType)
|
switch (aType)
|
||||||
{
|
{
|
||||||
case VALIDATION_MESSAGE_TOO_LONG:
|
case VALIDITY_STATE_TOO_LONG:
|
||||||
{
|
{
|
||||||
nsXPIDLString message;
|
nsXPIDLString message;
|
||||||
PRInt32 maxLength = -1;
|
PRInt32 maxLength = -1;
|
||||||
|
@ -3297,7 +3390,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
aValidationMessage = message;
|
aValidationMessage = message;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VALIDATION_MESSAGE_VALUE_MISSING:
|
case VALIDITY_STATE_VALUE_MISSING:
|
||||||
{
|
{
|
||||||
nsXPIDLString message;
|
nsXPIDLString message;
|
||||||
nsCAutoString key;
|
nsCAutoString key;
|
||||||
|
@ -3320,7 +3413,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
aValidationMessage = message;
|
aValidationMessage = message;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VALIDATION_MESSAGE_TYPE_MISMATCH:
|
case VALIDITY_STATE_TYPE_MISMATCH:
|
||||||
{
|
{
|
||||||
nsXPIDLString message;
|
nsXPIDLString message;
|
||||||
nsCAutoString key;
|
nsCAutoString key;
|
||||||
|
@ -3336,7 +3429,7 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
aValidationMessage = message;
|
aValidationMessage = message;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VALIDATION_MESSAGE_PATTERN_MISMATCH:
|
case VALIDITY_STATE_PATTERN_MISMATCH:
|
||||||
{
|
{
|
||||||
nsXPIDLString message;
|
nsXPIDLString message;
|
||||||
nsAutoString title;
|
nsAutoString title;
|
||||||
|
@ -3557,6 +3650,38 @@ protected:
|
||||||
nsIFormControl* mExcludeElement;
|
nsIFormControl* mExcludeElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class nsRadioUpdateValueMissingVisitor : public nsRadioVisitor {
|
||||||
|
public:
|
||||||
|
nsRadioUpdateValueMissingVisitor(PRBool aNotify)
|
||||||
|
: nsRadioVisitor()
|
||||||
|
, mNotify(aNotify)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual ~nsRadioUpdateValueMissingVisitor() { };
|
||||||
|
|
||||||
|
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The simplest way to update the value missing validity state is to do a
|
||||||
|
* global update of the validity state by simulationg a value change.
|
||||||
|
* OnValueChanged() is declared into nsITextControlElement. That may sound
|
||||||
|
* to be a weird way to update the validity states for radio controls but
|
||||||
|
* they are also implementing nsITextControlElement interface.
|
||||||
|
*
|
||||||
|
* When OnValueChanged() is called on a radio control, it will check if any
|
||||||
|
* radio in the group is checked. If none, the required radio will be
|
||||||
|
* suffering from being missing.
|
||||||
|
*/
|
||||||
|
nsCOMPtr<nsITextControlElement> textCtl(do_QueryInterface(aRadio));
|
||||||
|
NS_ASSERTION(textCtl, "Visit() passed a null or non-radio pointer");
|
||||||
|
textCtl->OnValueChanged(mNotify);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PRBool mNotify;
|
||||||
|
};
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
NS_GetRadioSetCheckedChangedVisitor(PRBool aCheckedChanged,
|
NS_GetRadioSetCheckedChangedVisitor(PRBool aCheckedChanged,
|
||||||
nsIRadioVisitor** aVisitor)
|
nsIRadioVisitor** aVisitor)
|
||||||
|
@ -3627,6 +3752,22 @@ NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method is a factory: it lets callers to create an instance of
|
||||||
|
* nsRadioUpdateValueMissing without the class declaration and definition.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* Do we really need factories for radio visitors? Or at least, we should move
|
||||||
|
* that somewhere else because it feels like it's here only because the radio
|
||||||
|
* visitor classes are defined after most of nsHTMLInputElement code.
|
||||||
|
* See bug 586298
|
||||||
|
*/
|
||||||
|
nsIRadioVisitor*
|
||||||
|
NS_GetRadioUpdateValueMissingVisitor(PRBool aNotify)
|
||||||
|
{
|
||||||
|
return new nsRadioUpdateValueMissingVisitor(aNotify);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(PRBool)
|
NS_IMETHODIMP_(PRBool)
|
||||||
nsHTMLInputElement::IsSingleLineTextControl() const
|
nsHTMLInputElement::IsSingleLineTextControl() const
|
||||||
{
|
{
|
||||||
|
@ -3725,3 +3866,10 @@ nsHTMLInputElement::InitializeKeyboardEventListeners()
|
||||||
state->InitializeKeyboardEventListeners();
|
state->InitializeKeyboardEventListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(void)
|
||||||
|
nsHTMLInputElement::OnValueChanged(PRBool aNotify)
|
||||||
|
{
|
||||||
|
UpdateAllValidityStates(aNotify);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,7 @@ public:
|
||||||
NS_IMETHOD_(void) UpdatePlaceholderText(PRBool aNotify);
|
NS_IMETHOD_(void) UpdatePlaceholderText(PRBool aNotify);
|
||||||
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify);
|
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify);
|
||||||
NS_IMETHOD_(void) InitializeKeyboardEventListeners();
|
NS_IMETHOD_(void) InitializeKeyboardEventListeners();
|
||||||
|
NS_IMETHOD_(void) OnValueChanged(PRBool aNotify);
|
||||||
|
|
||||||
// nsIFileControlElement
|
// nsIFileControlElement
|
||||||
virtual void GetDisplayFileName(nsAString& aFileName);
|
virtual void GetDisplayFileName(nsAString& aFileName);
|
||||||
|
@ -180,7 +181,7 @@ public:
|
||||||
void SetCheckedChangedInternal(PRBool aCheckedChanged);
|
void SetCheckedChangedInternal(PRBool aCheckedChanged);
|
||||||
PRBool GetCheckedChanged();
|
PRBool GetCheckedChanged();
|
||||||
void AddedToRadioGroup(PRBool aNotify = PR_TRUE);
|
void AddedToRadioGroup(PRBool aNotify = PR_TRUE);
|
||||||
void WillRemoveFromRadioGroup();
|
void WillRemoveFromRadioGroup(PRBool aNotify);
|
||||||
/**
|
/**
|
||||||
* Get the radio group container for this button (form or document)
|
* Get the radio group container for this button (form or document)
|
||||||
* @return the radio group container (or null if no form or document)
|
* @return the radio group container (or null if no form or document)
|
||||||
|
@ -215,9 +216,14 @@ public:
|
||||||
PRBool IsValueMissing();
|
PRBool IsValueMissing();
|
||||||
PRBool HasTypeMismatch();
|
PRBool HasTypeMismatch();
|
||||||
PRBool HasPatternMismatch();
|
PRBool HasPatternMismatch();
|
||||||
PRBool IsBarredFromConstraintValidation();
|
void UpdateTooLongValidityState();
|
||||||
|
void UpdateValueMissingValidityState();
|
||||||
|
void UpdateTypeMismatchValidityState();
|
||||||
|
void UpdatePatternMismatchValidityState();
|
||||||
|
void UpdateAllValidityStates(PRBool aNotify);
|
||||||
|
PRBool IsBarredFromConstraintValidation() const;
|
||||||
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
||||||
ValidationMessageType aType);
|
ValidityStateType aType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
|
// Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
|
||||||
|
@ -373,7 +379,7 @@ protected:
|
||||||
* Actually set checked and notify the frame of the change.
|
* Actually set checked and notify the frame of the change.
|
||||||
* @param aValue the value of checked to set
|
* @param aValue the value of checked to set
|
||||||
*/
|
*/
|
||||||
nsresult SetCheckedInternal(PRBool aValue, PRBool aNotify);
|
void SetCheckedInternal(PRBool aValue, PRBool aNotify);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syntax sugar to make it easier to check for checked
|
* Syntax sugar to make it easier to check for checked
|
||||||
|
|
|
@ -195,7 +195,21 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSelectElement)
|
||||||
NS_IMPL_ELEMENT_CLONE(nsHTMLSelectElement)
|
NS_IMPL_ELEMENT_CLONE(nsHTMLSelectElement)
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLSelectElement)
|
NS_IMPL_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLSelectElement)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLSelectElement::SetCustomValidity(const nsAString& aError)
|
||||||
|
{
|
||||||
|
nsresult rv = nsConstraintValidation::SetCustomValidity(aError);
|
||||||
|
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
|
||||||
|
NS_EVENT_STATE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
||||||
|
@ -1455,7 +1469,13 @@ nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||||
PRInt32
|
PRInt32
|
||||||
nsHTMLSelectElement::IntrinsicState() const
|
nsHTMLSelectElement::IntrinsicState() const
|
||||||
{
|
{
|
||||||
return NS_EVENT_STATE_OPTIONAL | nsGenericHTMLFormElement::IntrinsicState();
|
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
|
||||||
|
|
||||||
|
if (IsCandidateForConstraintValidation(this)) {
|
||||||
|
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state | NS_EVENT_STATE_OPTIONAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIFormControl
|
// nsIFormControl
|
||||||
|
|
|
@ -155,6 +155,7 @@ public:
|
||||||
NS_IMETHOD_(void) UpdatePlaceholderText(PRBool aNotify);
|
NS_IMETHOD_(void) UpdatePlaceholderText(PRBool aNotify);
|
||||||
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify);
|
NS_IMETHOD_(void) SetPlaceholderClass(PRBool aVisible, PRBool aNotify);
|
||||||
NS_IMETHOD_(void) InitializeKeyboardEventListeners();
|
NS_IMETHOD_(void) InitializeKeyboardEventListeners();
|
||||||
|
NS_IMETHOD_(void) OnValueChanged(PRBool aNotify);
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||||
|
@ -202,10 +203,12 @@ public:
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
PRBool IsTooLong();
|
PRBool IsTooLong();
|
||||||
PRBool IsValueMissing();
|
PRBool IsValueMissing() const;
|
||||||
PRBool IsBarredFromConstraintValidation();
|
void UpdateTooLongValidityState();
|
||||||
|
void UpdateValueMissingValidityState();
|
||||||
|
PRBool IsBarredFromConstraintValidation() const;
|
||||||
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
||||||
ValidationMessageType aType);
|
ValidityStateType aType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using nsGenericHTMLFormElement::IsSingleLineTextControl; // get rid of the compiler warning
|
using nsGenericHTMLFormElement::IsSingleLineTextControl; // get rid of the compiler warning
|
||||||
|
@ -233,7 +236,7 @@ protected:
|
||||||
* value. If this is true, linebreaks will not be inserted even if
|
* value. If this is true, linebreaks will not be inserted even if
|
||||||
* wrap=hard.
|
* wrap=hard.
|
||||||
*/
|
*/
|
||||||
void GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap);
|
void GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap) const;
|
||||||
|
|
||||||
nsresult SetValueInternal(const nsAString& aValue,
|
nsresult SetValueInternal(const nsAString& aValue,
|
||||||
PRBool aUserInput);
|
PRBool aUserInput);
|
||||||
|
@ -314,7 +317,7 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTextAreaElement)
|
||||||
NS_IMPL_ELEMENT_CLONE(nsHTMLTextAreaElement)
|
NS_IMPL_ELEMENT_CLONE(nsHTMLTextAreaElement)
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
NS_IMPL_NSCONSTRAINTVALIDATION(nsHTMLTextAreaElement)
|
NS_IMPL_NSCONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(nsHTMLTextAreaElement)
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -439,7 +442,7 @@ nsHTMLTextAreaElement::GetValue(nsAString& aValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHTMLTextAreaElement::GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap)
|
nsHTMLTextAreaElement::GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap) const
|
||||||
{
|
{
|
||||||
mState->GetValue(aValue, aIgnoreWrap);
|
mState->GetValue(aValue, aIgnoreWrap);
|
||||||
}
|
}
|
||||||
|
@ -841,9 +844,7 @@ nsresult
|
||||||
nsHTMLTextAreaElement::Reset()
|
nsHTMLTextAreaElement::Reset()
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
// If the frame is there, we have to set the value so that it will show up.
|
|
||||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
|
|
||||||
if (formControlFrame) {
|
|
||||||
// To get the initial spellchecking, reset value to
|
// To get the initial spellchecking, reset value to
|
||||||
// empty string before setting the default value.
|
// empty string before setting the default value.
|
||||||
SetValue(EmptyString());
|
SetValue(EmptyString());
|
||||||
|
@ -851,7 +852,7 @@ nsHTMLTextAreaElement::Reset()
|
||||||
GetDefaultValue(resetVal);
|
GetDefaultValue(resetVal);
|
||||||
rv = SetValue(resetVal);
|
rv = SetValue(resetVal);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
|
||||||
SetValueChanged(PR_FALSE);
|
SetValueChanged(PR_FALSE);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -965,6 +966,10 @@ nsHTMLTextAreaElement::IntrinsicState() const
|
||||||
state |= NS_EVENT_STATE_OPTIONAL;
|
state |= NS_EVENT_STATE_OPTIONAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsCandidateForConstraintValidation(this)) {
|
||||||
|
state |= IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,18 +1038,33 @@ nsresult
|
||||||
nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAString* aValue, PRBool aNotify)
|
const nsAString* aValue, PRBool aNotify)
|
||||||
{
|
{
|
||||||
if (aNotify && aNameSpaceID == kNameSpaceID_None &&
|
PRInt32 states = 0;
|
||||||
aName == nsGkAtoms::readonly) {
|
|
||||||
UpdateEditableState();
|
|
||||||
|
|
||||||
nsIDocument* document = GetCurrentDoc();
|
if (aNameSpaceID == kNameSpaceID_None) {
|
||||||
if (document) {
|
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
||||||
mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
|
aName == nsGkAtoms::readonly) {
|
||||||
document->ContentStatesChanged(this, nsnull,
|
UpdateValueMissingValidityState();
|
||||||
NS_EVENT_STATE_MOZ_READONLY |
|
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
|
||||||
NS_EVENT_STATE_MOZ_READWRITE);
|
} else if (aName == nsGkAtoms::maxlength) {
|
||||||
|
UpdateTooLongValidityState();
|
||||||
|
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aNotify) {
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||||
|
|
||||||
|
if (aName == nsGkAtoms::readonly) {
|
||||||
|
UpdateEditableState();
|
||||||
|
states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc && states) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull, states);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
|
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
|
||||||
aNotify);
|
aNotify);
|
||||||
}
|
}
|
||||||
|
@ -1072,6 +1092,20 @@ nsHTMLTextAreaElement::IsMutable() const
|
||||||
|
|
||||||
// nsConstraintValidation
|
// nsConstraintValidation
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLTextAreaElement::SetCustomValidity(const nsAString& aError)
|
||||||
|
{
|
||||||
|
nsresult rv = nsConstraintValidation::SetCustomValidity(aError);
|
||||||
|
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_INVALID |
|
||||||
|
NS_EVENT_STATE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLTextAreaElement::IsTooLong()
|
nsHTMLTextAreaElement::IsTooLong()
|
||||||
{
|
{
|
||||||
|
@ -1085,38 +1119,49 @@ nsHTMLTextAreaElement::IsTooLong()
|
||||||
GetMaxLength(&maxLength);
|
GetMaxLength(&maxLength);
|
||||||
GetTextLength(&textLength);
|
GetTextLength(&textLength);
|
||||||
|
|
||||||
return (maxLength >= 0) && (textLength > maxLength);
|
return maxLength >= 0 && textLength > maxLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLTextAreaElement::IsValueMissing()
|
nsHTMLTextAreaElement::IsValueMissing() const
|
||||||
{
|
{
|
||||||
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
|
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString value;
|
nsAutoString value;
|
||||||
nsresult rv = GetValue(value);
|
GetValueInternal(value, PR_TRUE);
|
||||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
|
||||||
|
|
||||||
return value.IsEmpty();
|
return value.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLTextAreaElement::UpdateTooLongValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLTextAreaElement::UpdateValueMissingValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLTextAreaElement::IsBarredFromConstraintValidation()
|
nsHTMLTextAreaElement::IsBarredFromConstraintValidation() const
|
||||||
{
|
{
|
||||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
|
return HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
|
nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
ValidationMessageType aType)
|
ValidityStateType aType)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
switch (aType)
|
switch (aType)
|
||||||
{
|
{
|
||||||
case VALIDATION_MESSAGE_TOO_LONG:
|
case VALIDITY_STATE_TOO_LONG:
|
||||||
{
|
{
|
||||||
nsXPIDLString message;
|
nsXPIDLString message;
|
||||||
PRInt32 maxLength = -1;
|
PRInt32 maxLength = -1;
|
||||||
|
@ -1137,7 +1182,7 @@ nsHTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||||
aValidationMessage = message;
|
aValidationMessage = message;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VALIDATION_MESSAGE_VALUE_MISSING:
|
case VALIDITY_STATE_VALUE_MISSING:
|
||||||
{
|
{
|
||||||
nsXPIDLString message;
|
nsXPIDLString message;
|
||||||
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||||
|
@ -1251,3 +1296,20 @@ nsHTMLTextAreaElement::InitializeKeyboardEventListeners()
|
||||||
{
|
{
|
||||||
mState->InitializeKeyboardEventListeners();
|
mState->InitializeKeyboardEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(void)
|
||||||
|
nsHTMLTextAreaElement::OnValueChanged(PRBool aNotify)
|
||||||
|
{
|
||||||
|
// Update the validity state
|
||||||
|
UpdateTooLongValidityState();
|
||||||
|
UpdateValueMissingValidityState();
|
||||||
|
|
||||||
|
if (aNotify) {
|
||||||
|
nsIDocument* doc = GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_VALID |
|
||||||
|
NS_EVENT_STATE_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -842,6 +842,8 @@ nsTextInputListener::EditAction()
|
||||||
// Fire input event
|
// Fire input event
|
||||||
mFrame->FireOnInput();
|
mFrame->FireOnInput();
|
||||||
|
|
||||||
|
mTxtCtrlElement->OnValueChanged(PR_TRUE);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1782,6 +1784,8 @@ nsTextEditorState::SetValue(const nsAString& aValue, PRBool aUserInput)
|
||||||
// If we've reached the point where the root node has been created, we
|
// If we've reached the point where the root node has been created, we
|
||||||
// can assume that it's safe to notify.
|
// can assume that it's safe to notify.
|
||||||
ValueWasChanged(!!mRootNode);
|
ValueWasChanged(!!mRootNode);
|
||||||
|
|
||||||
|
mTextCtrlElement->OnValueChanged(!!mRootNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -202,6 +202,7 @@ _TEST_FILES = \
|
||||||
test_bug566160.html \
|
test_bug566160.html \
|
||||||
test_bug582412-1.html \
|
test_bug582412-1.html \
|
||||||
test_bug582412-2.html \
|
test_bug582412-2.html \
|
||||||
|
test_bug558788.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_TEST_FILES)
|
libs:: $(_TEST_FILES)
|
||||||
|
|
|
@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=344615
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input { background-color: rgb(0,0,0) !important; }
|
||||||
|
input:valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
input:invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=344615">Mozilla Bug 344615</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=344615">Mozilla Bug 344615</a>
|
||||||
|
@ -40,6 +45,8 @@ function checkValidURL(element)
|
||||||
ok(!gInvalid, "The invalid event should not have been thrown");
|
ok(!gInvalid, "The invalid event should not have been thrown");
|
||||||
is(element.validationMessage, '',
|
is(element.validationMessage, '',
|
||||||
"Validation message should be the empty string");
|
"Validation message should be the empty string");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInvalidURL(element)
|
function checkInvalidURL(element)
|
||||||
|
@ -52,6 +59,8 @@ function checkInvalidURL(element)
|
||||||
ok(gInvalid, "The invalid event should have been thrown");
|
ok(gInvalid, "The invalid event should have been thrown");
|
||||||
is(element.validationMessage, "The entered URL is not valid.",
|
is(element.validationMessage, "The entered URL is not valid.",
|
||||||
"Validation message should be related to invalid URL");
|
"Validation message should be related to invalid URL");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = document.getElementById('i');
|
var url = document.getElementById('i');
|
||||||
|
|
|
@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345512
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input { background-color: rgb(0,0,0) !important; }
|
||||||
|
input:valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
input:invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345512">Mozilla Bug 345512</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345512">Mozilla Bug 345512</a>
|
||||||
|
@ -56,7 +61,7 @@ function checkPatternAttribute(element)
|
||||||
"pattern content attribute value should be 'bar'");
|
"pattern content attribute value should be 'bar'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function completeValidityCheck(element, alwaysValid)
|
function completeValidityCheck(element, alwaysValid, isBarred)
|
||||||
{
|
{
|
||||||
if (element.type == 'file') {
|
if (element.type == 'file') {
|
||||||
// Need privileges to set a filename with .value.
|
// Need privileges to set a filename with .value.
|
||||||
|
@ -75,7 +80,7 @@ function completeValidityCheck(element, alwaysValid)
|
||||||
element.value = "foo";
|
element.value = "foo";
|
||||||
}
|
}
|
||||||
|
|
||||||
checkValidPattern(element, true);
|
checkValidPattern(element, true, isBarred);
|
||||||
|
|
||||||
// Check when pattern does not match.
|
// Check when pattern does not match.
|
||||||
|
|
||||||
|
@ -93,11 +98,11 @@ function completeValidityCheck(element, alwaysValid)
|
||||||
if (!alwaysValid) {
|
if (!alwaysValid) {
|
||||||
checkInvalidPattern(element, true);
|
checkInvalidPattern(element, true);
|
||||||
} else {
|
} else {
|
||||||
checkValidPattern(element, true);
|
checkValidPattern(element, true, isBarred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkValidPattern(element, completeCheck)
|
function checkValidPattern(element, completeCheck, isBarred)
|
||||||
{
|
{
|
||||||
if (completeCheck) {
|
if (completeCheck) {
|
||||||
gInvalid = false;
|
gInvalid = false;
|
||||||
|
@ -109,6 +114,11 @@ function checkValidPattern(element, completeCheck)
|
||||||
ok(!gInvalid, "Invalid event shouldn't have been thrown");
|
ok(!gInvalid, "Invalid event shouldn't have been thrown");
|
||||||
is(element.validationMessage, '',
|
is(element.validationMessage, '',
|
||||||
"Validation message should be the empty string");
|
"Validation message should be the empty string");
|
||||||
|
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
isBarred ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
|
||||||
|
"The pseudo-class is not correctly applied");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ok(!element.validity.patternMismatch,
|
ok(!element.validity.patternMismatch,
|
||||||
"Element should not suffer from pattern mismatch");
|
"Element should not suffer from pattern mismatch");
|
||||||
|
@ -132,6 +142,11 @@ function checkInvalidPattern(element, completeCheck)
|
||||||
ok(element.validity.patternMismatch,
|
ok(element.validity.patternMismatch,
|
||||||
"Element should suffer from pattern mismatch");
|
"Element should suffer from pattern mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkPatternValidity(element)
|
function checkPatternValidity(element)
|
||||||
|
@ -277,8 +292,8 @@ checkPatternAttribute(input);
|
||||||
// |validTypes| are the types which accept @pattern
|
// |validTypes| are the types which accept @pattern
|
||||||
// and |invalidTypes| are the ones which do not accept it.
|
// and |invalidTypes| are the ones which do not accept it.
|
||||||
var validTypes = Array('text', 'password', 'search', 'telephone', 'email', 'url');
|
var validTypes = Array('text', 'password', 'search', 'telephone', 'email', 'url');
|
||||||
var invalidTypes = Array('hidden', 'checkbox', 'radio', 'file', 'submit',
|
var barredTypes = Array('hidden', 'reset', 'button');
|
||||||
'image', 'reset', 'button');
|
var invalidTypes = Array('checkbox', 'radio', 'file', 'submit', 'image');
|
||||||
// TODO: 'datetime', 'date', 'month', 'week', 'time', 'datetime-local',
|
// TODO: 'datetime', 'date', 'month', 'week', 'time', 'datetime-local',
|
||||||
// 'number', 'range', ande 'color' do not accept the @pattern too but are
|
// 'number', 'range', ande 'color' do not accept the @pattern too but are
|
||||||
// not implemented yet.
|
// not implemented yet.
|
||||||
|
@ -289,6 +304,11 @@ for each (type in validTypes) {
|
||||||
checkPatternValidity(input);
|
checkPatternValidity(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for each (type in barredTypes) {
|
||||||
|
input.type = type;
|
||||||
|
completeValidityCheck(input, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
for each (type in invalidTypes) {
|
for each (type in invalidTypes) {
|
||||||
input.type = type;
|
input.type = type;
|
||||||
completeValidityCheck(input, true);
|
completeValidityCheck(input, true);
|
||||||
|
|
|
@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input, textarea, fieldset, button, select, keygen { background-color: rgb(0,0,0) !important; }
|
||||||
|
:valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
:invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
|
||||||
|
@ -80,6 +85,34 @@ function checkConstraintValidationAPIDefaultValues(element)
|
||||||
ok(element.checkValidity(), "The element should be valid by default");
|
ok(element.checkValidity(), "The element should be valid by default");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkDefaultPseudoClass()
|
||||||
|
{
|
||||||
|
// TODO: add check for <output>
|
||||||
|
is(window.getComputedStyle(document.getElementById('f'), null)
|
||||||
|
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
|
||||||
|
"Nor :valid and :invalid should apply");
|
||||||
|
|
||||||
|
todo_is(window.getComputedStyle(document.getElementById('k'), null)
|
||||||
|
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
|
||||||
|
"Nor :valid and :invalid should apply");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(document.getElementById('s'), null)
|
||||||
|
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||||
|
":valid pseudo-class should apply");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(document.getElementById('i'), null)
|
||||||
|
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||||
|
":valid pseudo-class should apply");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(document.getElementById('t'), null)
|
||||||
|
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||||
|
":valid pseudo-class should apply");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(document.getElementById('b'), null)
|
||||||
|
.getPropertyValue('background-color'), "rgb(0, 255, 0)",
|
||||||
|
":valid pseudo-class should apply");
|
||||||
|
}
|
||||||
|
|
||||||
function checkSpecificWillValidate()
|
function checkSpecificWillValidate()
|
||||||
{
|
{
|
||||||
// fieldset, keygen (TODO) and select elements
|
// fieldset, keygen (TODO) and select elements
|
||||||
|
@ -91,31 +124,51 @@ function checkSpecificWillValidate()
|
||||||
i = document.getElementById('i');
|
i = document.getElementById('i');
|
||||||
i.type = "hidden";
|
i.type = "hidden";
|
||||||
ok(!i.willValidate, "Hidden state input should be barred from constraint validation");
|
ok(!i.willValidate, "Hidden state input should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
i.type = "reset";
|
i.type = "reset";
|
||||||
ok(!i.willValidate, "Reset button state input should be barred from constraint validation");
|
ok(!i.willValidate, "Reset button state input should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
i.type = "button";
|
i.type = "button";
|
||||||
ok(!i.willValidate, "Button state input should be barred from constraint validation");
|
ok(!i.willValidate, "Button state input should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
i.type = "";
|
i.type = "";
|
||||||
i.readOnly = 'true';
|
i.readOnly = 'true';
|
||||||
ok(!i.willValidate, "Readonly input should be barred from constraint validation");
|
ok(!i.willValidate, "Readonly input should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
i.removeAttribute('readOnly');
|
i.removeAttribute('readOnly');
|
||||||
ok(i.willValidate, "Default input element should not be barred from constraint validation");
|
ok(i.willValidate, "Default input element should not be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
|
||||||
// button element
|
// button element
|
||||||
b = document.getElementById('b');
|
b = document.getElementById('b');
|
||||||
b.type = "reset";
|
b.type = "reset";
|
||||||
ok(!b.willValidate, "Reset state button should be barred from constraint validation");
|
ok(!b.willValidate, "Reset state button should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
b.type = "button";
|
b.type = "button";
|
||||||
ok(!b.willValidate, "Button state button should be barred from constraint validation");
|
ok(!b.willValidate, "Button state button should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
b.type = "";
|
b.type = "";
|
||||||
ok(b.willValidate, "Default button element should not be barred from constraint validation");
|
ok(b.willValidate, "Default button element should not be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
|
||||||
// textarea element
|
// textarea element
|
||||||
t = document.getElementById('t');
|
t = document.getElementById('t');
|
||||||
t.readOnly = true;
|
t.readOnly = true;
|
||||||
ok(!t.willValidate, "Readonly textarea should be barred from constraint validation");
|
ok(!t.willValidate, "Readonly textarea should be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
t.removeAttribute('readOnly');
|
t.removeAttribute('readOnly');
|
||||||
ok(t.willValidate, "Default textarea element should not be barred from constraint validation");
|
ok(t.willValidate, "Default textarea element should not be barred from constraint validation");
|
||||||
|
is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
|
||||||
// TODO: output elements are always barred from constraint validation.
|
// TODO: output elements are always barred from constraint validation.
|
||||||
// TODO: PROGRESS
|
// TODO: PROGRESS
|
||||||
|
@ -124,10 +177,14 @@ function checkSpecificWillValidate()
|
||||||
|
|
||||||
function checkCommonWillValidate(element)
|
function checkCommonWillValidate(element)
|
||||||
{
|
{
|
||||||
// Not checking the default value because it has been check previously
|
// Not checking the default value because it has been checked previously.
|
||||||
|
|
||||||
element.disabled = true;
|
element.disabled = true;
|
||||||
ok(!element.willValidate, "Disabled element should be barred from constraint validation");
|
ok(!element.willValidate, "Disabled element should be barred from constraint validation");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
|
||||||
|
|
||||||
element.removeAttribute('disabled');
|
element.removeAttribute('disabled');
|
||||||
|
|
||||||
// TODO: If an element has a datalist element ancestor, it is barred from constraint validation.
|
// TODO: If an element has a datalist element ancestor, it is barred from constraint validation.
|
||||||
|
@ -140,10 +197,16 @@ function checkCustomError(element)
|
||||||
ok(element.validity.customError, "The element should suffer from a custom error");
|
ok(element.validity.customError, "The element should suffer from a custom error");
|
||||||
ok(!element.validity.valid, "The element should not be valid with a custom error");
|
ok(!element.validity.valid, "The element should not be valid with a custom error");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-classs should apply");
|
||||||
|
|
||||||
element.setCustomValidity("");
|
element.setCustomValidity("");
|
||||||
is(element.validationMessage, "", "The element should not have a validation message when reseted");
|
is(element.validationMessage, "", "The element should not have a validation message when reseted");
|
||||||
ok(!element.validity.customError, "The element should not suffer anymore from a custom error");
|
ok(!element.validity.customError, "The element should not suffer anymore from a custom error");
|
||||||
ok(element.validity.valid, "The element should now be valid");
|
ok(element.validity.valid, "The element should now be valid");
|
||||||
|
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkCheckValidity(element)
|
function checkCheckValidity(element)
|
||||||
|
@ -206,6 +269,8 @@ checkConstraintValidationAPIDefaultValues(document.getElementById('s'));
|
||||||
checkConstraintValidationAPIDefaultValues(document.getElementById('t'));
|
checkConstraintValidationAPIDefaultValues(document.getElementById('t'));
|
||||||
checkConstraintValidationAPIDefaultValues(document.getElementById('k'));
|
checkConstraintValidationAPIDefaultValues(document.getElementById('k'));
|
||||||
|
|
||||||
|
checkDefaultPseudoClass();
|
||||||
|
|
||||||
checkSpecificWillValidate();
|
checkSpecificWillValidate();
|
||||||
|
|
||||||
// Not checking fieldset, output and keygen
|
// Not checking fieldset, output and keygen
|
||||||
|
|
|
@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input, textarea { background-color: rgb(0,0,0) !important; }
|
||||||
|
:-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
:-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
|
||||||
|
@ -31,20 +36,28 @@ function checkTooLongValidity(element)
|
||||||
element.value = "foo";
|
element.value = "foo";
|
||||||
ok(!element.validity.tooLong,
|
ok(!element.validity.tooLong,
|
||||||
"Element should not be too long when maxlength is not set");
|
"Element should not be too long when maxlength is not set");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
|
||||||
element.maxLength = 3;
|
element.maxLength = 3;
|
||||||
ok(!element.validity.tooLong,
|
ok(!element.validity.tooLong,
|
||||||
"Element should not be to long when maxlength = value length");
|
"Element should not be to long when maxlength = value length");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
|
||||||
element.maxLength = 5;
|
element.maxLength = 5;
|
||||||
ok(!element.validity.tooLong,
|
ok(!element.validity.tooLong,
|
||||||
"Element should not be too long when maxlength > value length");
|
"Element should not be too long when maxlength > value length");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
|
||||||
ok(element.validity.valid, "Element should be valid");
|
ok(element.validity.valid, "Element should be valid");
|
||||||
|
|
||||||
element.maxLength = 2;
|
element.maxLength = 2;
|
||||||
ok(element.validity.tooLong,
|
ok(element.validity.tooLong,
|
||||||
"Element should be too long when maxlength < value length");
|
"Element should be too long when maxlength < value length");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
|
|
||||||
ok(!element.validity.valid,
|
ok(!element.validity.valid,
|
||||||
"Element should not be valid when it is too long");
|
"Element should not be valid when it is too long");
|
||||||
|
@ -54,6 +67,8 @@ function checkTooLongValidity(element)
|
||||||
"The validation message text is not correct");
|
"The validation message text is not correct");
|
||||||
ok(!element.checkValidity(), "The element should not be valid");
|
ok(!element.checkValidity(), "The element should not be valid");
|
||||||
element.setCustomValidity("custom message");
|
element.setCustomValidity("custom message");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
is(element.validationMessage, "custom message",
|
is(element.validationMessage, "custom message",
|
||||||
"Custom message should be shown instead of too long one");
|
"Custom message should be shown instead of too long one");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345822
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input, textarea { background-color: rgb(0,0,0) !important; }
|
||||||
|
:valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
:invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a>
|
||||||
<p id="display"></p>
|
<p id="display"></p>
|
||||||
<div id="content" style="display: none">
|
<div id="content">
|
||||||
<form>
|
<form>
|
||||||
<input name="input" id='i'>
|
|
||||||
<input name="input" id='r' type='radio'>
|
|
||||||
<textarea name="textarea" id='t'></textarea>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
|
@ -49,7 +51,7 @@ function checkRequiredAttribute(element)
|
||||||
"Element required attribute should be disabled");
|
"Element required attribute should be disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkNotSufferingFromBeingMissing(element)
|
function checkNotSufferingFromBeingMissing(element, doNotApply)
|
||||||
{
|
{
|
||||||
ok(!element.validity.valueMissing,
|
ok(!element.validity.valueMissing,
|
||||||
"Element should not suffer from value missing");
|
"Element should not suffer from value missing");
|
||||||
|
@ -57,6 +59,12 @@ function checkNotSufferingFromBeingMissing(element)
|
||||||
ok(element.checkValidity(), "Element should be valid");
|
ok(element.checkValidity(), "Element should be valid");
|
||||||
is(element.validationMessage, "",
|
is(element.validationMessage, "",
|
||||||
"Validation message should be the empty string");
|
"Validation message should be the empty string");
|
||||||
|
|
||||||
|
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
doNotApply ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
|
||||||
|
"The pseudo-class is not correctly applied");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkSufferingFromBeingMissing(element)
|
function checkSufferingFromBeingMissing(element)
|
||||||
|
@ -89,10 +97,18 @@ function checkSufferingFromBeingMissing(element)
|
||||||
"This field is mandatory, you have to fill it.",
|
"This field is mandatory, you have to fill it.",
|
||||||
"Validation message is wrong");
|
"Validation message is wrong");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkTextareaRequiredValidity(element)
|
function checkTextareaRequiredValidity()
|
||||||
{
|
{
|
||||||
|
var element = document.createElement('textarea');
|
||||||
|
document.forms[0].appendChild(element);
|
||||||
|
|
||||||
element.value = '';
|
element.value = '';
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
@ -101,7 +117,7 @@ function checkTextareaRequiredValidity(element)
|
||||||
checkSufferingFromBeingMissing(element);
|
checkSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
element.readOnly = true;
|
element.readOnly = true;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element, true);
|
||||||
|
|
||||||
element.readOnly = false;
|
element.readOnly = false;
|
||||||
checkSufferingFromBeingMissing(element);
|
checkSufferingFromBeingMissing(element);
|
||||||
|
@ -114,22 +130,34 @@ function checkTextareaRequiredValidity(element)
|
||||||
|
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
|
document.forms[0].removeChild(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInputRequiredNotApply(element)
|
function checkInputRequiredNotApply(type, isBarred)
|
||||||
{
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = type;
|
||||||
|
document.forms[0].appendChild(element);
|
||||||
|
|
||||||
element.value = '';
|
element.value = '';
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element, isBarred);
|
||||||
|
|
||||||
element.required = true;
|
element.required = true;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element, isBarred);
|
||||||
|
|
||||||
element.required = false;
|
element.required = false;
|
||||||
|
|
||||||
|
document.forms[0].removeChild(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInputRequiredValidity(element)
|
function checkInputRequiredValidity(type)
|
||||||
{
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = type;
|
||||||
|
document.forms[0].appendChild(element);
|
||||||
|
|
||||||
element.value = '';
|
element.value = '';
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
@ -138,7 +166,7 @@ function checkInputRequiredValidity(element)
|
||||||
checkSufferingFromBeingMissing(element);
|
checkSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
element.readOnly = true;
|
element.readOnly = true;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element, true);
|
||||||
|
|
||||||
element.readOnly = false;
|
element.readOnly = false;
|
||||||
checkSufferingFromBeingMissing(element);
|
checkSufferingFromBeingMissing(element);
|
||||||
|
@ -155,12 +183,16 @@ function checkInputRequiredValidity(element)
|
||||||
element.value = '';
|
element.value = '';
|
||||||
checkSufferingFromBeingMissing(element);
|
checkSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
element.required = false;
|
document.forms[0].removeChild(element);
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInputRequiredValidityForCheckbox(element)
|
function checkInputRequiredValidityForCheckbox()
|
||||||
{
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = 'checkbox';
|
||||||
|
document.forms[0].appendChild(element);
|
||||||
|
|
||||||
element.checked = false;
|
element.checked = false;
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
@ -176,10 +208,17 @@ function checkInputRequiredValidityForCheckbox(element)
|
||||||
|
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
|
document.forms[0].removeChild(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInputRequiredValidityForRadio(element)
|
function checkInputRequiredValidityForRadio()
|
||||||
{
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = 'radio';
|
||||||
|
element.name = 'test'
|
||||||
|
document.forms[0].appendChild(element);
|
||||||
|
|
||||||
element.checked = false;
|
element.checked = false;
|
||||||
element.required = false;
|
element.required = false;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
@ -193,28 +232,28 @@ function checkInputRequiredValidityForRadio(element)
|
||||||
element.checked = false;
|
element.checked = false;
|
||||||
checkSufferingFromBeingMissing(element);
|
checkSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
element.required = false;
|
|
||||||
checkNotSufferingFromBeingMissing(element);
|
|
||||||
|
|
||||||
// A required radio button should not suffer from value missing if another
|
// A required radio button should not suffer from value missing if another
|
||||||
// radio button from the same group is checked.
|
// radio button from the same group is checked.
|
||||||
var element2 = document.createElement('input');//document.getElementById('r');
|
var element2 = document.createElement('input');
|
||||||
document.forms[0].appendChild(element2);
|
|
||||||
element2.name = 'input';
|
|
||||||
element2.type = 'radio';
|
element2.type = 'radio';
|
||||||
element2.checked = false;
|
element2.name = 'test';
|
||||||
element2.required = false;
|
|
||||||
|
|
||||||
element.checked = false;
|
|
||||||
element.required = true;
|
|
||||||
checkSufferingFromBeingMissing(element);
|
|
||||||
|
|
||||||
element2.checked = true;
|
element2.checked = true;
|
||||||
|
element2.required = false;
|
||||||
|
document.forms[0].appendChild(element2);
|
||||||
|
|
||||||
|
// Adding a checked radio should make required radio in the group not
|
||||||
|
// suffering from being missing.
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
|
element.checked = false;
|
||||||
|
element2.checked = false;
|
||||||
|
checkSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
// The other radio button should not be disabled.
|
// The other radio button should not be disabled.
|
||||||
// A disabled checked radio button in the radio group
|
// A disabled checked radio button in the radio group
|
||||||
// is enough to not suffer from value missing.
|
// is enough to not suffer from value missing.
|
||||||
|
element2.checked = true;
|
||||||
element2.disabled = true;
|
element2.disabled = true;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
|
@ -227,10 +266,23 @@ function checkInputRequiredValidityForRadio(element)
|
||||||
element2.required = true;
|
element2.required = true;
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
checkSufferingFromBeingMissing(element2);
|
checkSufferingFromBeingMissing(element2);
|
||||||
|
|
||||||
|
element.checked = true;
|
||||||
|
checkNotSufferingFromBeingMissing(element2);
|
||||||
|
|
||||||
|
// The checked radio is not in the group anymore, element2 should be invalid.
|
||||||
|
document.forms[0].removeChild(element);
|
||||||
|
checkSufferingFromBeingMissing(element2);
|
||||||
|
|
||||||
|
document.forms[0].removeChild(element2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInputRequiredValidityForFile(element)
|
function checkInputRequiredValidityForFile()
|
||||||
{
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = 'file'
|
||||||
|
document.forms[0].appendChild(element);
|
||||||
|
|
||||||
function createFileWithData(fileName, fileData) {
|
function createFileWithData(fileName, fileData) {
|
||||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||||
.getService(Components.interfaces.nsIProperties);
|
.getService(Components.interfaces.nsIProperties);
|
||||||
|
@ -269,52 +321,42 @@ function checkInputRequiredValidityForFile(element)
|
||||||
checkNotSufferingFromBeingMissing(element);
|
checkNotSufferingFromBeingMissing(element);
|
||||||
|
|
||||||
file.remove(false);
|
file.remove(false);
|
||||||
|
document.forms[0].removeChild(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
var textarea = document.getElementById('t');
|
checkRequiredAttribute(document.createElement('textarea'));
|
||||||
var input = document.getElementById('i');
|
checkTextareaRequiredValidity();
|
||||||
|
|
||||||
checkRequiredAttribute(textarea);
|
|
||||||
checkTextareaRequiredValidity(textarea);
|
|
||||||
|
|
||||||
// Every input element should have the required attribute.
|
// Every input element should have the required attribute.
|
||||||
checkRequiredAttribute(input);
|
checkRequiredAttribute(document.createElement('input'));
|
||||||
|
|
||||||
// The required attribute behavior depend of the input type.
|
// The require attribute behavior depend of the input type.
|
||||||
// First of all, checks for the types which do not use the required attribute.
|
// First of all, checks for types that make the element barred from
|
||||||
|
// constraint validation.
|
||||||
|
var typeBarredFromConstraintValidation = ["hidden", "button", "reset"];
|
||||||
|
for each (type in typeRequireNotApply) {
|
||||||
|
checkInputRequiredNotApply(type, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, checks for the types which do not use the required attribute.
|
||||||
// TODO: check 'color' and 'range' when they will be implemented.
|
// TODO: check 'color' and 'range' when they will be implemented.
|
||||||
input.type = 'hidden';
|
var typeRequireNotApply = ["submit", "image"];
|
||||||
checkInputRequiredNotApply(input);
|
for each (type in typeRequireNotApply) {
|
||||||
input.type = 'submit';
|
checkInputRequiredNotApply(type, false);
|
||||||
checkInputRequiredNotApply(input);
|
}
|
||||||
input.type = 'button';
|
|
||||||
checkInputRequiredNotApply(input);
|
|
||||||
input.type = 'reset';
|
|
||||||
checkInputRequiredNotApply(input);
|
|
||||||
input.type = 'image';
|
|
||||||
checkInputRequiredNotApply(input);
|
|
||||||
|
|
||||||
// Now, checking for all types which accept the required attribute.
|
// Now, checking for all types which accept the required attribute.
|
||||||
// TODO: check 'datetime', 'date', 'month', 'week', 'time', 'datetime-local'
|
// TODO: check 'datetime', 'date', 'month', 'week', 'time', 'datetime-local'
|
||||||
// and 'number' when they will be implemented.
|
// and 'number' when they will be implemented.
|
||||||
input.type = 'text';
|
var typeRequireApply = ["text", "password", "search", "tel", "email", "url"];
|
||||||
checkInputRequiredValidity(input);
|
|
||||||
input.type = 'password';
|
for each (type in typeRequireApply) {
|
||||||
checkInputRequiredValidity(input);
|
checkInputRequiredValidity(type);
|
||||||
input.type = 'checkbox';
|
}
|
||||||
checkInputRequiredValidityForCheckbox(input);
|
|
||||||
input.type = 'radio';
|
checkInputRequiredValidityForCheckbox();
|
||||||
checkInputRequiredValidityForRadio(input);
|
checkInputRequiredValidityForRadio();
|
||||||
input.type = 'file';
|
checkInputRequiredValidityForFile();
|
||||||
checkInputRequiredValidityForFile(input);
|
|
||||||
input.type = 'search';
|
|
||||||
checkInputRequiredValidity(input);
|
|
||||||
input.type = 'tel';
|
|
||||||
checkInputRequiredValidity(input);
|
|
||||||
input.type = 'email';
|
|
||||||
checkInputRequiredValidity(input);
|
|
||||||
input.type = 'url';
|
|
||||||
checkInputRequiredValidity(input);
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
|
@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=555559
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input { background-color: rgb(0,0,0) !important; }
|
||||||
|
input:valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
input:invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555559">Mozilla Bug 555559</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555559">Mozilla Bug 555559</a>
|
||||||
|
@ -42,6 +47,8 @@ function checkValidEmailAddress(element)
|
||||||
ok(!gInvalid, "The invalid event should not have been thrown");
|
ok(!gInvalid, "The invalid event should not have been thrown");
|
||||||
is(element.validationMessage, '',
|
is(element.validationMessage, '',
|
||||||
"Validation message should be the empty string");
|
"Validation message should be the empty string");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInvalidEmailAddress(element)
|
function checkInvalidEmailAddress(element)
|
||||||
|
@ -54,6 +61,8 @@ function checkInvalidEmailAddress(element)
|
||||||
ok(gInvalid, "The invalid event should have been thrown");
|
ok(gInvalid, "The invalid event should have been thrown");
|
||||||
is(element.validationMessage, "The entered email address is not valid.",
|
is(element.validationMessage, "The entered email address is not valid.",
|
||||||
"Validation message is not valid");
|
"Validation message is not valid");
|
||||||
|
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
var email = document.forms[0].elements[0];
|
var email = document.forms[0].elements[0];
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=558788
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 558788</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input, textarea { background-color: rgb(0,0,0) !important; }
|
||||||
|
:-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
:-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558788">Mozilla Bug 558788</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 558788 **/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test checks the behavior of :valid and :invalid pseudo-classes
|
||||||
|
* when the user is typing/interacting with the element.
|
||||||
|
* Only <input> and <textarea> elements can have there validity changed by an
|
||||||
|
* user input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gContent = document.getElementById('content');
|
||||||
|
|
||||||
|
function checkValidApplies(elmt)
|
||||||
|
{
|
||||||
|
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInvalidApplies(elmt)
|
||||||
|
{
|
||||||
|
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkMissing(elementName)
|
||||||
|
{
|
||||||
|
var element = document.createElement(elementName);
|
||||||
|
element.required = true;
|
||||||
|
gContent.appendChild(element);
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
synthesizeKey("a", {});
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
|
||||||
|
gContent.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTooLong(elementName)
|
||||||
|
{
|
||||||
|
var element = document.createElement(elementName);
|
||||||
|
element.value = "foo";
|
||||||
|
element.maxLength = 2;
|
||||||
|
gContent.appendChild(element);
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
checkValidApplies(element);
|
||||||
|
gContent.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTextAreaMissing()
|
||||||
|
{
|
||||||
|
checkMissing('textarea');
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTextAreaTooLong()
|
||||||
|
{
|
||||||
|
checkTooLong('textarea');
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTextArea()
|
||||||
|
{
|
||||||
|
checkTextAreaMissing();
|
||||||
|
checkTextAreaTooLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInputMissing()
|
||||||
|
{
|
||||||
|
checkMissing('input');
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInputTooLong()
|
||||||
|
{
|
||||||
|
checkTooLong('input');
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInputEmail()
|
||||||
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = 'email';
|
||||||
|
gContent.appendChild(element);
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
synthesizeKey("a", {});
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
|
||||||
|
sendString("@b.c", element);
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
for (var i=0; i<4; ++i) {
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
}
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
gContent.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInputURL()
|
||||||
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.type = 'url';
|
||||||
|
gContent.appendChild(element);
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
synthesizeKey("h", {});
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
|
||||||
|
sendString("ttp://mozilla.org", element);
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
for (var i=0; i<13; ++i) {
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
checkValidApplies(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
for (var i=0; i<4; ++i) {
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
}
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
gContent.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInputPattern()
|
||||||
|
{
|
||||||
|
var element = document.createElement('input');
|
||||||
|
element.pattern = "[0-9]*"
|
||||||
|
gContent.appendChild(element);
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
synthesizeKey("0", {});
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
synthesizeKey("a", {});
|
||||||
|
checkInvalidApplies(element);
|
||||||
|
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
synthesizeKey("VK_BACK_SPACE", {});
|
||||||
|
checkValidApplies(element);
|
||||||
|
|
||||||
|
gContent.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInput()
|
||||||
|
{
|
||||||
|
checkInputMissing();
|
||||||
|
checkInputTooLong();
|
||||||
|
checkInputEmail();
|
||||||
|
checkInputURL();
|
||||||
|
checkInputPattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
checkTextArea();
|
||||||
|
checkInput();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -8,6 +8,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=561640
|
||||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input, textarea { background-color: rgb(0,0,0) !important; }
|
||||||
|
:-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
|
||||||
|
:-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561640">Mozilla Bug 561640</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561640">Mozilla Bug 561640</a>
|
||||||
|
@ -25,11 +30,15 @@ var content = document.getElementById('content');
|
||||||
function checkValid(elmt)
|
function checkValid(elmt)
|
||||||
{
|
{
|
||||||
ok(!elmt.validity.tooLong, "element should not be too long");
|
ok(!elmt.validity.tooLong, "element should not be too long");
|
||||||
|
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInvalid(elmt)
|
function checkInvalid(elmt)
|
||||||
{
|
{
|
||||||
ok(elmt.validity.tooLong, "element should be too long");
|
ok(elmt.validity.tooLong, "element should be too long");
|
||||||
|
is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
|
||||||
|
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
for each (var elmtName in elements) {
|
for each (var elmtName in elements) {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button is of the button type, it is barred from constraint
|
||||||
|
validation and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<button id='b' type='button'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if button is disabled, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<button disabled></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button is disabled and invalid, it is barred from constraint
|
||||||
|
validation and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('b');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.disabled = 'true';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<button id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button is not disabled and invalid, it is candidate for
|
||||||
|
constraint validation and should be affected
|
||||||
|
by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: red; }
|
||||||
|
button:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('b');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.removeAttribute('disabled');
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<button id='b' disabled></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button has a custom error, it should not be affected by :invalid
|
||||||
|
pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: red; }
|
||||||
|
button:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<button id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<button style="background-color: green;"></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button is of the reset type, it is barred from constraint
|
||||||
|
validation and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<button id='b' type='reset'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if a button has is candidate for constraint validation then change
|
||||||
|
its type to be barred from constraint validation, it should not be
|
||||||
|
affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var b = document.getElementById('b');
|
||||||
|
b.setCustomValidity('foo');
|
||||||
|
b.type = 'button';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="document.getElementById('b').type='button'; document.documentElement.className='';">
|
||||||
|
<button type='submit' id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if a button has a custom error when barred from constraint
|
||||||
|
validation then move a type candidate for constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: red; }
|
||||||
|
button:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var b = document.getElementById('b');
|
||||||
|
b.setCustomValidity('foo');
|
||||||
|
b.type = 'submit';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<button type='button' id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if button has no custom error and is not barred from constraint
|
||||||
|
validation, it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<button></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
== button-valid.html button-ref.html
|
||||||
|
== button-invalid.html button-ref.html
|
||||||
|
== button-disabled.html button-ref.html
|
||||||
|
== button-dyn-disabled.html button-ref.html
|
||||||
|
== button-dyn-not-disabled.html button-ref.html
|
||||||
|
== button-button.html button-ref.html
|
||||||
|
== button-reset.html button-ref.html
|
||||||
|
== button-type-invalid.html button-ref.html
|
||||||
|
== button-type-barred.html button-ref.html
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: even if it has a custom error, a fieldset should not be affected by
|
||||||
|
:invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
fieldset { background-color: green; }
|
||||||
|
fieldset:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('f').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<fieldset id='f'></fieldset>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<fieldset style="background-color: green;"></fieldset>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: fieldset is always barred from constraint validation.
|
||||||
|
It should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
fieldset { background-color: green; }
|
||||||
|
fieldset:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<fieldset></fieldset>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,2 @@
|
||||||
|
== fieldset-valid.html fieldset-ref.html
|
||||||
|
== fieldset-invalid.html fieldset-ref.html
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input type='button' style="background-color: green;">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is of button type, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input type='button'>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if input has a custom error, it should be affected by :invalid
|
||||||
|
pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('t').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<input id='t'>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is disabled, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input disabled>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if input is disabled and invalid, it is barred from constraint
|
||||||
|
validation and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('i');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.disabled = 'true';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<input id='i'>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if input is not disabled and invalid, it is candidate for
|
||||||
|
constraint validation and should be affected
|
||||||
|
by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('i');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.removeAttribute('disabled');
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<input id='i' disabled>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if input is no longer readonly, it is candidate for constraint
|
||||||
|
validation and should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('i').removeAttribute('readonly'); document.documentElement.className='';">
|
||||||
|
<input id='i' readonly required>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if input is readonly, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('i').readOnly='ro'; document.documentElement.className='';">
|
||||||
|
<input id='i' required>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input type='email' value='foo'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input value='foo@bar.com' style="background-color: green;">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is valid and not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input type='email' value='foo@bar.com'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if input isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('i').value='foo'; document.documentElement.className='';">
|
||||||
|
<input maxlength="2" id='i'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is valid and is not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input maxlength="2">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input pattern='bar' value='foo'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is valid and not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input pattern='foo' value='foo'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is readonly, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input readonly>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input style="background-color: green;">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input required>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is valid and not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input value='foo' required>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is of reset type, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<!-- Setting value to the empty string let us check against input-button-ref.html -->
|
||||||
|
<input type='reset' value=''>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if an input has is candidate for constraint validation then change
|
||||||
|
its type to be barred from constraint validation, it should not be
|
||||||
|
affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('i').type='button'; document.documentElement.className='';">
|
||||||
|
<input id='i'>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if an input has a custom error when barred from constraint
|
||||||
|
validation then move a type candidate for constraint validation,
|
||||||
|
it should not be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var i = document.getElementById('i');
|
||||||
|
i.setCustomValidity('foo');
|
||||||
|
i.type = 'text';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<input type='button' id='i'>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: red; }
|
||||||
|
input:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input type='url' value='foo'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input value='http://mozilla.org/' style="background-color: green;">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is valid and not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input type='url' value='http://mozilla.org/'>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if input is valid and is not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
input { background-color: green; }
|
||||||
|
input:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<input>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input value='foo' style="background-color: green;">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,23 @@
|
||||||
|
== input-valid.html input-ref.html
|
||||||
|
== input-customerror.html input-ref.html
|
||||||
|
== input-disabled.html input-ref.html
|
||||||
|
== input-dyn-disabled.html input-ref.html
|
||||||
|
== input-dyn-not-disabled.html input-ref.html
|
||||||
|
== input-readonly.html input-ref.html
|
||||||
|
== input-dyn-readonly.html input-ref.html
|
||||||
|
== input-dyn-not-readonly.html input-ref.html
|
||||||
|
== input-maxlength-valid.html input-ref.html
|
||||||
|
== input-maxlength-invalid.html input-withtext-ref.html
|
||||||
|
== input-required-valid.html input-withtext-ref.html
|
||||||
|
== input-required-invalid.html input-ref.html
|
||||||
|
== input-button.html input-button-ref.html
|
||||||
|
== input-reset.html input-button-ref.html
|
||||||
|
== input-email-invalid.html input-withtext-ref.html
|
||||||
|
== input-email-valid.html input-email-ref.html
|
||||||
|
== input-url-invalid.html input-withtext-ref.html
|
||||||
|
== input-url-valid.html input-url-ref.html
|
||||||
|
== input-pattern-valid.html input-withtext-ref.html
|
||||||
|
== input-pattern-invalid.html input-withtext-ref.html
|
||||||
|
== input-type-barred.html input-button-ref.html
|
||||||
|
== input-type-invalid.html input-ref.html
|
||||||
|
# input type='hidden' shouldn't show
|
|
@ -0,0 +1,8 @@
|
||||||
|
# :invalid should not apply on fieldset (always barred from constraint validation)
|
||||||
|
include fieldset/reftest.list
|
||||||
|
|
||||||
|
# :invalid should apply on the following elements
|
||||||
|
include button/reftest.list
|
||||||
|
include input/reftest.list
|
||||||
|
include select/reftest.list
|
||||||
|
include textarea/reftest.list
|
|
@ -0,0 +1,5 @@
|
||||||
|
== select-valid.html select-ref.html
|
||||||
|
== select-invalid.html select-ref.html
|
||||||
|
== select-disabled.html select-disabled-ref.html
|
||||||
|
== select-dyn-disabled.html select-disabled-ref.html
|
||||||
|
== select-dyn-not-disabled.html select-ref.html
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<select disabled style="background-color: green;"></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if select is disabled, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
select { background-color: green; }
|
||||||
|
select:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('s').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<select id='s' disabled></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if select is disabled and invalid, it is barred from constraint
|
||||||
|
validation and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
select { background-color: green; }
|
||||||
|
select:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('s');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.disabled = 'true';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<select id='s'></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if select is not disabled and invalid, it is candidate for
|
||||||
|
constraint validation and should be affected
|
||||||
|
by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
select { background-color: red; }
|
||||||
|
select:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('s');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.removeAttribute('disabled');
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<select id='s' disabled></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if select has a custom error, it should be affected by :invalid
|
||||||
|
pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
select { background-color: red; }
|
||||||
|
select:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('s').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<select id='s'></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<select style="background-color: green;"></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if select has no custom error and is not barred from constraint
|
||||||
|
validation, it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
select { background-color: green; }
|
||||||
|
select:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<select></select>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
== textarea-valid.html textarea-ref.html
|
||||||
|
== textarea-customerror.html textarea-ref.html
|
||||||
|
== textarea-disabled.html textarea-ref.html
|
||||||
|
== textarea-dyn-disabled.html textarea-ref.html
|
||||||
|
== textarea-dyn-not-disabled.html textarea-ref.html
|
||||||
|
== textarea-readonly.html textarea-ref.html
|
||||||
|
== textarea-dyn-readonly.html textarea-ref.html
|
||||||
|
== textarea-dyn-not-readonly.html textarea-ref.html
|
||||||
|
== textarea-maxlength-valid.html textarea-ref.html
|
||||||
|
== textarea-maxlength-invalid.html textarea-withtext-ref.html
|
||||||
|
== textarea-required-valid.html textarea-withtext-ref.html
|
||||||
|
== textarea-required-invalid.html textarea-ref.html
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if textarea has a custom error, it should be affected by :invalid
|
||||||
|
pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: red; }
|
||||||
|
textarea:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('t').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<textarea id='t'></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if textarea is disabled, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<textarea disabled></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if textarea is disabled and invalid, it is barred from constraint
|
||||||
|
validation and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('t');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.disabled = 'true';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<textarea id='t'></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if textarea is not disabled and invalid, it is candidate for
|
||||||
|
constraint validation and should be affected
|
||||||
|
by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: red; }
|
||||||
|
textarea:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var e = document.getElementById('t');
|
||||||
|
e.setCustomValidity('foo');
|
||||||
|
e.removeAttribute('disabled');
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<textarea id='t' disabled></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if textarea is no longer readonly, it is candidate for constraint
|
||||||
|
validation and should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: red; }
|
||||||
|
textarea:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('t').removeAttribute('readonly'); document.documentElement.className='';">
|
||||||
|
<textarea id='t' readonly required></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if textarea is readonly, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('t').readOnly='ro'; document.documentElement.className='';">
|
||||||
|
<textarea id='t' required></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if textarea isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: red; }
|
||||||
|
textarea:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('t').value='foo'; document.documentElement.className='';">
|
||||||
|
<textarea maxlength="2" id='t'></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if textarea is valid and is not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<textarea maxlength="2"></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if textarea is readonly, it is barred from constraint validation
|
||||||
|
and should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<textarea readonly></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<textarea style="background-color: green;"></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if textarea isn't valid nor barred from constraint validation,
|
||||||
|
it should be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: red; }
|
||||||
|
textarea:invalid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<textarea required></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if textarea is valid and not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<textarea required>foo</textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if textarea is valid and is not barred from constraint validation,
|
||||||
|
it should not be affected by :invalid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
textarea { background-color: green; }
|
||||||
|
textarea:invalid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<textarea></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<textarea style="background-color: green;">foo</textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if button is of the button type, it is barred from constraint
|
||||||
|
validation and should not be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<button type='button'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if button is disabled, it is barred from constraint validation
|
||||||
|
and should not be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<button disabled></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button is disabled, it is barred from constraint validation
|
||||||
|
and should not be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').disabled='true'; document.documentElement.className='';">
|
||||||
|
<button id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button is not disabled, it is candidate for constraint validation
|
||||||
|
and should be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: red; }
|
||||||
|
button:valid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').removeAttribute('disabled'); document.documentElement.className='';">
|
||||||
|
<button id='b' disabled></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if button has a custom error, it should not be affected by :valid
|
||||||
|
pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').setCustomValidity('foo'); document.documentElement.className='';">
|
||||||
|
<button id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<button style="background-color: green;"></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if button is of the reset type, it is barred from constraint
|
||||||
|
validation and should not be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<button type='reset'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if a button has is candidate for constraint validation then change
|
||||||
|
its type to be barred from constraint validation, it should not be
|
||||||
|
affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<body onload="document.getElementById('b').type='button'; document.documentElement.className='';">
|
||||||
|
<button type='submit' id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<!-- Test: if a button has a custom error when barred from constraint
|
||||||
|
validation then move a type candidate for constraint validation,
|
||||||
|
it should not be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: green; }
|
||||||
|
button:valid { background-color: red; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function onLoadHandler()
|
||||||
|
{
|
||||||
|
var b = document.getElementById('b');
|
||||||
|
b.setCustomValidity('foo');
|
||||||
|
b.type = 'submit';
|
||||||
|
document.documentElement.className='';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="onLoadHandler();">
|
||||||
|
<button type='button' id='b'></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Test: if button has no custom error and is not barred from constraint
|
||||||
|
validation, it should be affected by :valid pseudo-class. -->
|
||||||
|
<style>
|
||||||
|
button { background-color: red; }
|
||||||
|
button:valid { background-color: green; }
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<button></button>
|
||||||
|
</body>
|
||||||
|
</html>
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче