mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Bug 605124 (5/5) - :-moz-ui-invalid should not apply while typing if it was not applied on focus. r=bz a=bsmedberg
--HG-- rename : content/html/content/test/test_bug605124.html => content/html/content/test/test_bug605124-1.html
This commit is contained in:
parent
9803705a0f
commit
41847811d6
@ -1706,20 +1706,9 @@ nsHTMLFormElement::CheckValidFormSubmission()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!CheckFormValidity(invalidElements.get())) {
|
||||
nsCOMPtr<nsISupports> inst;
|
||||
nsCOMPtr<nsIFormSubmitObserver> observer;
|
||||
PRBool more = PR_TRUE;
|
||||
while (NS_SUCCEEDED(theEnum->HasMoreElements(&more)) && more) {
|
||||
theEnum->GetNext(getter_AddRefs(inst));
|
||||
observer = do_QueryInterface(inst);
|
||||
|
||||
if (observer) {
|
||||
observer->NotifyInvalidSubmit(this,
|
||||
static_cast<nsIArray*>(invalidElements));
|
||||
}
|
||||
}
|
||||
|
||||
// For the first invalid submission, we should update element states.
|
||||
// We have to do that _before_ calling the observers so we are sure they
|
||||
// will not interfere (like focusing the element).
|
||||
if (!mEverTriedInvalidSubmit) {
|
||||
mEverTriedInvalidSubmit = true;
|
||||
|
||||
@ -1750,6 +1739,19 @@ nsHTMLFormElement::CheckValidFormSubmission()
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> inst;
|
||||
nsCOMPtr<nsIFormSubmitObserver> observer;
|
||||
PRBool more = PR_TRUE;
|
||||
while (NS_SUCCEEDED(theEnum->HasMoreElements(&more)) && more) {
|
||||
theEnum->GetNext(getter_AddRefs(inst));
|
||||
observer = do_QueryInterface(inst);
|
||||
|
||||
if (observer) {
|
||||
observer->NotifyInvalidSubmit(this,
|
||||
static_cast<nsIArray*>(invalidElements));
|
||||
}
|
||||
}
|
||||
|
||||
// The form is invalid. Observers have been alerted. Do not submit.
|
||||
return false;
|
||||
}
|
||||
|
@ -115,7 +115,6 @@
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -626,6 +625,7 @@ nsHTMLInputElement::nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
SET_BOOLBIT(mBitField, BF_PARSER_CREATING, aFromParser);
|
||||
SET_BOOLBIT(mBitField, BF_INHIBIT_RESTORATION,
|
||||
aFromParser & mozilla::dom::FROM_PARSER_FRAGMENT);
|
||||
SET_BOOLBIT(mBitField, BF_CAN_SHOW_INVALID_UI, PR_TRUE);
|
||||
mInputData.mState = new nsTextEditorState(this);
|
||||
NS_ADDREF(mInputData.mState);
|
||||
|
||||
@ -2113,16 +2113,33 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (PlaceholderApplies() &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
|
||||
// TODO: checking if the value is empty could be a good idea but we do not
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
||||
nsEventStates states;
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
|
||||
// If the invalid UI is shown, we should show it while focusing (and
|
||||
// update). Otherwise, we should not.
|
||||
SET_BOOLBIT(mBitField, BF_CAN_SHOW_INVALID_UI,
|
||||
!IsValid() && ShouldShowInvalidUI());
|
||||
// We don't have to update NS_EVENT_STATE_MOZ_UI_INVALID given that
|
||||
// the state should not change.
|
||||
} else { // NS_BLUR_CONTENT
|
||||
SET_BOOLBIT(mBitField, BF_CAN_SHOW_INVALID_UI, PR_TRUE);
|
||||
states |= NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (PlaceholderApplies() &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
// TODO: checking if the value is empty could be a good idea but we do not
|
||||
// have a simple way to do that, see bug 585100
|
||||
(aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
aVisitor.mEvent->message == NS_BLUR_CONTENT)) {
|
||||
states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_MOZ_PLACEHOLDER);
|
||||
doc->ContentStatesChanged(this, nsnull, states);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3310,20 +3327,9 @@ nsHTMLInputElement::IntrinsicState() const
|
||||
state |= NS_EVENT_STATE_VALID;
|
||||
} else {
|
||||
state |= NS_EVENT_STATE_INVALID;
|
||||
ValueModeType valueMode = GetValueMode();
|
||||
// If the element is suffering from VALIDITY_STATE_CUSTOM_ERROR,
|
||||
// NS_EVENT_STATE_MOZ_UI_INVALID always apply.
|
||||
// Otherwise, NS_EVENT_STATE_MOZ_UI_INVALID applies if the element's value
|
||||
// has been modified.
|
||||
// For VALUE_MODE_DEFAULT case, value being modified has no sense.
|
||||
// NS_EVENT_STATE_MOZ_UI_INVALID always applies if the form submission has
|
||||
// been tried while invalid.
|
||||
if ((mForm && mForm->HasEverTriedInvalidSubmit()) ||
|
||||
(valueMode == VALUE_MODE_DEFAULT ||
|
||||
GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
||||
(valueMode == VALUE_MODE_DEFAULT_ON && GetCheckedChanged()) ||
|
||||
((valueMode == VALUE_MODE_FILENAME || valueMode == VALUE_MODE_VALUE) &&
|
||||
GET_BOOLBIT(mBitField, BF_VALUE_CHANGED)))) {
|
||||
|
||||
if (GET_BOOLBIT(mBitField, BF_CAN_SHOW_INVALID_UI) &&
|
||||
ShouldShowInvalidUI()) {
|
||||
state |= NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
}
|
||||
|
@ -45,11 +45,11 @@
|
||||
#include "nsITextControlElement.h"
|
||||
#include "nsIPhonetic.h"
|
||||
#include "nsIDOMNSEditableElement.h"
|
||||
|
||||
#include "nsTextEditorState.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIConstraintValidation.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsHTMLFormElement.h" // for ShouldShowInvalidUI()
|
||||
|
||||
//
|
||||
// Accessors for mBitField
|
||||
@ -66,6 +66,7 @@
|
||||
#define BF_CHECKED_IS_TOGGLED 9
|
||||
#define BF_INDETERMINATE 10
|
||||
#define BF_INHIBIT_RESTORATION 11
|
||||
#define BF_CAN_SHOW_INVALID_UI 12
|
||||
|
||||
#define GET_BOOLBIT(bitfield, field) (((bitfield) & (0x01 << (field))) \
|
||||
? PR_TRUE : PR_FALSE)
|
||||
@ -533,6 +534,44 @@ protected:
|
||||
*/
|
||||
nsresult SetDefaultValueAsValue();
|
||||
|
||||
/**
|
||||
* Return if an invalid element should have a specific UI for being invalid
|
||||
* (with :-moz-ui-invalid pseudo-class.
|
||||
*
|
||||
* @return Whether the invalid elemnet should have a UI for being invalid.
|
||||
* @note The caller has to be sure the element is invalid before calling.
|
||||
*/
|
||||
bool ShouldShowInvalidUI() const {
|
||||
NS_ASSERTION(!IsValid(), "You should not call ShouldShowInvalidUI if the "
|
||||
"element is valid!");
|
||||
|
||||
/**
|
||||
* 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;
|
||||
* - the element has had its value changed
|
||||
*
|
||||
* Otherwise, show the invalid UI if the element's value has been changed.
|
||||
*/
|
||||
if ((mForm && mForm->HasEverTriedInvalidSubmit()) ||
|
||||
GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (GetValueMode()) {
|
||||
case VALUE_MODE_DEFAULT:
|
||||
return true;
|
||||
case VALUE_MODE_DEFAULT_ON:
|
||||
return GetCheckedChanged();
|
||||
case VALUE_MODE_VALUE:
|
||||
case VALUE_MODE_FILENAME:
|
||||
return GET_BOOLBIT(mBitField, BF_VALUE_CHANGED);
|
||||
default:
|
||||
NS_NOTREACHED("We should not be there: there are no other modes.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
|
||||
/**
|
||||
|
@ -238,9 +238,12 @@ protected:
|
||||
PRPackedBool mInhibitStateRestoration;
|
||||
/** Whether our disabled state has changed from the default **/
|
||||
PRPackedBool mDisabledChanged;
|
||||
/** Whether we should make :-moz-ui-invalid apply on the element. **/
|
||||
PRPackedBool mCanShowInvalidUI;
|
||||
|
||||
/** The state of the text editor (selection controller and the editor) **/
|
||||
nsRefPtr<nsTextEditorState> mState;
|
||||
|
||||
|
||||
NS_IMETHOD SelectAll(nsPresContext* aPresContext);
|
||||
/**
|
||||
* Get the value, whether it is from the content or the frame.
|
||||
@ -270,6 +273,29 @@ protected:
|
||||
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom *aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Return if an invalid element should have a specific UI for being invalid
|
||||
* (with :-moz-ui-invalid pseudo-class.
|
||||
*
|
||||
* @return Whether the invalid elemnet should have a UI for being invalid.
|
||||
* @note The caller has to be sure the element is invalid before calling.
|
||||
*/
|
||||
bool ShouldShowInvalidUI() const {
|
||||
NS_ASSERTION(!IsValid(), "You should not call ShouldShowInvalidUI if the "
|
||||
"element is valid!");
|
||||
|
||||
/**
|
||||
* 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 element's value has been changed.
|
||||
*/
|
||||
|
||||
return (mForm && mForm->HasEverTriedInvalidSubmit()) ||
|
||||
mValueChanged || GetValidityState(VALIDITY_STATE_CUSTOM_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mutable state of the element.
|
||||
*/
|
||||
@ -288,6 +314,7 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(already_AddRefed<nsINodeInfo> aNode
|
||||
mDoneAddingChildren(!aFromParser),
|
||||
mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
|
||||
mDisabledChanged(PR_FALSE),
|
||||
mCanShowInvalidUI(PR_TRUE),
|
||||
mState(new nsTextEditorState(this))
|
||||
{
|
||||
AddMutationObserver(this);
|
||||
@ -730,15 +757,31 @@ nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
mHandlingSelect = PR_FALSE;
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
||||
nsEventStates states;
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
|
||||
// If the invalid UI is shown, we should show it while focusing (and
|
||||
// update). Otherwise, we should not.
|
||||
mCanShowInvalidUI = !IsValid() && ShouldShowInvalidUI();
|
||||
// We don't have to update NS_EVENT_STATE_MOZ_UI_INVALID given that
|
||||
// the state should not change.
|
||||
} else { // NS_BLUR_CONTENT
|
||||
mCanShowInvalidUI = PR_TRUE;
|
||||
states |= NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
// TODO: checking if the value is empty could be a good idea but we do not
|
||||
// have a simple way to do that, see bug 585100
|
||||
(aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
aVisitor.mEvent->message == NS_BLUR_CONTENT)) {
|
||||
states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
|
||||
doc->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_MOZ_PLACEHOLDER);
|
||||
doc->ContentStatesChanged(this, nsnull, states);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1022,8 +1065,7 @@ nsHTMLTextAreaElement::IntrinsicState() const
|
||||
// Otherwise, it applies if the value has been modified.
|
||||
// NS_EVENT_STATE_MOZ_UI_INVALID always applies if the form submission has
|
||||
// been tried while invalid.
|
||||
if ((mForm && mForm->HasEverTriedInvalidSubmit()) ||
|
||||
(mValueChanged || GetValidityState(VALIDITY_STATE_CUSTOM_ERROR))) {
|
||||
if (mCanShowInvalidUI && ShouldShowInvalidUI()) {
|
||||
state |= NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +243,8 @@ _TEST_FILES = \
|
||||
test_bug596511.html \
|
||||
reflect.js \
|
||||
test_bug613113.html \
|
||||
test_bug605124.html \
|
||||
test_bug605124-1.html \
|
||||
test_bug605124-2.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=605124
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605124">Mozilla Bug 605124</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<div id="content">
|
||||
<form>
|
||||
<textarea required></textarea>
|
||||
<input required>
|
75
content/html/content/test/test_bug605124-2.html
Normal file
75
content/html/content/test/test_bug605124-2.html
Normal file
@ -0,0 +1,75 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=605124
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 605124</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"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605124">Mozilla Bug 605124</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input required>
|
||||
<textarea required></textarea>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 605124 **/
|
||||
|
||||
function checkPseudoClass(aElement, aExpected)
|
||||
{
|
||||
is(aElement.mozMatchesSelector(":-moz-ui-invalid"), aExpected,
|
||||
"mozMatchesSelector(':-moz-ui-invalid') should return " + aExpected + " for " + aElement);
|
||||
}
|
||||
|
||||
function checkElement(aElement)
|
||||
{
|
||||
checkPseudoClass(aElement, false);
|
||||
|
||||
// Focusing while :-moz-ui-invalid doesn't apply,
|
||||
// the pseudo-class should not apply while typing.
|
||||
aElement.focus();
|
||||
checkPseudoClass(aElement, false);
|
||||
// with keys
|
||||
synthesizeKey('f', {});
|
||||
checkPseudoClass(aElement, false);
|
||||
synthesizeKey('VK_BACK_SPACE', {});
|
||||
checkPseudoClass(aElement, false);
|
||||
// with .value
|
||||
aElement.value = 'f';
|
||||
checkPseudoClass(aElement, false);
|
||||
aElement.value = '';
|
||||
checkPseudoClass(aElement, false);
|
||||
|
||||
aElement.blur();
|
||||
checkPseudoClass(aElement, true);
|
||||
|
||||
// Focusing while :-moz-ui-invalid applies,
|
||||
// the pseudo-class should apply while typing if appropriate.
|
||||
aElement.focus();
|
||||
checkPseudoClass(aElement, true);
|
||||
// with keys
|
||||
synthesizeKey('f', {});
|
||||
checkPseudoClass(aElement, false);
|
||||
synthesizeKey('VK_BACK_SPACE', {});
|
||||
checkPseudoClass(aElement, true);
|
||||
// with .value
|
||||
aElement.value = 'f';
|
||||
checkPseudoClass(aElement, false);
|
||||
aElement.value = '';
|
||||
checkPseudoClass(aElement, true);
|
||||
}
|
||||
|
||||
checkElement(document.getElementsByTagName('input')[0]);
|
||||
checkElement(document.getElementsByTagName('textarea')[0]);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user