Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / forms / InputType.cpp
index 0b43554..6f79e08 100644 (file)
@@ -83,8 +83,7 @@ static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
     OwnPtr<InputTypeFactoryMap> map = adoptPtr(new InputTypeFactoryMap);
     map->add(InputTypeNames::button, ButtonInputType::create);
     map->add(InputTypeNames::checkbox, CheckboxInputType::create);
-    if (RuntimeEnabledFeatures::inputTypeColorEnabled())
-        map->add(InputTypeNames::color, ColorInputType::create);
+    map->add(InputTypeNames::color, ColorInputType::create);
     map->add(InputTypeNames::date, DateInputType::create);
     map->add(InputTypeNames::datetime_local, DateTimeLocalInputType::create);
     map->add(InputTypeNames::email, EmailInputType::create);
@@ -102,8 +101,7 @@ static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
     map->add(InputTypeNames::tel, TelephoneInputType::create);
     map->add(InputTypeNames::time, TimeInputType::create);
     map->add(InputTypeNames::url, URLInputType::create);
-    if (RuntimeEnabledFeatures::inputTypeWeekEnabled())
-        map->add(InputTypeNames::week, WeekInputType::create);
+    map->add(InputTypeNames::week, WeekInputType::create);
     // No need to register "text" because it is the default type.
     return map.release();
 }
@@ -222,12 +220,12 @@ double InputType::valueAsDouble() const
 
 void InputType::setValueAsDouble(double doubleValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const
 {
-    setValueAsDecimal(Decimal::fromDouble(doubleValue), eventBehavior, exceptionState);
+    exceptionState.throwDOMException(InvalidStateError, "This input element does not support Number values.");
 }
 
-void InputType::setValueAsDecimal(const Decimal&, TextFieldEventBehavior, ExceptionState& exceptionState) const
+void InputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState&) const
 {
-    exceptionState.throwDOMException(InvalidStateError, "This input element does not support Decimal values.");
+    element().setValue(serialize(newValue), eventBehavior);
 }
 
 bool InputType::supportsValidation() const
@@ -567,7 +565,7 @@ bool InputType::storesValueSeparateFromAttribute()
 void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
 {
     element().setValueInternal(sanitizedValue, eventBehavior);
-    element().setNeedsStyleRecalc();
+    element().setNeedsStyleRecalc(SubtreeStyleChange);
     if (!valueChanged)
         return;
     switch (eventBehavior) {
@@ -750,10 +748,6 @@ bool InputType::supportsReadOnly() const
     return false;
 }
 
-void InputType::updatePlaceholderText()
-{
-}
-
 String InputType::defaultToolTip() const
 {
     return String();
@@ -794,7 +788,7 @@ unsigned InputType::width() const
     return 0;
 }
 
-void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState)
+void InputType::applyStep(const Decimal& current, int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState)
 {
     StepRange stepRange(createStepRange(anyStepHandling));
     if (!stepRange.hasStep()) {
@@ -802,38 +796,56 @@ void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldE
         return;
     }
 
-    const Decimal current = parseToNumberOrNaN(element().value());
-    if (!current.isFinite()) {
-        exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::notAFiniteNumber(current, "form element's current value"));
-        return;
-    }
-    Decimal newValue = current + stepRange.step() * count;
-    if (!newValue.isFinite()) {
-        exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::notAFiniteNumber(newValue, "form element's new value"));
-        return;
-    }
-
-    const Decimal acceptableErrorValue = stepRange.acceptableError();
-    if (newValue - stepRange.minimum() < -acceptableErrorValue) {
-        exceptionState.throwDOMException(InvalidStateError, "The form element's new value (" + newValue.toString() + ") would be lower than the minimum (" + stepRange.minimum().toString() + "), and snapping to the minimum would exceed the amount of acceptible error.");
-        return;
-    }
-    if (newValue < stepRange.minimum())
-        newValue = stepRange.minimum();
+    EventQueueScope scope;
+    const Decimal step = stepRange.step();
 
     const AtomicString& stepString = element().fastGetAttribute(stepAttr);
-    if (!equalIgnoringCase(stepString, "any"))
-        newValue = stepRange.alignValueForStep(current, newValue);
+    if (!equalIgnoringCase(stepString, "any") && stepRange.stepMismatch(current)) {
+        // Snap-to-step / clamping steps
+        // If the current value is not matched to step value:
+        // - The value should be the larger matched value nearest to 0 if count > 0
+        //   e.g. <input type=number value=3 min=-100 step=3> -> 5
+        // - The value should be the smaller matched value nearest to 0 if count < 0
+        //   e.g. <input type=number value=3 min=-100 step=3> -> 2
+        //
+
+        ASSERT(!step.isZero());
+        Decimal newValue;
+        const Decimal base = stepRange.stepBase();
+        if (count < 0)
+            newValue = base + ((current - base) / step).floor() * step;
+        else if (count > 0)
+            newValue = base + ((current - base) / step).ceiling() * step;
+        else
+            newValue = current;
+
+        if (newValue < stepRange.minimum())
+            newValue = stepRange.minimum();
+        if (newValue > stepRange.maximum())
+            newValue = stepRange.maximum();
+
+        setValueAsDecimal(newValue, count == 1 || count == -1 ? DispatchChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION);
+        if (count > 1) {
+            applyStep(newValue, count - 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
+            return;
+        }
+        if (count < -1) {
+            applyStep(newValue, count + 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
+            return;
+        }
+    } else {
+        Decimal newValue = current + stepRange.step() * count;
 
-    if (newValue - stepRange.maximum() > acceptableErrorValue) {
-        exceptionState.throwDOMException(InvalidStateError, "The form element's new value (" + newValue.toString() + ") would be higher than the maximum (" + stepRange.maximum().toString() + "), and snapping to the maximum would exceed the amount of acceptible error.");
-        return;
-    }
-    if (newValue > stepRange.maximum())
-        newValue = stepRange.maximum();
+        if (!equalIgnoringCase(stepString, "any"))
+            newValue = stepRange.alignValueForStep(current, newValue);
 
-    setValueAsDecimal(newValue, eventBehavior, exceptionState);
+        if (newValue > stepRange.maximum())
+            newValue = newValue - stepRange.step();
+        else if (newValue < stepRange.minimum())
+            newValue = newValue + stepRange.step();
 
+        setValueAsDecimal(newValue, eventBehavior, exceptionState);
+    }
     if (AXObjectCache* cache = element().document().existingAXObjectCache())
         cache->postNotification(&element(), AXObjectCache::AXValueChanged, true);
 }
@@ -857,14 +869,15 @@ void InputType::stepUp(int n, ExceptionState& exceptionState)
         exceptionState.throwDOMException(InvalidStateError, "This form element is not steppable.");
         return;
     }
-    applyStep(n, RejectAny, DispatchNoEvent, exceptionState);
+    const Decimal current = parseToNumber(element().value(), 0);
+    applyStep(current, n, RejectAny, DispatchNoEvent, exceptionState);
 }
 
 void InputType::stepUpFromRenderer(int n)
 {
-    // The differences from stepUp()/stepDown():
+    // The only difference from stepUp()/stepDown() is the extra treatment
+    // of the current value before applying the step:
     //
-    // Difference 1: the current value
     // If the current value is not a number, including empty, the current value is assumed as 0.
     //   * If 0 is in-range, and matches to step value
     //     - The value should be the +step if n > 0
@@ -888,13 +901,6 @@ void InputType::stepUpFromRenderer(int n)
     //  - The value should be the maximum value if n < 0
     //  - Nothing should happen if n > 0
     //
-    // Difference 2: clamping steps
-    // If the current value is not matched to step value:
-    // - The value should be the larger matched value nearest to 0 if n > 0
-    //   e.g. <input type=number value=3 min=-100 step=3> -> 5
-    // - The value should be the smaler matched value nearest to 0 if n < 0
-    //   e.g. <input type=number value=3 min=-100 step=3> -> 2
-    //
     // n is assumed as -n if step < 0.
 
     ASSERT(isSteppable());
@@ -922,8 +928,7 @@ void InputType::stepUpFromRenderer(int n)
     else
         sign = 0;
 
-    String currentStringValue = element().value();
-    Decimal current = parseToNumberOrNaN(currentStringValue);
+    Decimal current = parseToNumberOrNaN(element().value());
     if (!current.isFinite()) {
         current = defaultValueForStepUp();
         const Decimal nextDiff = step * n;
@@ -934,33 +939,10 @@ void InputType::stepUpFromRenderer(int n)
         setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION);
     }
     if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) {
-        setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION);
-    } else {
-        if (stepMismatch(element().value())) {
-            ASSERT(!step.isZero());
-            const Decimal base = stepRange.stepBase();
-            Decimal newValue;
-            if (sign < 0)
-                newValue = base + ((current - base) / step).floor() * step;
-            else if (sign > 0)
-                newValue = base + ((current - base) / step).ceiling() * step;
-            else
-                newValue = current;
-
-            if (newValue < stepRange.minimum())
-                newValue = stepRange.minimum();
-            if (newValue > stepRange.maximum())
-                newValue = stepRange.maximum();
-
-            setValueAsDecimal(newValue, n == 1 || n == -1 ? DispatchChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION);
-            if (n > 1)
-                applyStep(n - 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
-            else if (n < -1)
-                applyStep(n + 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
-        } else {
-            applyStep(n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
-        }
+        setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
+        return;
     }
+    applyStep(current, n, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
 }
 
 void InputType::countUsageIfVisible(UseCounter::Feature feature) const