v = document.getElementsByName("victim");
for (i = 0; i < v.length; i++)
- log('Test for ' + v[i].tagName + ': ' + ((v[i].validity && countAttr(v[i].validity) == 9) ? "SUCCESS" : "FAILURE"));
+ log('Test for ' + v[i].tagName + ': ' + ((v[i].validity && countAttr(v[i].validity) == 10) ? "SUCCESS" : "FAILURE"));
}
</script>
</head>
--- /dev/null
+A date input fields with a bad user input should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(input) is not invalidStyleColor
+PASS input.validity.badInput is false
+Set a value to the first sub-field. The element becomes badInput.
+PASS colorOf(input) is invalidStyleColor
+PASS input.validity.badInput is true
+Set an invalid date, 2012-02-31.
+PASS input.validity.badInput is false
+PASS input.value is ""
+PASS input.validity.badInput is true
+PASS colorOf(input) is invalidStyleColor
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/multiple-fields-validity-badinput.js"></script>
+<script>
+testBadInput('date');
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
--- /dev/null
+A datetime input fields with a bad user input should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(input) is not invalidStyleColor
+PASS input.validity.badInput is false
+Set a value to the first sub-field. The element becomes badInput.
+PASS colorOf(input) is invalidStyleColor
+PASS input.validity.badInput is true
+Set an invalid date, 2012-02-31.
+PASS input.validity.badInput is false
+PASS input.value is ""
+PASS input.validity.badInput is true
+PASS colorOf(input) is invalidStyleColor
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/multiple-fields-validity-badinput.js"></script>
+<script>
+testBadInput('datetime');
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
--- /dev/null
+A datetime-local input fields with a bad user input should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(input) is not invalidStyleColor
+PASS input.validity.badInput is false
+Set a value to the first sub-field. The element becomes badInput.
+PASS colorOf(input) is invalidStyleColor
+PASS input.validity.badInput is true
+Set an invalid date, 2012-02-31.
+PASS input.validity.badInput is false
+PASS input.value is ""
+PASS input.validity.badInput is true
+PASS colorOf(input) is invalidStyleColor
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/multiple-fields-validity-badinput.js"></script>
+<script>
+testBadInput('datetime-local');
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
--- /dev/null
+A month input fields with a bad user input should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(input) is not invalidStyleColor
+PASS input.validity.badInput is false
+Set a value to the first sub-field. The element becomes badInput.
+PASS colorOf(input) is invalidStyleColor
+PASS input.validity.badInput is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/multiple-fields-validity-badinput.js"></script>
+<script>
+testBadInput('month');
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
--- /dev/null
+A number input fields with a bad input string should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(number) != invalidStyleColor is true
+PASS number.validity.badInput is false
+Type '-'. The element becomes badInput.
+PASS colorOf(number) is invalidStyleColor
+PASS number.validity.valid is false
+PASS number.validity.badInput is true
+PASS number.value is ""
+Type '1' additionally. The element becomes valid.
+PASS colorOf(number) != invalidStyleColor is true
+PASS number.validity.badInput is false
+PASS number.value is "-1"
+Type 'a' additionally. The element becomes badInput again.
+PASS colorOf(number) is invalidStyleColor
+PASS number.validity.badInput is true
+PASS number.value is ""
+The element losts focus. The element state should not be changed.
+PASS colorOf(number) is invalidStyleColor
+PASS number.validity.badInput is true
+PASS document.getSelection().toString() is "-1a"
+PASS number.value is ""
+The element losts a renderer. The element state should not be changed.
+PASS number.style.display = "none"; number.validity.badInput is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../fast/js/resources/js-test-pre.js"></script>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<div id=parent>
+<input type=number id=number>
+<input id=another>
+</div>
+<script>
+description('A number input fields with a bad input string should make validity.badInput true and have :invalid style.');
+
+function colorOf(el) {
+ return document.defaultView.getComputedStyle(el, null).getPropertyValue('background-color');
+}
+var invalidStyleColor = 'rgb(255, 0, 0)';
+
+var number = document.getElementById('number');
+number.focus();
+debug('Initial state. The elment has no value.');
+shouldBeTrue('colorOf(number) != invalidStyleColor');
+shouldBeFalse('number.validity.badInput');
+
+debug("Type '-'. The element becomes badInput.");
+document.execCommand('InsertText', false, '-');
+shouldBe('colorOf(number)', 'invalidStyleColor');
+shouldBeFalse('number.validity.valid');
+shouldBeTrue('number.validity.badInput');
+shouldBeEqualToString('number.value', '');
+
+debug("Type '1' additionally. The element becomes valid.");
+document.execCommand('InsertText', false, '1');
+shouldBeTrue('colorOf(number) != invalidStyleColor');
+shouldBeFalse('number.validity.badInput');
+shouldBeEqualToString('number.value', '-1');
+
+debug("Type 'a' additionally. The element becomes badInput again.");
+document.execCommand('InsertText', false, 'a');
+shouldBe('colorOf(number)', 'invalidStyleColor');
+shouldBeTrue('number.validity.badInput');
+shouldBeEqualToString('number.value', '');
+
+debug("The element losts focus. The element state should not be changed.");
+document.getElementById('another').focus();
+shouldBe('colorOf(number)', 'invalidStyleColor');
+shouldBeTrue('number.validity.badInput');
+// Visible value is '-1a'.
+number.focus();
+document.execCommand('SelectAll');
+shouldBeEqualToString('document.getSelection().toString()', '-1a');
+shouldBeEqualToString('number.value', '');
+
+debug("The element losts a renderer. The element state should not be changed.");
+shouldBeTrue('number.style.display = "none"; number.validity.badInput');
+
+document.getElementById('parent').innerHTML = '';
+</script>
+<script src="../../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+var invalidStyleColor = 'rgb(255, 0, 0)';
+var input;
+var quiet = true;
+
+function colorOf(el) {
+ return document.defaultView.getComputedStyle(el, null).getPropertyValue('background-color');
+}
+function testBadInput(type) {
+ if (!window.eventSender) {
+ debug('Needs to run this on DRT/WTR.');
+ return;
+ }
+ description('A ' + type + ' input fields with a bad user input should make validity.badInput true and have :invalid style.');
+ input = document.createElement('input');
+ input.type = type;
+ document.body.appendChild(input);
+ input.focus();
+
+ debug('Initial state. The elment has no value.');
+ shouldNotBe('colorOf(input)', 'invalidStyleColor');
+ shouldBeFalse('input.validity.badInput');
+
+ debug('Set a value to the first sub-field. The element becomes badInput.');
+ eventSender.keyDown('upArrow');
+ shouldBe('colorOf(input)', 'invalidStyleColor');
+ shouldBeTrue('input.validity.badInput');
+
+ if (type == 'date' || type== 'datetime' || type == 'datetime-local') {
+ debug('Set an invalid date, 2012-02-31.');
+ if (type == 'date')
+ input.value = '2012-02-01';
+ else if (type == 'datetime')
+ input.value = '2012-02-01T03:04Z';
+ else
+ input.value = '2012-02-01T03:04';
+ shouldNotBe('colorOf(input)', 'invalidStyleColor', quiet);
+ shouldBeFalse('input.validity.badInput', quiet);
+ eventSender.keyDown('rightArrow'); // -> 02/[01]/2012 ...
+ eventSender.keyDown('downArrow'); // -> 02/[31]/2012 ...
+ shouldBeEqualToString('input.value', '');
+ shouldBeTrue('input.validity.badInput');
+ shouldBe('colorOf(input)', 'invalidStyleColor');
+ }
+}
--- /dev/null
+A time input fields with a bad user input should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(input) is not invalidStyleColor
+PASS input.validity.badInput is false
+Set a value to the first sub-field. The element becomes badInput.
+PASS colorOf(input) is invalidStyleColor
+PASS input.validity.badInput is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/multiple-fields-validity-badinput.js"></script>
+<script>
+testBadInput('time');
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
--- /dev/null
+A week input fields with a bad user input should make validity.badInput true and have :invalid style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state. The elment has no value.
+PASS colorOf(input) is not invalidStyleColor
+PASS input.validity.badInput is false
+Set a value to the first sub-field. The element becomes badInput.
+PASS colorOf(input) is invalidStyleColor
+PASS input.validity.badInput is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<style>
+:invalid {
+ background-color: #ff0000;
+}
+</style>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/multiple-fields-validity-badinput.js"></script>
+<script>
+testBadInput('week');
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
if (!element)
return false;
element->document()->setContainsValidityStyleRules();
- return (element->willValidate() && !element->isValidFormControlElement()) || element->hasUnacceptableValue();
+ return element->willValidate() && !element->isValidFormControlElement();
case CSSSelector::PseudoChecked:
{
if (!element)
virtual bool isDefaultButtonForForm() const { return false; }
virtual bool willValidate() const { return false; }
virtual bool isValidFormControlElement() { return false; }
- virtual bool hasUnacceptableValue() const { return false; }
virtual bool isInRange() const { return false; }
virtual bool isOutOfRange() const { return false; }
virtual bool isFrameElementBase() const { return false; }
return element->willValidate() && !m_customValidationMessage.isEmpty();
}
+bool FormAssociatedElement::hasBadInput() const
+{
+ return false;
+}
+
bool FormAssociatedElement::patternMismatch() const
{
return false;
bool FormAssociatedElement::valid() const
{
bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
- || tooLong() || patternMismatch() || valueMissing() || customError();
+ || tooLong() || patternMismatch() || valueMissing() || hasBadInput() || customError();
return !someError;
}
// Override functions for patterMismatch, rangeOverflow, rangerUnderflow,
// stepMismatch, tooLong and valueMissing must call willValidate method.
+ virtual bool hasBadInput() const;
virtual bool patternMismatch() const;
virtual bool rangeOverflow() const;
virtual bool rangeUnderflow() const;
return willValidate() && m_inputType->valueMissing(value());
}
+bool HTMLInputElement::hasBadInput() const
+{
+ return m_inputType->hasBadInput();
+}
+
bool HTMLInputElement::patternMismatch() const
{
return willValidate() && m_inputType->patternMismatch(value());
return m_inputType->localizeValue(proposedValue);
}
-bool HTMLInputElement::hasUnacceptableValue() const
-{
- return m_inputType->hasUnacceptableValue();
-}
-
bool HTMLInputElement::isInRange() const
{
return m_inputType->isInRange(value());
virtual bool shouldAutocomplete() const;
// For ValidityState
+ virtual bool hasBadInput() const OVERRIDE;
virtual bool patternMismatch() const OVERRIDE;
virtual bool rangeUnderflow() const OVERRIDE;
virtual bool rangeOverflow() const;
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
- virtual bool hasUnacceptableValue() const;
-
virtual bool isInRange() const;
virtual bool isOutOfRange() const;
return false;
}
+bool InputType::hasBadInput() const
+{
+ return false;
+}
+
bool InputType::patternMismatch(const String&) const
{
return false;
return createStepRange(RejectAny).stepMismatch(numericValue);
}
+String InputType::badInputText() const
+{
+ ASSERT_NOT_REACHED();
+ return validationMessageTypeMismatchText();
+}
+
String InputType::typeMismatchText() const
{
return validationMessageTypeMismatchText();
if (typeMismatch())
return typeMismatchText();
+ if (hasBadInput())
+ return badInputText();
+
if (patternMismatch(value))
return validationMessagePatternMismatchText();
return proposedValue;
}
-bool InputType::hasUnacceptableValue()
-{
- return false;
-}
-
bool InputType::receiveDroppedFiles(const DragData*)
{
ASSERT_NOT_REACHED();
virtual bool typeMismatch() const;
virtual bool supportsRequired() const;
virtual bool valueMissing(const String&) const;
+ virtual bool hasBadInput() const;
virtual bool patternMismatch(const String&) const;
bool rangeUnderflow(const String&) const;
bool rangeOverflow(const String&) const;
virtual StepRange createStepRange(AnyStepHandling) const;
virtual void stepUp(int, ExceptionCode&);
virtual void stepUpFromRenderer(int);
+ virtual String badInputText() const;
virtual String typeMismatchText() const;
virtual String valueMissingText() const;
virtual bool canSetStringValue() const;
// Returing the null string means "use the default value."
// This function must be called only by HTMLInputElement::sanitizeValue().
virtual String sanitizeValue(const String&) const;
- virtual bool hasUnacceptableValue();
// Event handlers
#include "HTMLParserIdioms.h"
#include "KeyboardEvent.h"
#include "LocalizedNumber.h"
+#include "LocalizedStrings.h"
+//#include "PlatformLocale.h"
#include "RenderTextControl.h"
#include <limits>
#include <wtf/ASCIICType.h>
return serializeForNumberType(value);
}
-void NumberInputType::handleBlurEvent()
-{
- // Reset the renderer value, which might be unmatched with the element value.
- element()->setFormControlValueMatchesRenderer(false);
-
- // We need to reset the renderer value explicitly because an unacceptable
- // renderer value should be purged before style calculation.
- updateInnerTextValue();
-}
-
static bool isE(UChar ch)
{
return ch == 'e' || ch == 'E';
return isfinite(parseToDoubleForNumberType(proposedValue)) ? proposedValue : emptyString();
}
-bool NumberInputType::hasUnacceptableValue()
+bool NumberInputType::hasBadInput() const
{
- if (!element()->renderer())
- return false;
String standardValue = convertFromVisibleValue(element()->innerTextValue());
return !standardValue.isEmpty() && !isfinite(parseToDoubleForNumberType(standardValue));
}
+String NumberInputType::badInputText() const
+{
+ return validationMessageBadInputForNumberText();
+}
+
bool NumberInputType::shouldRespectSpeechAttribute()
{
return true;
virtual void handleWheelEvent(WheelEvent*) OVERRIDE;
virtual Decimal parseToNumber(const String&, const Decimal&) const OVERRIDE;
virtual String serialize(const Decimal&) const OVERRIDE;
- virtual void handleBlurEvent() OVERRIDE;
virtual String localizeValue(const String&) const OVERRIDE;
virtual String visibleValue() const OVERRIDE;
virtual String convertFromVisibleValue(const String&) const OVERRIDE;
virtual String sanitizeValue(const String&) const OVERRIDE;
- virtual bool hasUnacceptableValue() OVERRIDE;
+ virtual bool hasBadInput() const OVERRIDE;
+ virtual String badInputText() const OVERRIDE;
virtual bool shouldRespectSpeechAttribute() OVERRIDE;
virtual bool supportsPlaceholder() const OVERRIDE;
virtual bool isNumberField() const OVERRIDE;
// sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
element()->setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element()->innerTextValue())));
element()->updatePlaceholderVisibility(false);
- // Recalc for :invalid and hasUnacceptableValue() change.
+ // Recalc for :invalid change.
element()->setNeedsStyleRecalc();
didSetValueByUserEdit(wasChanged ? ValueChangeStateChanged : ValueChangeStateNone);
return m_control->stepMismatch();
}
+bool ValidityState::badInput() const
+{
+ return m_control->hasBadInput();
+}
+
bool ValidityState::customError() const
{
return m_control->customError();
bool rangeUnderflow() const;
bool rangeOverflow() const;
bool stepMismatch() const;
+ bool badInput() const;
bool customError() const;
bool valid() const;
readonly attribute boolean rangeUnderflow;
readonly attribute boolean rangeOverflow;
readonly attribute boolean stepMismatch;
+ readonly attribute boolean badInput;
readonly attribute boolean customError;
readonly attribute boolean valid;
};
return WEB_UI_STRING("step mismatch", "Validation message for input form controls with value not respecting the step attribute");
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return validationMessageTypeMismatchText();
+}
+
} // namespace WebCore
String validationMessageRangeUnderflowText(const String& minimum);
String validationMessageRangeOverflowText(const String& maximum);
String validationMessageStepMismatchText(const String& base, const String& step);
+ String validationMessageBadInputForNumberText();
+/*#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+ String validationMessageBadInputForDateTimeText();
+#endif*/
#if ENABLE(CALENDAR_PICKER)
String calendarTodayText();
String calendarClearText();
return validationMessageValueMissingText();
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return validationMessageTypeMismatchText();
+}
+
String localizedMediaControlElementString(const String&)
{
notImplemented();
return validationMessageValueMissingText();
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return validationMessageTypeMismatchText();
+}
+
String missingPluginText()
{
return String::fromUTF8("missing plugin");
{
return String::fromUTF8(key, strlen(key));
}
-}
\ No newline at end of file
+}
return validationMessageValueMissingText();
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return validationMessageTypeMismatchText();
+}
+
String missingPluginText()
{
return String::fromUTF8("missing plugin");
{
return String::fromUTF8(key, strlen(key));
}
-}
\ No newline at end of file
+}
return String::fromUTF8(key, strlen(key));
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return validationMessageTypeMismatchText();
+}
+
}
return String();
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return validationMessageTypeMismatchText();
+}
+
String validationMessageTypeMismatchForEmailText()
{
notImplemented();
return query(WebLocalizedString::ValidationTypeMismatch);
}
+String validationMessageBadInputForNumberText()
+{
+ notImplemented();
+ return String("Bad number");
+}
+
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+String validationMessageBadInputForDateTimeText()
+{
+ notImplemented();
+ return String("bad date");
+}
+#endif
+
String validationMessageTypeMismatchForEmailText()
{
return query(WebLocalizedString::ValidationTypeMismatchForEmail);