diff options
Diffstat (limited to 'dom/html/input/NumericInputTypes.cpp')
-rw-r--r-- | dom/html/input/NumericInputTypes.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/dom/html/input/NumericInputTypes.cpp b/dom/html/input/NumericInputTypes.cpp new file mode 100644 index 0000000000..54811ddb9d --- /dev/null +++ b/dom/html/input/NumericInputTypes.cpp @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/NumericInputTypes.h" + +#include "mozilla/TextControlState.h" +#include "mozilla/dom/HTMLInputElement.h" +#include "ICUUtils.h" + +using namespace mozilla; +using namespace mozilla::dom; + +bool NumericInputTypeBase::IsRangeOverflow() const { + Decimal maximum = mInputElement->GetMaximum(); + if (maximum.isNaN()) { + return false; + } + + Decimal value = mInputElement->GetValueAsDecimal(); + if (value.isNaN()) { + return false; + } + + return value > maximum; +} + +bool NumericInputTypeBase::IsRangeUnderflow() const { + Decimal minimum = mInputElement->GetMinimum(); + if (minimum.isNaN()) { + return false; + } + + Decimal value = mInputElement->GetValueAsDecimal(); + if (value.isNaN()) { + return false; + } + + return value < minimum; +} + +bool NumericInputTypeBase::HasStepMismatch() const { + Decimal value = mInputElement->GetValueAsDecimal(); + return mInputElement->ValueIsStepMismatch(value); +} + +nsresult NumericInputTypeBase::GetRangeOverflowMessage(nsAString& aMessage) { + // We want to show the value as parsed when it's a number + Decimal maximum = mInputElement->GetMaximum(); + MOZ_ASSERT(!maximum.isNaN()); + + nsAutoString maxStr; + char buf[32]; + DebugOnly<bool> ok = maximum.toString(buf, ArrayLength(buf)); + maxStr.AssignASCII(buf); + MOZ_ASSERT(ok, "buf not big enough"); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationNumberRangeOverflow", mInputElement->OwnerDoc(), maxStr); +} + +nsresult NumericInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { + Decimal minimum = mInputElement->GetMinimum(); + MOZ_ASSERT(!minimum.isNaN()); + + nsAutoString minStr; + char buf[32]; + DebugOnly<bool> ok = minimum.toString(buf, ArrayLength(buf)); + minStr.AssignASCII(buf); + MOZ_ASSERT(ok, "buf not big enough"); + + return nsContentUtils::FormatMaybeLocalizedString( + aMessage, nsContentUtils::eDOM_PROPERTIES, + "FormValidationNumberRangeUnderflow", mInputElement->OwnerDoc(), minStr); +} + +bool NumericInputTypeBase::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + aResultValue = HTMLInputElement::StringToDecimal(aValue); + return aResultValue.isFinite(); +} + +bool NumericInputTypeBase::ConvertNumberToString( + Decimal aValue, nsAString& aResultString) const { + MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number."); + + aResultString.Truncate(); + + char buf[32]; + bool ok = aValue.toString(buf, ArrayLength(buf)); + aResultString.AssignASCII(buf); + MOZ_ASSERT(ok, "buf not big enough"); + + return ok; +} + +/* input type=number */ + +bool NumberInputType::IsValueMissing() const { + if (!mInputElement->IsRequired()) { + return false; + } + + if (!IsMutable()) { + return false; + } + + return IsValueEmpty(); +} + +bool NumberInputType::HasBadInput() const { + nsAutoString value; + GetNonFileValueInternal(value); + return !value.IsEmpty() && mInputElement->GetValueAsDecimal().isNaN(); +} + +bool NumberInputType::ConvertStringToNumber(nsAString& aValue, + Decimal& aResultValue) const { + ICUUtils::LanguageTagIterForContent langTagIter(mInputElement); + aResultValue = + Decimal::fromDouble(ICUUtils::ParseNumber(aValue, langTagIter)); + if (aResultValue.isFinite()) { + return true; + } + return NumericInputTypeBase::ConvertStringToNumber(aValue, aResultValue); +} + +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", + mInputElement->OwnerDoc(), aMessage); +} + +nsresult NumberInputType::GetBadInputMessage(nsAString& aMessage) { + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationBadInputNumber", + mInputElement->OwnerDoc(), aMessage); +} + +bool NumberInputType::IsMutable() const { + return !mInputElement->IsDisabled() && + !mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly); +} + +/* input type=range */ +void RangeInputType::MinMaxStepAttrChanged() { + // The value may need to change when @min/max/step changes since the value may + // have been invalid and can now change to a valid value, or vice versa. For + // example, consider: <input type=range value=-1 max=1 step=3>. The valid + // range is 0 to 1 while the nearest valid steps are -1 and 2 (the max value + // having prevented there being a valid step in range). Changing @max to/from + // 1 and a number greater than on equal to 3 should change whether we have a + // step mismatch or not. + // The value may also need to change between a value that results in a step + // mismatch and a value that results in overflow. For example, if @max in the + // example above were to change from 1 to -1. + nsAutoString value; + GetNonFileValueInternal(value); + SetValueInternal(value, TextControlState::ValueSetterOption::ByInternalAPI); +} |