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; }
StepRange NumberInputType::createStepRange(AnyStepHandling anyStepHandling) const { DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (numberDefaultStep, numberDefaultStepBase, numberStepScaleFactor)); const Decimal stepBase = parseToDecimalForNumberType(element()->fastGetAttribute(minAttr), numberDefaultStepBase); // FIXME: We should use numeric_limits<double>::max for number input type. const Decimal floatMax = Decimal::fromDouble(numeric_limits<float>::max()); const Decimal minimum = parseToNumber(element()->fastGetAttribute(minAttr), -floatMax); const Decimal maximum = parseToNumber(element()->fastGetAttribute(maxAttr), floatMax); const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); return StepRange(stepBase, minimum, maximum, step, stepDescription); }
Decimal StepRange::parseStep(AnyStepHandling anyStepHandling, const StepDescription& stepDescription, const String& stepString) { if (stepString.isEmpty()) return stepDescription.defaultValue(); if (equalIgnoringCase(stepString, "any")) { switch (anyStepHandling) { case RejectAny: return Decimal::nan(); case AnyIsDefaultStep: return stepDescription.defaultValue(); default: ASSERT_NOT_REACHED(); } } Decimal step = parseToDecimalForNumberType(stepString); if (!step.isFinite() || step <= 0) return stepDescription.defaultValue(); switch (stepDescription.stepValueShouldBe) { case StepValueShouldBeReal: step *= stepDescription.stepScaleFactor; break; case ParsedStepValueShouldBeInteger: // For date, month, and week, the parsed value should be an integer for some types. step = std::max(step.round(), Decimal(1)); step *= stepDescription.stepScaleFactor; break; case ScaledStepValueShouldBeInteger: // For datetime, datetime-local, time, the result should be an integer. step *= stepDescription.stepScaleFactor; step = std::max(step.round(), Decimal(1)); break; default: ASSERT_NOT_REACHED(); } ASSERT(step > 0); return step; }
Decimal NumberInputType::parseToNumber(const String& src, const Decimal& defaultValue) const { return parseToDecimalForNumberType(src, defaultValue); }
inline static Decimal sliderPosition(HTMLInputElement* element) { const StepRange stepRange(element->createStepRange(RejectAny)); const Decimal oldValue = parseToDecimalForNumberType(element->value(), stepRange.defaultValue()); return stepRange.proportionFromValue(stepRange.clampValue(oldValue)); }
Decimal parseToDecimalForNumberType(const String& string) { return parseToDecimalForNumberType(string, Decimal::nan()); }