зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1622221 - Rework number input localization. r=jwatt
This restores our previous behavior with the new <input type=number> implementation (see the changes in test_input_number_l10n.html, which undoes the changes of the regressing bug), and adds a test that shows that we display the localized value properly. Differential Revision: https://phabricator.services.mozilla.com/D66822 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ae23069b7b
Коммит
0c9bcce517
|
@ -1441,7 +1441,7 @@ void HTMLInputElement::GetValue(nsAString& aValue, CallerType aCallerType) {
|
|||
GetValueInternal(aValue, aCallerType);
|
||||
|
||||
if (SanitizesOnValueGetter()) {
|
||||
SanitizeValue(aValue);
|
||||
SanitizeValue(aValue, ForValueGetter::Yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4495,7 +4495,8 @@ void HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify) {
|
|||
}
|
||||
}
|
||||
|
||||
void HTMLInputElement::SanitizeValue(nsAString& aValue) {
|
||||
void HTMLInputElement::SanitizeValue(nsAString& aValue,
|
||||
ForValueGetter aForGetter) {
|
||||
NS_ASSERTION(mDoneCreating, "The element creation should be finished!");
|
||||
|
||||
switch (mType) {
|
||||
|
@ -4517,7 +4518,40 @@ void HTMLInputElement::SanitizeValue(nsAString& aValue) {
|
|||
bool ok = mInputType->ConvertStringToNumber(aValue, value);
|
||||
if (!ok) {
|
||||
aValue.Truncate();
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString sanitizedValue;
|
||||
if (aForGetter == ForValueGetter::Yes) {
|
||||
// If the default non-localized algorithm parses the value, then we're
|
||||
// done, don't un-localize it, to avoid precision loss, and to preserve
|
||||
// scientific notation as well for example.
|
||||
//
|
||||
// FIXME(emilio, bug 1622808): Localization should ideally be more
|
||||
// input-preserving.
|
||||
if (StringToDecimal(aValue).isFinite()) {
|
||||
return;
|
||||
}
|
||||
// For the <input type=number> value getter, we return the unlocalized
|
||||
// value if it doesn't parse as StringToDecimal, for compat with other
|
||||
// browsers.
|
||||
char buf[32];
|
||||
DebugOnly<bool> ok = value.toString(buf, ArrayLength(buf));
|
||||
sanitizedValue.AssignASCII(buf);
|
||||
MOZ_ASSERT(ok, "buf not big enough");
|
||||
} else {
|
||||
mInputType->ConvertNumberToString(value, sanitizedValue);
|
||||
// Otherwise we localize as needed, but if both the localized and
|
||||
// unlocalized version parse, we just use the unlocalized one, to
|
||||
// preserve the input as much as possible.
|
||||
//
|
||||
// FIXME(emilio, bug 1622808): Localization should ideally be more
|
||||
// input-preserving.
|
||||
if (StringToDecimal(sanitizedValue).isFinite()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
aValue.Assign(sanitizedValue);
|
||||
} break;
|
||||
case NS_FORM_INPUT_RANGE: {
|
||||
Decimal minimum = GetMinimum();
|
||||
|
|
|
@ -1085,12 +1085,14 @@ class HTMLInputElement final : public TextControlElement,
|
|||
MOZ_CAN_RUN_SCRIPT
|
||||
void HandleTypeChange(uint8_t aNewType, bool aNotify);
|
||||
|
||||
enum class ForValueGetter { No, Yes };
|
||||
|
||||
/**
|
||||
* Sanitize the value of the element depending of its current type.
|
||||
* See:
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#value-sanitization-algorithm
|
||||
*/
|
||||
void SanitizeValue(nsAString& aValue);
|
||||
void SanitizeValue(nsAString& aValue, ForValueGetter = ForValueGetter::No);
|
||||
|
||||
/**
|
||||
* Returns whether the placeholder attribute applies for the current type.
|
||||
|
|
|
@ -95,8 +95,6 @@ nsresult NumericInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) {
|
|||
|
||||
bool NumericInputTypeBase::ConvertStringToNumber(nsAString& aValue,
|
||||
Decimal& aResultValue) const {
|
||||
// FIXME(emilio, bug 1605158): This should really just be
|
||||
// StringToDecimal(aValue).
|
||||
ICUUtils::LanguageTagIterForContent langTagIter(mInputElement);
|
||||
aResultValue =
|
||||
Decimal::fromDouble(ICUUtils::ParseNumber(aValue, langTagIter));
|
||||
|
@ -120,7 +118,7 @@ bool NumericInputTypeBase::ConvertNumberToString(
|
|||
return ok;
|
||||
}
|
||||
|
||||
/* input type=numer */
|
||||
/* input type=number */
|
||||
|
||||
bool NumberInputType::IsValueMissing() const {
|
||||
if (!mInputElement->IsRequired()) {
|
||||
|
@ -140,6 +138,16 @@ bool NumberInputType::HasBadInput() const {
|
|||
return !value.IsEmpty() && mInputElement->GetValueAsDecimal().isNaN();
|
||||
}
|
||||
|
||||
bool NumberInputType::ConvertNumberToString(
|
||||
Decimal aValue, nsAString& aResultString) const {
|
||||
MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number.");
|
||||
|
||||
aResultString.Truncate();
|
||||
ICUUtils::LanguageTagIterForContent langTagIter(mInputElement);
|
||||
ICUUtils::LocalizeNumber(aValue.toDouble(), langTagIter, aResultString);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult NumberInputType::GetValueMissingMessage(nsAString& aMessage) {
|
||||
return nsContentUtils::GetMaybeLocalizedString(
|
||||
nsContentUtils::eDOM_PROPERTIES, "FormValidationBadInputNumber",
|
||||
|
|
|
@ -34,7 +34,7 @@ class NumericInputTypeBase : public InputType {
|
|||
};
|
||||
|
||||
// input type=number
|
||||
class NumberInputType : public NumericInputTypeBase {
|
||||
class NumberInputType final : public NumericInputTypeBase {
|
||||
public:
|
||||
static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) {
|
||||
return new (aMemory) NumberInputType(aInputElement);
|
||||
|
@ -46,6 +46,9 @@ class NumberInputType : public NumericInputTypeBase {
|
|||
nsresult GetValueMissingMessage(nsAString& aMessage) override;
|
||||
nsresult GetBadInputMessage(nsAString& aMessage) override;
|
||||
|
||||
bool ConvertNumberToString(Decimal aValue,
|
||||
nsAString& aResultString) const override;
|
||||
|
||||
protected:
|
||||
bool IsMutable() const override;
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ function runTest(test) {
|
|||
sendString(test.inputWithoutGrouping);
|
||||
is(elem.valueAsNumber, test.value, "Test " + test.desc + " ('" + test.langTag +
|
||||
"') localization without grouping separator");
|
||||
is(elem.value, test.inputWithoutGrouping,
|
||||
"Test " + test.desc + " ('" + test.langTag + "') localization without grouping separator as string");
|
||||
is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag +
|
||||
"') localization without grouping separator as string");
|
||||
}
|
||||
|
||||
function runInvalidInputTest(test) {
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<!doctype html>
|
||||
<input type=number value=1.25 step=0.01>
|
|
@ -0,0 +1,2 @@
|
|||
<!doctype html>
|
||||
<input type=number value=1.25 step=0.01 lang=de>
|
|
@ -55,5 +55,8 @@ fuzzy(0-128,0-4) == number-reframe-anon-text-field.html number-reframe-anon-text
|
|||
# Style inheritance:
|
||||
== number-style-inheritance.html number-style-inheritance-ref.html
|
||||
|
||||
# l10n
|
||||
!= number-localized.html number-localized-notref.html
|
||||
|
||||
== overflow-clip-box.html overflow-clip-box-ref.html
|
||||
!= overflow-clip-box.html overflow-clip-box-notref.html
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
[number.html]
|
||||
max-asserts: 2
|
||||
[value >= Number.MAX_VALUE]
|
||||
expected: FAIL
|
||||
|
||||
[value = +1]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче