| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. |
| 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) | 7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) |
| 8 * Copyright (C) 2009, 2010, 2011, 2012 Google Inc. All rights reserved. | 8 * Copyright (C) 2009, 2010, 2011, 2012 Google Inc. All rights reserved. |
| 9 * Copyright (C) 2012 Samsung Electronics. All rights reserved. | 9 * Copyright (C) 2012 Samsung Electronics. All rights reserved. |
| 10 * | 10 * |
| (...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 unsigned InputType::height() const | 787 unsigned InputType::height() const |
| 788 { | 788 { |
| 789 return 0; | 789 return 0; |
| 790 } | 790 } |
| 791 | 791 |
| 792 unsigned InputType::width() const | 792 unsigned InputType::width() const |
| 793 { | 793 { |
| 794 return 0; | 794 return 0; |
| 795 } | 795 } |
| 796 | 796 |
| 797 void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldE
ventBehavior eventBehavior, ExceptionState& exceptionState) | 797 void InputType::applyStep(const Decimal& current, int count, AnyStepHandling any
StepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionSta
te) |
| 798 { | 798 { |
| 799 StepRange stepRange(createStepRange(anyStepHandling)); | 799 StepRange stepRange(createStepRange(anyStepHandling)); |
| 800 if (!stepRange.hasStep()) { | 800 if (!stepRange.hasStep()) { |
| 801 exceptionState.throwDOMException(InvalidStateError, "This form element d
oes not have an allowed value step."); | 801 exceptionState.throwDOMException(InvalidStateError, "This form element d
oes not have an allowed value step."); |
| 802 return; | 802 return; |
| 803 } | 803 } |
| 804 | 804 |
| 805 const Decimal current = parseToNumberOrNaN(element().value()); | 805 EventQueueScope scope; |
| 806 if (!current.isFinite()) { | 806 const Decimal step = stepRange.step(); |
| 807 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::n
otAFiniteNumber(current, "form element's current value")); | |
| 808 return; | |
| 809 } | |
| 810 Decimal newValue = current + stepRange.step() * count; | |
| 811 if (!newValue.isFinite()) { | |
| 812 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::n
otAFiniteNumber(newValue, "form element's new value")); | |
| 813 return; | |
| 814 } | |
| 815 | |
| 816 const Decimal acceptableErrorValue = stepRange.acceptableError(); | |
| 817 if (newValue - stepRange.minimum() < -acceptableErrorValue) { | |
| 818 exceptionState.throwDOMException(InvalidStateError, "The form element's
new value (" + newValue.toString() + ") would be lower than the minimum (" + ste
pRange.minimum().toString() + "), and snapping to the minimum would exceed the a
mount of acceptible error."); | |
| 819 return; | |
| 820 } | |
| 821 if (newValue < stepRange.minimum()) | |
| 822 newValue = stepRange.minimum(); | |
| 823 | 807 |
| 824 const AtomicString& stepString = element().fastGetAttribute(stepAttr); | 808 const AtomicString& stepString = element().fastGetAttribute(stepAttr); |
| 825 if (!equalIgnoringCase(stepString, "any")) | 809 if (!equalIgnoringCase(stepString, "any") && stepRange.stepMismatch(current)
) { |
| 826 newValue = stepRange.alignValueForStep(current, newValue); | 810 // Snap-to-step / clamping steps |
| 811 // If the current value is not matched to step value: |
| 812 // - The value should be the larger matched value nearest to 0 if count
> 0 |
| 813 // e.g. <input type=number value=3 min=-100 step=3> -> 5 |
| 814 // - The value should be the smaller matched value nearest to 0 if count
< 0 |
| 815 // e.g. <input type=number value=3 min=-100 step=3> -> 2 |
| 816 // |
| 827 | 817 |
| 828 if (newValue - stepRange.maximum() > acceptableErrorValue) { | 818 ASSERT(!step.isZero()); |
| 829 exceptionState.throwDOMException(InvalidStateError, "The form element's
new value (" + newValue.toString() + ") would be higher than the maximum (" + st
epRange.maximum().toString() + "), and snapping to the maximum would exceed the
amount of acceptible error."); | 819 Decimal newValue; |
| 830 return; | 820 const Decimal base = stepRange.stepBase(); |
| 821 if (count < 0) |
| 822 newValue = base + ((current - base) / step).floor() * step; |
| 823 else if (count > 0) |
| 824 newValue = base + ((current - base) / step).ceiling() * step; |
| 825 else |
| 826 newValue = current; |
| 827 |
| 828 if (newValue < stepRange.minimum()) |
| 829 newValue = stepRange.minimum(); |
| 830 if (newValue > stepRange.maximum()) |
| 831 newValue = stepRange.maximum(); |
| 832 |
| 833 setValueAsDecimal(newValue, count == 1 || count == -1 ? DispatchChangeEv
ent : DispatchNoEvent, IGNORE_EXCEPTION); |
| 834 if (count > 1) { |
| 835 applyStep(newValue, count - 1, AnyIsDefaultStep, DispatchChangeEvent
, IGNORE_EXCEPTION); |
| 836 return; |
| 837 } |
| 838 if (count < -1) { |
| 839 applyStep(newValue, count + 1, AnyIsDefaultStep, DispatchChangeEvent
, IGNORE_EXCEPTION); |
| 840 return; |
| 841 } |
| 842 } else { |
| 843 Decimal newValue = current + stepRange.step() * count; |
| 844 |
| 845 if (!equalIgnoringCase(stepString, "any")) |
| 846 newValue = stepRange.alignValueForStep(current, newValue); |
| 847 |
| 848 if (newValue > stepRange.maximum()) |
| 849 newValue = newValue - stepRange.step(); |
| 850 else if (newValue < stepRange.minimum()) |
| 851 newValue = newValue + stepRange.step(); |
| 852 |
| 853 setValueAsDecimal(newValue, eventBehavior, exceptionState); |
| 831 } | 854 } |
| 832 if (newValue > stepRange.maximum()) | |
| 833 newValue = stepRange.maximum(); | |
| 834 | |
| 835 setValueAsDecimal(newValue, eventBehavior, exceptionState); | |
| 836 | |
| 837 if (AXObjectCache* cache = element().document().existingAXObjectCache()) | 855 if (AXObjectCache* cache = element().document().existingAXObjectCache()) |
| 838 cache->postNotification(&element(), AXObjectCache::AXValueChanged, true)
; | 856 cache->postNotification(&element(), AXObjectCache::AXValueChanged, true)
; |
| 839 } | 857 } |
| 840 | 858 |
| 841 bool InputType::getAllowedValueStep(Decimal* step) const | 859 bool InputType::getAllowedValueStep(Decimal* step) const |
| 842 { | 860 { |
| 843 StepRange stepRange(createStepRange(RejectAny)); | 861 StepRange stepRange(createStepRange(RejectAny)); |
| 844 *step = stepRange.step(); | 862 *step = stepRange.step(); |
| 845 return stepRange.hasStep(); | 863 return stepRange.hasStep(); |
| 846 } | 864 } |
| 847 | 865 |
| 848 StepRange InputType::createStepRange(AnyStepHandling) const | 866 StepRange InputType::createStepRange(AnyStepHandling) const |
| 849 { | 867 { |
| 850 ASSERT_NOT_REACHED(); | 868 ASSERT_NOT_REACHED(); |
| 851 return StepRange(); | 869 return StepRange(); |
| 852 } | 870 } |
| 853 | 871 |
| 854 void InputType::stepUp(int n, ExceptionState& exceptionState) | 872 void InputType::stepUp(int n, ExceptionState& exceptionState) |
| 855 { | 873 { |
| 856 if (!isSteppable()) { | 874 if (!isSteppable()) { |
| 857 exceptionState.throwDOMException(InvalidStateError, "This form element i
s not steppable."); | 875 exceptionState.throwDOMException(InvalidStateError, "This form element i
s not steppable."); |
| 858 return; | 876 return; |
| 859 } | 877 } |
| 860 applyStep(n, RejectAny, DispatchNoEvent, exceptionState); | 878 const Decimal current = parseToNumber(element().value(), 0); |
| 879 applyStep(current, n, RejectAny, DispatchNoEvent, exceptionState); |
| 861 } | 880 } |
| 862 | 881 |
| 863 void InputType::stepUpFromRenderer(int n) | 882 void InputType::stepUpFromRenderer(int n) |
| 864 { | 883 { |
| 865 // The differences from stepUp()/stepDown(): | 884 // The only difference from stepUp()/stepDown() is the extra treatment |
| 885 // of the current value before applying the step: |
| 866 // | 886 // |
| 867 // Difference 1: the current value | |
| 868 // If the current value is not a number, including empty, the current value
is assumed as 0. | 887 // If the current value is not a number, including empty, the current value
is assumed as 0. |
| 869 // * If 0 is in-range, and matches to step value | 888 // * If 0 is in-range, and matches to step value |
| 870 // - The value should be the +step if n > 0 | 889 // - The value should be the +step if n > 0 |
| 871 // - The value should be the -step if n < 0 | 890 // - The value should be the -step if n < 0 |
| 872 // If -step or +step is out of range, new value should be 0. | 891 // If -step or +step is out of range, new value should be 0. |
| 873 // * If 0 is smaller than the minimum value | 892 // * If 0 is smaller than the minimum value |
| 874 // - The value should be the minimum value for any n | 893 // - The value should be the minimum value for any n |
| 875 // * If 0 is larger than the maximum value | 894 // * If 0 is larger than the maximum value |
| 876 // - The value should be the maximum value for any n | 895 // - The value should be the maximum value for any n |
| 877 // * If 0 is in-range, but not matched to step value | 896 // * If 0 is in-range, but not matched to step value |
| 878 // - The value should be the larger matched value nearest to 0 if n > 0 | 897 // - The value should be the larger matched value nearest to 0 if n > 0 |
| 879 // e.g. <input type=number min=-100 step=3> -> 2 | 898 // e.g. <input type=number min=-100 step=3> -> 2 |
| 880 // - The value should be the smaler matched value nearest to 0 if n < 0 | 899 // - The value should be the smaler matched value nearest to 0 if n < 0 |
| 881 // e.g. <input type=number min=-100 step=3> -> -1 | 900 // e.g. <input type=number min=-100 step=3> -> -1 |
| 882 // As for date/datetime-local/month/time/week types, the current value is
assumed as "the current local date/time". | 901 // As for date/datetime-local/month/time/week types, the current value is
assumed as "the current local date/time". |
| 883 // As for datetime type, the current value is assumed as "the current date
/time in UTC". | 902 // As for datetime type, the current value is assumed as "the current date
/time in UTC". |
| 884 // If the current value is smaller than the minimum value: | 903 // If the current value is smaller than the minimum value: |
| 885 // - The value should be the minimum value if n > 0 | 904 // - The value should be the minimum value if n > 0 |
| 886 // - Nothing should happen if n < 0 | 905 // - Nothing should happen if n < 0 |
| 887 // If the current value is larger than the maximum value: | 906 // If the current value is larger than the maximum value: |
| 888 // - The value should be the maximum value if n < 0 | 907 // - The value should be the maximum value if n < 0 |
| 889 // - Nothing should happen if n > 0 | 908 // - Nothing should happen if n > 0 |
| 890 // | 909 // |
| 891 // Difference 2: clamping steps | |
| 892 // If the current value is not matched to step value: | |
| 893 // - The value should be the larger matched value nearest to 0 if n > 0 | |
| 894 // e.g. <input type=number value=3 min=-100 step=3> -> 5 | |
| 895 // - The value should be the smaler matched value nearest to 0 if n < 0 | |
| 896 // e.g. <input type=number value=3 min=-100 step=3> -> 2 | |
| 897 // | |
| 898 // n is assumed as -n if step < 0. | 910 // n is assumed as -n if step < 0. |
| 899 | 911 |
| 900 ASSERT(isSteppable()); | 912 ASSERT(isSteppable()); |
| 901 if (!isSteppable()) | 913 if (!isSteppable()) |
| 902 return; | 914 return; |
| 903 ASSERT(n); | 915 ASSERT(n); |
| 904 if (!n) | 916 if (!n) |
| 905 return; | 917 return; |
| 906 | 918 |
| 907 StepRange stepRange(createStepRange(AnyIsDefaultStep)); | 919 StepRange stepRange(createStepRange(AnyIsDefaultStep)); |
| 908 | 920 |
| 909 // FIXME: Not any changes after stepping, even if it is an invalid value, ma
y be better. | 921 // FIXME: Not any changes after stepping, even if it is an invalid value, ma
y be better. |
| 910 // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "
foo") | 922 // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "
foo") |
| 911 if (!stepRange.hasStep()) | 923 if (!stepRange.hasStep()) |
| 912 return; | 924 return; |
| 913 | 925 |
| 914 EventQueueScope scope; | 926 EventQueueScope scope; |
| 915 const Decimal step = stepRange.step(); | 927 const Decimal step = stepRange.step(); |
| 916 | 928 |
| 917 int sign; | 929 int sign; |
| 918 if (step > 0) | 930 if (step > 0) |
| 919 sign = n; | 931 sign = n; |
| 920 else if (step < 0) | 932 else if (step < 0) |
| 921 sign = -n; | 933 sign = -n; |
| 922 else | 934 else |
| 923 sign = 0; | 935 sign = 0; |
| 924 | 936 |
| 925 String currentStringValue = element().value(); | 937 Decimal current = parseToNumberOrNaN(element().value()); |
| 926 Decimal current = parseToNumberOrNaN(currentStringValue); | |
| 927 if (!current.isFinite()) { | 938 if (!current.isFinite()) { |
| 928 current = defaultValueForStepUp(); | 939 current = defaultValueForStepUp(); |
| 929 const Decimal nextDiff = step * n; | 940 const Decimal nextDiff = step * n; |
| 930 if (current < stepRange.minimum() - nextDiff) | 941 if (current < stepRange.minimum() - nextDiff) |
| 931 current = stepRange.minimum() - nextDiff; | 942 current = stepRange.minimum() - nextDiff; |
| 932 if (current > stepRange.maximum() - nextDiff) | 943 if (current > stepRange.maximum() - nextDiff) |
| 933 current = stepRange.maximum() - nextDiff; | 944 current = stepRange.maximum() - nextDiff; |
| 934 setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); | 945 setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); |
| 935 } | 946 } |
| 936 if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > st
epRange.maximum())) { | 947 if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > st
epRange.maximum())) { |
| 937 setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(),
DispatchChangeEvent, IGNORE_EXCEPTION); | 948 setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(),
DispatchChangeEvent, IGNORE_EXCEPTION); |
| 938 } else { | 949 return; |
| 939 if (stepMismatch(element().value())) { | |
| 940 ASSERT(!step.isZero()); | |
| 941 const Decimal base = stepRange.stepBase(); | |
| 942 Decimal newValue; | |
| 943 if (sign < 0) | |
| 944 newValue = base + ((current - base) / step).floor() * step; | |
| 945 else if (sign > 0) | |
| 946 newValue = base + ((current - base) / step).ceiling() * step; | |
| 947 else | |
| 948 newValue = current; | |
| 949 | |
| 950 if (newValue < stepRange.minimum()) | |
| 951 newValue = stepRange.minimum(); | |
| 952 if (newValue > stepRange.maximum()) | |
| 953 newValue = stepRange.maximum(); | |
| 954 | |
| 955 setValueAsDecimal(newValue, n == 1 || n == -1 ? DispatchChangeEvent
: DispatchNoEvent, IGNORE_EXCEPTION); | |
| 956 if (n > 1) | |
| 957 applyStep(n - 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_E
XCEPTION); | |
| 958 else if (n < -1) | |
| 959 applyStep(n + 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_E
XCEPTION); | |
| 960 } else { | |
| 961 applyStep(n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION
); | |
| 962 } | |
| 963 } | 950 } |
| 951 applyStep(current, n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTIO
N); |
| 964 } | 952 } |
| 965 | 953 |
| 966 void InputType::countUsageIfVisible(UseCounter::Feature feature) const | 954 void InputType::countUsageIfVisible(UseCounter::Feature feature) const |
| 967 { | 955 { |
| 968 if (RenderStyle* style = element().renderStyle()) { | 956 if (RenderStyle* style = element().renderStyle()) { |
| 969 if (style->visibility() != HIDDEN) | 957 if (style->visibility() != HIDDEN) |
| 970 UseCounter::count(element().document(), feature); | 958 UseCounter::count(element().document(), feature); |
| 971 } | 959 } |
| 972 } | 960 } |
| 973 | 961 |
| 974 Decimal InputType::findStepBase(const Decimal& defaultValue) const | 962 Decimal InputType::findStepBase(const Decimal& defaultValue) const |
| 975 { | 963 { |
| 976 Decimal stepBase = parseToNumber(element().fastGetAttribute(minAttr), Decima
l::nan()); | 964 Decimal stepBase = parseToNumber(element().fastGetAttribute(minAttr), Decima
l::nan()); |
| 977 if (!stepBase.isFinite()) | 965 if (!stepBase.isFinite()) |
| 978 stepBase = parseToNumber(element().fastGetAttribute(valueAttr), defaultV
alue); | 966 stepBase = parseToNumber(element().fastGetAttribute(valueAttr), defaultV
alue); |
| 979 return stepBase; | 967 return stepBase; |
| 980 } | 968 } |
| 981 | 969 |
| 982 StepRange InputType::createStepRange(AnyStepHandling anyStepHandling, const Deci
mal& stepBaseDefault, const Decimal& minimumDefault, const Decimal& maximumDefau
lt, const StepRange::StepDescription& stepDescription) const | 970 StepRange InputType::createStepRange(AnyStepHandling anyStepHandling, const Deci
mal& stepBaseDefault, const Decimal& minimumDefault, const Decimal& maximumDefau
lt, const StepRange::StepDescription& stepDescription) const |
| 983 { | 971 { |
| 984 const Decimal stepBase = findStepBase(stepBaseDefault); | 972 const Decimal stepBase = findStepBase(stepBaseDefault); |
| 985 const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), m
inimumDefault); | 973 const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), m
inimumDefault); |
| 986 const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), m
aximumDefault); | 974 const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), m
aximumDefault); |
| 987 const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription,
element().fastGetAttribute(stepAttr)); | 975 const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription,
element().fastGetAttribute(stepAttr)); |
| 988 return StepRange(stepBase, minimum, maximum, step, stepDescription); | 976 return StepRange(stepBase, minimum, maximum, step, stepDescription); |
| 989 } | 977 } |
| 990 | 978 |
| 991 } // namespace WebCore | 979 } // namespace WebCore |
| OLD | NEW |