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 const Decimal step = stepRange.step(); |
806 if (!current.isFinite()) { | 806 const AtomicString& stepString = element().fastGetAttribute(stepAttr); |
807 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::n otAFiniteNumber(current, "form element's current value")); | 807 if (!equalIgnoringCase(stepString, "any") && stepRange.stepMismatch(current) ) { |
808 return; | 808 // Snap-to-step / clamping steps |
809 // If the current value is not matched to step value: | |
810 // - The value should be the larger matched value nearest to 0 if count > 0 | |
811 // e.g. <input type=number value=3 min=-100 step=3> -> 5 | |
812 // - The value should be the smaller matched value nearest to 0 if count < 0 | |
813 // e.g. <input type=number value=3 min=-100 step=3> -> 2 | |
814 // | |
815 | |
816 ASSERT(!step.isZero()); | |
817 Decimal newValue; | |
818 const Decimal base = stepRange.stepBase(); | |
819 if (count < 0) | |
820 newValue = base + ((current - base) / step).floor() * step; | |
821 else if (count > 0) | |
822 newValue = base + ((current - base) / step).ceiling() * step; | |
823 else | |
824 newValue = current; | |
825 | |
826 if (newValue < stepRange.minimum()) | |
827 newValue = stepRange.minimum(); | |
828 if (newValue > stepRange.maximum()) | |
829 newValue = stepRange.maximum(); | |
830 | |
831 setValueAsDecimal(newValue, count == 1 || count == -1 ? DispatchChangeEv ent : DispatchNoEvent, IGNORE_EXCEPTION); | |
832 if (count > 1) { | |
833 applyStep(newValue, count - 1, AnyIsDefaultStep, DispatchChangeEvent , IGNORE_EXCEPTION); | |
tkent
2014/02/05 08:33:24
Please add EventQueueScope in this function.
setVa
sof
2014/02/05 08:42:51
Thanks, done.
| |
834 return; | |
835 } | |
836 if (count < -1) { | |
837 applyStep(newValue, count + 1, AnyIsDefaultStep, DispatchChangeEvent , IGNORE_EXCEPTION); | |
838 return; | |
839 } | |
840 } else { | |
841 Decimal newValue = current + stepRange.step() * count; | |
842 | |
843 if (!equalIgnoringCase(stepString, "any")) | |
844 newValue = stepRange.alignValueForStep(current, newValue); | |
845 | |
846 if (newValue > stepRange.maximum()) | |
847 newValue = newValue - stepRange.step(); | |
848 else if (newValue < stepRange.minimum()) | |
849 newValue = newValue + stepRange.step(); | |
850 | |
851 setValueAsDecimal(newValue, eventBehavior, exceptionState); | |
809 } | 852 } |
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 | |
824 const AtomicString& stepString = element().fastGetAttribute(stepAttr); | |
825 if (!equalIgnoringCase(stepString, "any")) | |
826 newValue = stepRange.alignValueForStep(current, newValue); | |
827 | |
828 if (newValue - stepRange.maximum() > acceptableErrorValue) { | |
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."); | |
830 return; | |
831 } | |
832 if (newValue > stepRange.maximum()) | |
833 newValue = stepRange.maximum(); | |
834 | |
835 setValueAsDecimal(newValue, eventBehavior, exceptionState); | |
836 | |
837 if (AXObjectCache* cache = element().document().existingAXObjectCache()) | 853 if (AXObjectCache* cache = element().document().existingAXObjectCache()) |
838 cache->postNotification(&element(), AXObjectCache::AXValueChanged, true) ; | 854 cache->postNotification(&element(), AXObjectCache::AXValueChanged, true) ; |
839 } | 855 } |
840 | 856 |
841 bool InputType::getAllowedValueStep(Decimal* step) const | 857 bool InputType::getAllowedValueStep(Decimal* step) const |
842 { | 858 { |
843 StepRange stepRange(createStepRange(RejectAny)); | 859 StepRange stepRange(createStepRange(RejectAny)); |
844 *step = stepRange.step(); | 860 *step = stepRange.step(); |
845 return stepRange.hasStep(); | 861 return stepRange.hasStep(); |
846 } | 862 } |
847 | 863 |
848 StepRange InputType::createStepRange(AnyStepHandling) const | 864 StepRange InputType::createStepRange(AnyStepHandling) const |
849 { | 865 { |
850 ASSERT_NOT_REACHED(); | 866 ASSERT_NOT_REACHED(); |
851 return StepRange(); | 867 return StepRange(); |
852 } | 868 } |
853 | 869 |
854 void InputType::stepUp(int n, ExceptionState& exceptionState) | 870 void InputType::stepUp(int n, ExceptionState& exceptionState) |
855 { | 871 { |
856 if (!isSteppable()) { | 872 if (!isSteppable()) { |
857 exceptionState.throwDOMException(InvalidStateError, "This form element i s not steppable."); | 873 exceptionState.throwDOMException(InvalidStateError, "This form element i s not steppable."); |
858 return; | 874 return; |
859 } | 875 } |
860 applyStep(n, RejectAny, DispatchNoEvent, exceptionState); | 876 const Decimal current = parseToNumber(element().value(), 0); |
877 applyStep(current, n, RejectAny, DispatchNoEvent, exceptionState); | |
861 } | 878 } |
862 | 879 |
863 void InputType::stepUpFromRenderer(int n) | 880 void InputType::stepUpFromRenderer(int n) |
864 { | 881 { |
865 // The differences from stepUp()/stepDown(): | 882 // The only difference from stepUp()/stepDown() is the extra treatment |
883 // of the current value before applying the step: | |
866 // | 884 // |
867 // Difference 1: the current value | |
868 // If the current value is not a number, including empty, the current value is assumed as 0. | 885 // 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 | 886 // * If 0 is in-range, and matches to step value |
870 // - The value should be the +step if n > 0 | 887 // - The value should be the +step if n > 0 |
871 // - The value should be the -step if n < 0 | 888 // - The value should be the -step if n < 0 |
872 // If -step or +step is out of range, new value should be 0. | 889 // If -step or +step is out of range, new value should be 0. |
873 // * If 0 is smaller than the minimum value | 890 // * If 0 is smaller than the minimum value |
874 // - The value should be the minimum value for any n | 891 // - The value should be the minimum value for any n |
875 // * If 0 is larger than the maximum value | 892 // * If 0 is larger than the maximum value |
876 // - The value should be the maximum value for any n | 893 // - The value should be the maximum value for any n |
877 // * If 0 is in-range, but not matched to step value | 894 // * 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 | 895 // - 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 | 896 // 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 | 897 // - 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 | 898 // 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". | 899 // 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". | 900 // 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: | 901 // If the current value is smaller than the minimum value: |
885 // - The value should be the minimum value if n > 0 | 902 // - The value should be the minimum value if n > 0 |
886 // - Nothing should happen if n < 0 | 903 // - Nothing should happen if n < 0 |
887 // If the current value is larger than the maximum value: | 904 // If the current value is larger than the maximum value: |
888 // - The value should be the maximum value if n < 0 | 905 // - The value should be the maximum value if n < 0 |
889 // - Nothing should happen if n > 0 | 906 // - Nothing should happen if n > 0 |
890 // | 907 // |
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. | 908 // n is assumed as -n if step < 0. |
899 | 909 |
900 ASSERT(isSteppable()); | 910 ASSERT(isSteppable()); |
901 if (!isSteppable()) | 911 if (!isSteppable()) |
902 return; | 912 return; |
903 ASSERT(n); | 913 ASSERT(n); |
904 if (!n) | 914 if (!n) |
905 return; | 915 return; |
906 | 916 |
907 StepRange stepRange(createStepRange(AnyIsDefaultStep)); | 917 StepRange stepRange(createStepRange(AnyIsDefaultStep)); |
908 | 918 |
909 // FIXME: Not any changes after stepping, even if it is an invalid value, ma y be better. | 919 // 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") | 920 // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => " foo") |
911 if (!stepRange.hasStep()) | 921 if (!stepRange.hasStep()) |
912 return; | 922 return; |
913 | 923 |
914 EventQueueScope scope; | 924 EventQueueScope scope; |
915 const Decimal step = stepRange.step(); | 925 const Decimal step = stepRange.step(); |
916 | 926 |
917 int sign; | 927 int sign; |
918 if (step > 0) | 928 if (step > 0) |
919 sign = n; | 929 sign = n; |
920 else if (step < 0) | 930 else if (step < 0) |
921 sign = -n; | 931 sign = -n; |
922 else | 932 else |
923 sign = 0; | 933 sign = 0; |
924 | 934 |
925 String currentStringValue = element().value(); | 935 Decimal current = parseToNumberOrNaN(element().value()); |
926 Decimal current = parseToNumberOrNaN(currentStringValue); | |
927 if (!current.isFinite()) { | 936 if (!current.isFinite()) { |
928 current = defaultValueForStepUp(); | 937 current = defaultValueForStepUp(); |
929 const Decimal nextDiff = step * n; | 938 const Decimal nextDiff = step * n; |
930 if (current < stepRange.minimum() - nextDiff) | 939 if (current < stepRange.minimum() - nextDiff) |
931 current = stepRange.minimum() - nextDiff; | 940 current = stepRange.minimum() - nextDiff; |
932 if (current > stepRange.maximum() - nextDiff) | 941 if (current > stepRange.maximum() - nextDiff) |
933 current = stepRange.maximum() - nextDiff; | 942 current = stepRange.maximum() - nextDiff; |
934 setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); | 943 setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); |
935 } | 944 } |
936 if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > st epRange.maximum())) { | 945 if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > st epRange.maximum())) { |
937 setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION); | 946 setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION); |
938 } else { | 947 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 } | 948 } |
949 applyStep(current, n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTIO N); | |
964 } | 950 } |
965 | 951 |
966 void InputType::countUsageIfVisible(UseCounter::Feature feature) const | 952 void InputType::countUsageIfVisible(UseCounter::Feature feature) const |
967 { | 953 { |
968 if (RenderStyle* style = element().renderStyle()) { | 954 if (RenderStyle* style = element().renderStyle()) { |
969 if (style->visibility() != HIDDEN) | 955 if (style->visibility() != HIDDEN) |
970 UseCounter::count(element().document(), feature); | 956 UseCounter::count(element().document(), feature); |
971 } | 957 } |
972 } | 958 } |
973 | 959 |
974 Decimal InputType::findStepBase(const Decimal& defaultValue) const | 960 Decimal InputType::findStepBase(const Decimal& defaultValue) const |
975 { | 961 { |
976 Decimal stepBase = parseToNumber(element().fastGetAttribute(minAttr), Decima l::nan()); | 962 Decimal stepBase = parseToNumber(element().fastGetAttribute(minAttr), Decima l::nan()); |
977 if (!stepBase.isFinite()) | 963 if (!stepBase.isFinite()) |
978 stepBase = parseToNumber(element().fastGetAttribute(valueAttr), defaultV alue); | 964 stepBase = parseToNumber(element().fastGetAttribute(valueAttr), defaultV alue); |
979 return stepBase; | 965 return stepBase; |
980 } | 966 } |
981 | 967 |
982 StepRange InputType::createStepRange(AnyStepHandling anyStepHandling, const Deci mal& stepBaseDefault, const Decimal& minimumDefault, const Decimal& maximumDefau lt, const StepRange::StepDescription& stepDescription) const | 968 StepRange InputType::createStepRange(AnyStepHandling anyStepHandling, const Deci mal& stepBaseDefault, const Decimal& minimumDefault, const Decimal& maximumDefau lt, const StepRange::StepDescription& stepDescription) const |
983 { | 969 { |
984 const Decimal stepBase = findStepBase(stepBaseDefault); | 970 const Decimal stepBase = findStepBase(stepBaseDefault); |
985 const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), m inimumDefault); | 971 const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), m inimumDefault); |
986 const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), m aximumDefault); | 972 const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), m aximumDefault); |
987 const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr)); | 973 const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr)); |
988 return StepRange(stepBase, minimum, maximum, step, stepDescription); | 974 return StepRange(stepBase, minimum, maximum, step, stepDescription); |
989 } | 975 } |
990 | 976 |
991 } // namespace WebCore | 977 } // namespace WebCore |
OLD | NEW |