Bug 610415 - Make :-moz-ui-invalid and :-moz-ui-valid not applying when the form element has novalidate attribute set. r+a=sicking

This commit is contained in:
Mounir Lamouri
2010-12-17 15:26:24 -08:00
parent d3a9a1e5a4
commit 14f99c88ea
27 changed files with 239 additions and 16 deletions

View File

@@ -708,8 +708,17 @@ nsHTMLButtonElement::IntrinsicState() const
nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
if (IsCandidateForConstraintValidation()) {
state |= IsValid() ? NS_EVENT_STATE_VALID | NS_EVENT_STATE_MOZ_UI_VALID
: NS_EVENT_STATE_INVALID | NS_EVENT_STATE_MOZ_UI_INVALID;
if (IsValid()) {
state |= NS_EVENT_STATE_VALID;
if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
state |= NS_EVENT_STATE_MOZ_UI_VALID;
}
} else {
state |= NS_EVENT_STATE_INVALID;
if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
state |= NS_EVENT_STATE_MOZ_UI_INVALID;
}
}
}
if (mForm && !mForm->GetValidity() && IsSubmitControl()) {

View File

@@ -376,6 +376,36 @@ nsHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
aNotify);
}
nsresult
nsHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
// Update all form elements states because they might be [no longer]
// affected by :-moz-ui-valid or :-moz-ui-invalid.
nsIDocument* doc = GetCurrentDoc();
if (doc) {
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
for (PRUint32 i = 0, length = mControls->mElements.Length();
i < length; ++i) {
doc->ContentStatesChanged(mControls->mElements[i], nsnull,
NS_EVENT_STATE_MOZ_UI_VALID |
NS_EVENT_STATE_MOZ_UI_INVALID);
}
for (PRUint32 i = 0, length = mControls->mNotInElements.Length();
i < length; ++i) {
doc->ContentStatesChanged(mControls->mNotInElements[i], nsnull,
NS_EVENT_STATE_MOZ_UI_VALID |
NS_EVENT_STATE_MOZ_UI_INVALID);
}
}
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify);
}
NS_IMPL_STRING_ATTR(nsHTMLFormElement, AcceptCharset, acceptcharset)
NS_IMPL_ACTION_ATTR(nsHTMLFormElement, Action, action)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Autocomplete, autocomplete,

View File

@@ -172,6 +172,8 @@ public:
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
/**
* Forget all information about the current submission (and the fact that we

View File

@@ -560,6 +560,8 @@ protected:
"element is valid!");
/**
* Never show the invalid UI if the form has the novalidate attribute set.
*
* Always show the invalid UI if:
* - the form has already tried to be submitted but was invalid;
* - the element is suffering from a custom error;
@@ -567,8 +569,16 @@ protected:
*
* Otherwise, show the invalid UI if the element's value has been changed.
*/
if ((mForm && mForm->HasEverTriedInvalidSubmit()) ||
GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
if (mForm) {
if (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return false;
}
if (mForm->HasEverTriedInvalidSubmit()) {
return true;
}
}
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
return true;
}
@@ -593,9 +603,14 @@ protected:
* @note This doesn't take into account the validity of the element.
*/
bool ShouldShowValidUI() const {
if (mForm && mForm->HasEverTriedInvalidSubmit()) {
if (mForm) {
if (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return false;
}
if (mForm->HasEverTriedInvalidSubmit()) {
return true;
}
}
switch (GetValueMode()) {
case VALUE_MODE_DEFAULT:

View File

@@ -43,6 +43,7 @@
#include "nsIConstraintValidation.h"
#include "nsIEventStateManager.h"
#include "mozAutoDocUpdate.h"
#include "nsHTMLFormElement.h"
class nsHTMLOutputElement : public nsGenericHTMLFormElement,
@@ -206,8 +207,17 @@ nsHTMLOutputElement::IntrinsicState() const
// We don't have to call IsCandidateForConstraintValidation()
// because <output> can't be barred from constraint validation.
states |= IsValid() ? NS_EVENT_STATE_VALID | NS_EVENT_STATE_MOZ_UI_VALID
: NS_EVENT_STATE_INVALID | NS_EVENT_STATE_MOZ_UI_INVALID;
if (IsValid()) {
states |= NS_EVENT_STATE_VALID;
if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
states |= NS_EVENT_STATE_MOZ_UI_VALID;
}
} else {
states |= NS_EVENT_STATE_INVALID;
if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
states |= NS_EVENT_STATE_MOZ_UI_INVALID;
}
}
return states;
}

View File

@@ -527,15 +527,28 @@ protected:
"element is valid!");
/**
* Never show the invalid UI if the form has the novalidate attribute set.
*
* Always show the invalid UI if:
* - the form has already tried to be submitted but was invalid;
* - the element is suffering from a custom error;
*
* Otherwise, show the invalid UI if the selection has been changed.
*/
return mSelectionHasChanged ||
(mForm && mForm->HasEverTriedInvalidSubmit()) ||
GetValidityState(VALIDITY_STATE_CUSTOM_ERROR);
if (mForm) {
if (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return false;
}
if (mForm->HasEverTriedInvalidSubmit()) {
return true;
}
}
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
return true;
}
return mSelectionHasChanged;
}
/**
@@ -545,9 +558,18 @@ protected:
* @note This doesn't take into account the validity of the element.
*/
bool ShouldShowValidUI() const {
return mSelectionHasChanged ||
(mForm && mForm->HasEverTriedInvalidSubmit());
if (mForm) {
if (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return false;
}
if (mForm->HasEverTriedInvalidSubmit()) {
return true;
}
}
return mSelectionHasChanged;
}
/** The options[] array */
nsRefPtr<nsHTMLOptionCollection> mOptions;
/** false if the parser is in the middle of adding children. */

View File

@@ -287,6 +287,8 @@ protected:
"element is valid!");
/**
* Never show the invalid UI if the form has the novalidate attribute set.
*
* Always show the invalid UI if:
* - the form has already tried to be submitted but was invalid;
* - the element is suffering from a custom error;
@@ -294,8 +296,20 @@ protected:
* Otherwise, show the invalid UI if the element's value has been changed.
*/
return (mForm && mForm->HasEverTriedInvalidSubmit()) ||
mValueChanged || GetValidityState(VALIDITY_STATE_CUSTOM_ERROR);
if (mForm) {
if (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return false;
}
if (mForm->HasEverTriedInvalidSubmit()) {
return true;
}
}
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
return true;
}
return mValueChanged;
}
/**
@@ -305,7 +319,16 @@ protected:
* @note This doesn't take into account the validity of the element.
*/
bool ShouldShowValidUI() const {
return (mForm && mForm->HasEverTriedInvalidSubmit()) || mValueChanged;
if (mForm) {
if (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return false;
}
if (mForm->HasEverTriedInvalidSubmit()) {
return true;
}
}
return mValueChanged;
}
/**

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html class='reftest-wait'>
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('b').setCustomValidity('foo');
document.documentElement.className = '';">
<form novalidate>
<button id='b' class='notinvalid'></button>
</form>
</body>
</html>

View File

@@ -10,3 +10,4 @@
== button-disabled-fieldset-1.html button-fieldset-ref.html
== button-disabled-fieldset-2.html button-fieldset-ref.html
== button-fieldset-legend.html button-fieldset-legend-ref.html
== button-novalidate.html button-ref.html

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html class="reftest-wait">
<!-- When the form has @novalidate, :-moz-ui-invalid doesn't apply. -->
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('i').value = '';
document.documentElement.className = '';">
<form novalidate>
<input id='i' class='notinvalid' required>
</form>
</body>
</html>

View File

@@ -41,4 +41,5 @@
== input-radio-dyn-valid-2.html success-ref.html
== input-radio-nogroup-required-valid.html success-ref.html
== input-radio-nogroup-required-invalid.html success-ref.html
== input-novalidate.html input-ref.html
# input type='hidden' shouldn't show

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html class="reftest-wait">
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('o').setCustomValidity('foo');
document.documentElement.className = '';">
<form novalidate>
<output id='o' class='notinvalid'>foo</output>
</form>
</body>
</html>

View File

@@ -1,2 +1,3 @@
== output-valid.html output-ref.html
== output-invalid.html output-ref.html
== output-novalidate.html output-ref.html

View File

@@ -15,3 +15,4 @@
== select-disabled-fieldset-1.html select-fieldset-ref.html
== select-disabled-fieldset-2.html select-fieldset-ref.html
== select-fieldset-legend.html select-fieldset-legend-ref.html
== select-novalidate.html select-ref.html

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html class="reftest-wait">
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('s').setCustomValidity('foo');
document.documentElement.className = '';">
<form novalidate>
<select id='s' class='notinvalid'></select>
</form>
</body>
</html>

View File

@@ -15,3 +15,4 @@
== textarea-required-invalid-changed.html textarea-ref.html
== textarea-disabled-fieldset-1.html textarea-fieldset-ref.html
== textarea-disabled-fieldset-2.html textarea-fieldset-ref.html
== textarea-novalidate.html textarea-ref.html

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html class='reftest-wait'>
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('t').value = '';
document.documentElement.className = '';">
<form novalidate>
<textarea id='t' required class='notinvalid'></textarea>
</form>
</body>
</html>

View File

@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<link rel='stylesheet' type='text/css' href='style.css'>
<body>
<form novalidate>
<button class='notvalid'></button>
</form>
</body>
</html>

View File

@@ -10,3 +10,4 @@
== button-disabled-fieldset-1.html button-fieldset-ref.html
== button-disabled-fieldset-2.html button-fieldset-ref.html
== button-fieldset-legend.html button-fieldset-legend-ref.html
== button-novalidate.html button-ref.html

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html class="reftest-wait">
<!-- When the form has @novalidate, :-moz-ui-invalid doesn't apply. -->
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('i').value = 'foo';
document.documentElement.className = '';">
<form novalidate>
<input id='i' class='notvalid' required>
</form>
</body>
</html>

View File

@@ -40,4 +40,5 @@
== input-radio-dyn-valid-2.html success-ref.html
== input-radio-nogroup-required-valid.html success-ref.html
== input-radio-nogroup-required-invalid.html success-ref.html
== input-novalidate.html input-withtext-ref.html
# input type='hidden' shouldn't show

View File

@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<link rel='stylesheet' type='text/css' href='style.css'>
<body>
<form novalidate>
<output class='notvalid'>foo</output>
</form>
</body>
</html>

View File

@@ -1,2 +1,3 @@
== output-valid.html output-ref.html
== output-invalid.html output-ref.html
== output-novalidate.html output-ref.html

View File

@@ -15,3 +15,4 @@
== select-disabled-fieldset-1.html select-fieldset-ref.html
== select-disabled-fieldset-2.html select-fieldset-ref.html
== select-fieldset-legend.html select-fieldset-legend-ref.html
== select-novalidate.html select-required-ref.html

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html class="reftest-wait">
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('s').selectedIndex = 0;
document.documentElement.className = '';">
<form novalidate>
<select id='s' class='notvalid'>
<option>foo</option>
</select>
</form>
</body>
</html>

View File

@@ -17,3 +17,4 @@
== textarea-disabled-fieldset-1.html textarea-fieldset-ref.html
== textarea-disabled-fieldset-2.html textarea-fieldset-ref.html
== textarea-fieldset-legend.html textarea-fieldset-legend-ref.html
== textarea-novalidate.html textarea-withtext-ref.html

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html class='reftest-wait'>
<link rel='stylesheet' type='text/css' href='style.css'>
<body onload="document.getElementById('t').value = 'foo';
document.documentElement.className = '';">
<form novalidate>
<textarea id='t' required class='notvalid'></textarea>
</form>
</body>
</html>