This source file includes following definitions.
- calculateRenderSize
- create
- countUsage
- formControlType
- setValue
- valueAsDouble
- setValueAsDouble
- setValueAsDecimal
- typeMismatchFor
- typeMismatch
- createStepRange
- sizeShouldIncludeDecoration
- isSteppable
- handleKeydownEvent
- parseToNumber
- serialize
- isE
- localizeValue
- visibleValue
- convertFromVisibleValue
- sanitizeValue
- hasBadInput
- badInputText
- rangeOverflowText
- rangeUnderflowText
- shouldRespectSpeechAttribute
- supportsPlaceholder
- isNumberField
- minOrMaxAttributeChanged
- stepAttributeChanged
- supportsSelectionAPI
#include "config.h"
#include "core/html/forms/NumberInputType.h"
#include "HTMLNames.h"
#include "InputTypeNames.h"
#include "bindings/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/events/KeyboardEvent.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/rendering/RenderTextControl.h"
#include "platform/text/PlatformLocale.h"
#include "wtf/MathExtras.h"
#include "wtf/PassOwnPtr.h"
#include <limits>
namespace WebCore {
using blink::WebLocalizedString;
using namespace HTMLNames;
using namespace std;
static const int numberDefaultStep = 1;
static const int numberDefaultStepBase = 0;
static const int numberStepScaleFactor = 1;
struct RealNumberRenderSize {
unsigned sizeBeforeDecimalPoint;
unsigned sizeAfteDecimalPoint;
RealNumberRenderSize(unsigned before, unsigned after)
: sizeBeforeDecimalPoint(before)
, sizeAfteDecimalPoint(after)
{
}
RealNumberRenderSize max(const RealNumberRenderSize& other) const
{
return RealNumberRenderSize(
std::max(sizeBeforeDecimalPoint, other.sizeBeforeDecimalPoint),
std::max(sizeAfteDecimalPoint, other.sizeAfteDecimalPoint));
}
};
static RealNumberRenderSize calculateRenderSize(const Decimal& value)
{
ASSERT(value.isFinite());
const unsigned sizeOfDigits = String::number(value.value().coefficient()).length();
const unsigned sizeOfSign = value.isNegative() ? 1 : 0;
const int exponent = value.exponent();
if (exponent >= 0)
return RealNumberRenderSize(sizeOfSign + sizeOfDigits, 0);
const int sizeBeforeDecimalPoint = exponent + sizeOfDigits;
if (sizeBeforeDecimalPoint > 0) {
return RealNumberRenderSize(sizeOfSign + sizeBeforeDecimalPoint, sizeOfDigits - sizeBeforeDecimalPoint);
}
const unsigned sizeOfZero = 1;
const unsigned numberOfZeroAfterDecimalPoint = -sizeBeforeDecimalPoint;
return RealNumberRenderSize(sizeOfSign + sizeOfZero , numberOfZeroAfterDecimalPoint + sizeOfDigits);
}
PassRefPtr<InputType> NumberInputType::create(HTMLInputElement& element)
{
return adoptRef(new NumberInputType(element));
}
void NumberInputType::countUsage()
{
countUsageIfVisible(UseCounter::InputTypeNumber);
}
const AtomicString& NumberInputType::formControlType() const
{
return InputTypeNames::number;
}
void NumberInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
if (!valueChanged && sanitizedValue.isEmpty() && !element().innerTextValue().isEmpty())
element().updateView();
TextFieldInputType::setValue(sanitizedValue, valueChanged, eventBehavior);
}
double NumberInputType::valueAsDouble() const
{
return parseToDoubleForNumberType(element().value());
}
void NumberInputType::setValueAsDouble(double newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const
{
element().setValue(serializeForNumberType(newValue), eventBehavior);
}
void NumberInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const
{
element().setValue(serializeForNumberType(newValue), eventBehavior);
}
bool NumberInputType::typeMismatchFor(const String& value) const
{
return !value.isEmpty() && !std::isfinite(parseToDoubleForNumberType(value));
}
bool NumberInputType::typeMismatch() const
{
ASSERT(!typeMismatchFor(element().value()));
return false;
}
StepRange NumberInputType::createStepRange(AnyStepHandling anyStepHandling) const
{
DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (numberDefaultStep, numberDefaultStepBase, numberStepScaleFactor));
const Decimal doubleMax = Decimal::fromDouble(numeric_limits<double>::max());
return InputType::createStepRange(anyStepHandling, numberDefaultStepBase, -doubleMax, doubleMax, stepDescription);
}
bool NumberInputType::sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const
{
preferredSize = defaultSize;
const String stepString = element().fastGetAttribute(stepAttr);
if (equalIgnoringCase(stepString, "any"))
return false;
const Decimal minimum = parseToDecimalForNumberType(element().fastGetAttribute(minAttr));
if (!minimum.isFinite())
return false;
const Decimal maximum = parseToDecimalForNumberType(element().fastGetAttribute(maxAttr));
if (!maximum.isFinite())
return false;
const Decimal step = parseToDecimalForNumberType(stepString, 1);
ASSERT(step.isFinite());
RealNumberRenderSize size = calculateRenderSize(minimum).max(calculateRenderSize(maximum).max(calculateRenderSize(step)));
preferredSize = size.sizeBeforeDecimalPoint + size.sizeAfteDecimalPoint + (size.sizeAfteDecimalPoint ? 1 : 0);
return true;
}
bool NumberInputType::isSteppable() const
{
return true;
}
void NumberInputType::handleKeydownEvent(KeyboardEvent* event)
{
handleKeydownEventForSpinButton(event);
if (!event->defaultHandled())
TextFieldInputType::handleKeydownEvent(event);
}
Decimal NumberInputType::parseToNumber(const String& src, const Decimal& defaultValue) const
{
return parseToDecimalForNumberType(src, defaultValue);
}
String NumberInputType::serialize(const Decimal& value) const
{
if (!value.isFinite())
return String();
return serializeForNumberType(value);
}
static bool isE(UChar ch)
{
return ch == 'e' || ch == 'E';
}
String NumberInputType::localizeValue(const String& proposedValue) const
{
if (proposedValue.isEmpty())
return proposedValue;
if (proposedValue.find(isE) != kNotFound)
return proposedValue;
return element().locale().convertToLocalizedNumber(proposedValue);
}
String NumberInputType::visibleValue() const
{
return localizeValue(element().value());
}
String NumberInputType::convertFromVisibleValue(const String& visibleValue) const
{
if (visibleValue.isEmpty())
return visibleValue;
if (visibleValue.find(isE) != kNotFound)
return visibleValue;
return element().locale().convertFromLocalizedNumber(visibleValue);
}
String NumberInputType::sanitizeValue(const String& proposedValue) const
{
if (proposedValue.isEmpty())
return proposedValue;
return std::isfinite(parseToDoubleForNumberType(proposedValue)) ? proposedValue : emptyString();
}
bool NumberInputType::hasBadInput() const
{
String standardValue = convertFromVisibleValue(element().innerTextValue());
return !standardValue.isEmpty() && !std::isfinite(parseToDoubleForNumberType(standardValue));
}
String NumberInputType::badInputText() const
{
return locale().queryString(WebLocalizedString::ValidationBadInputForNumber);
}
String NumberInputType::rangeOverflowText(const Decimal& maximum) const
{
return locale().queryString(WebLocalizedString::ValidationRangeOverflow, localizeValue(serialize(maximum)));
}
String NumberInputType::rangeUnderflowText(const Decimal& minimum) const
{
return locale().queryString(WebLocalizedString::ValidationRangeUnderflow, localizeValue(serialize(minimum)));
}
bool NumberInputType::shouldRespectSpeechAttribute()
{
return true;
}
bool NumberInputType::supportsPlaceholder() const
{
return true;
}
bool NumberInputType::isNumberField() const
{
return true;
}
void NumberInputType::minOrMaxAttributeChanged()
{
InputType::minOrMaxAttributeChanged();
if (element().renderer())
element().renderer()->setNeedsLayoutAndPrefWidthsRecalc();
}
void NumberInputType::stepAttributeChanged()
{
InputType::stepAttributeChanged();
if (element().renderer())
element().renderer()->setNeedsLayoutAndPrefWidthsRecalc();
}
bool NumberInputType::supportsSelectionAPI() const
{
return false;
}
}