Title: [137561] trunk
Revision
137561
Author
commit-qu...@webkit.org
Date
2012-12-12 19:02:04 -0800 (Wed, 12 Dec 2012)

Log Message

Milliseconds field of date/time input UI should respect step attribute
https://bugs.webkit.org/show_bug.cgi?id=104628

Patch by Kunihiko Sakamoto <ksakam...@chromium.org> on 2012-12-12
Reviewed by Kent Tamura.

Source/WebCore:

This patch makes step-up/-down UI of the milliseconds fields respect step attribute
in a special case when the step is divisible by 1000 milliseconds.

Test: fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html

* html/shadow/DateTimeEditElement.cpp:
(WebCore::DateTimeEditBuilder::visitField):
If step of the element (in milliseconds) is divisible by 1000, use it as the step of the milliseconds field. Otherwise, the millisecond field has step 1.
* html/shadow/DateTimeFieldElements.cpp:
(WebCore::DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement): Add step and stepBase arguments.
(WebCore::DateTimeMillisecondFieldElement::create): Ditto.
* html/shadow/DateTimeFieldElements.h:
(DateTimeMillisecondFieldElement): Ditto.
* html/shadow/DateTimeNumericFieldElement.cpp:
(WebCore::DateTimeNumericFieldElement::DateTimeNumericFieldElement): Ditto.
(WebCore::DateTimeNumericFieldElement::stepDown): Changed to compute next allowed value using roundDown().
(WebCore::DateTimeNumericFieldElement::stepUp): Changed to compute next allowed value using roundUp().
(WebCore::DateTimeNumericFieldElement::roundDown): Added.
(WebCore::DateTimeNumericFieldElement::roundUp): Added.
* html/shadow/DateTimeNumericFieldElement.h:
(DateTimeNumericFieldElement): Add m_step and m_stepBase fields.

LayoutTests:

* fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-expected.txt:
* fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html:
Changed to use eventSender.keyDown() instead of making keydown event because we need delete-key handling.
Added new helper function test() and changed stepUp/stepDown to use it.
Added test cases for milliseconds field with various step values and step baees.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (137560 => 137561)


--- trunk/LayoutTests/ChangeLog	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/LayoutTests/ChangeLog	2012-12-13 03:02:04 UTC (rev 137561)
@@ -1,3 +1,16 @@
+2012-12-12  Kunihiko Sakamoto  <ksakam...@chromium.org>
+
+        Milliseconds field of date/time input UI should respect step attribute
+        https://bugs.webkit.org/show_bug.cgi?id=104628
+
+        Reviewed by Kent Tamura.
+
+        * fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-expected.txt:
+        * fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html:
+        Changed to use eventSender.keyDown() instead of making keydown event because we need delete-key handling.
+        Added new helper function test() and changed stepUp/stepDown to use it.
+        Added test cases for milliseconds field with various step values and step baees.
+
 2012-12-12  Julien Chaffraix  <jchaffr...@webkit.org>
 
         [CSS Grid Layout] Include paddings and borders into the grid element's logical height / width

Modified: trunk/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-expected.txt (137560 => 137561)


--- trunk/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-expected.txt	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-expected.txt	2012-12-13 03:02:04 UTC (rev 137561)
@@ -3,12 +3,33 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-Function arguments are (value, step, {min or max}, [stepCount]).
+Function arguments are (value, step, min, max, [keySequence]).
 Normal cases
-PASS stepUp("07:13", null, null) is "07:14"
-PASS stepDown("07:13", null, null) is "07:12"
-PASS stepUp("07:13", null, null, 10) is "07:23"
-PASS stepDown("07:13", null, null, 11) is "07:02"
+PASS stepUp("07:13", null, null, null) is "07:14"
+PASS stepDown("07:13", null, null, null) is "07:12"
+PASS test("07:13", null, null, null, ["upArrow", "upArrow", "upArrow"]) is "07:16"
+PASS test("07:13", null, null, null, ["downArrow", "downArrow", "downArrow"]) is "07:10"
+Milliseconds
+PASS stepUp("07:13:00.000", 0.001, null, null) is "07:13:00.001"
+PASS stepDown("07:13:00.001", 0.001, null, null) is "07:13"
+PASS stepUp("07:13:00.999", 0.001, null, null) is "07:13"
+PASS stepDown("07:13:00.000", 0.001, null, null) is "07:13:00.999"
+PASS stepUp("07:13:00.000", 0.250, null, null) is "07:13:00.250"
+PASS stepDown("07:13:00.500", 0.250, null, null) is "07:13:00.250"
+PASS stepUp("07:13:00.750", 0.250, null, null) is "07:13"
+PASS stepDown("07:13:00.000", 0.250, null, null) is "07:13:00.750"
+PASS stepUp("07:13:00.099", 0.100, null, null) is "07:13:00.100"
+PASS stepDown("07:13:00.101", 0.100, null, null) is "07:13:00.100"
+PASS stepUp("07:13:00.500", 0.0001, null, null) is "07:13:00.501"
+PASS stepDown("07:13:00.500", 0.0001, null, null) is "07:13:00.499"
+PASS stepUp("07:13:00.500", 0, null, null) is "07:13:00.501"
+PASS stepDown("07:13:00.500", 0, null, null) is "07:13:00.499"
+PASS stepUp("07:13:00.500", 0.100, "00:00:00.050", null) is "07:13:00.550"
+PASS stepDown("07:13:00.500", 0.100, "00:00:00.050", null) is "07:13:00.450"
+PASS test("07:13:00.500", 0.100, null, null, ["delete", "upArrow"]) is "07:13"
+PASS test("07:13:00.500", 0.100, null, null, ["delete", "downArrow"]) is "07:13:00.900"
+PASS test("07:13:00.500", 0.100, "00:00:00.050", null, ["delete", "upArrow"]) is "07:13:00.050"
+PASS test("07:13:00.500", 0.100, "00:00:00.050", null, ["delete", "downArrow"]) is "07:13:00.950"
 
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html (137560 => 137561)


--- trunk/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html	2012-12-13 03:02:04 UTC (rev 137561)
@@ -12,10 +12,11 @@
 
 document.body.appendChild(input);
 
-function sendKey(keyName) {
-    var event = document.createEvent('KeyboardEvent');
-    event.initKeyboardEvent('keydown', true, true, document.defaultView, keyName);
-    input.dispatchEvent(event);
+function keyDown(key, modifiers)
+{
+    if (!window.eventSender)
+        return;
+    eventSender.keyDown(key, modifiers);
 }
 
 function setInputAttributes(min, max, step, value) {
@@ -25,43 +26,56 @@
     input.value = value;
 }
 
-function stepUp(value, step, max, optionalStepCount) {
-    setInputAttributes(null, max, step, value);
-    if (typeof optionalStepCount != "undefined")
-        if (optionalStepCount < 0)
-            for (var i = 0; i < -optionalStepCount; i++)
-                sendKey('Down');
-        else
-            for (var i = 0; i < optionalStepCount; i++)
-                sendKey('Up');
-    else
-        sendKey('Up');
+function test(value, step, min, max, keySequence) {
+    setInputAttributes(min, max, step, value);
+    for (var i = 0; i < keySequence.length; i++)
+        keyDown(keySequence[i]);
     return input.value;
 }
 
-function stepDown(value, step, min, optionalStepCount) {
-    setInputAttributes(min, null, step, value);
-    if (typeof optionalStepCount != "undefined")
-        if (optionalStepCount < 0)
-            for (var i = 0; i < -optionalStepCount; i++)
-                sendKey('Up');
-        else
-            for (var i = 0; i < optionalStepCount; i++)
-                sendKey('Down');
-    else
-        sendKey('Down');
-    return input.value;
+function stepUp(value, step, min, max) {
+    return test(value,step, min, max, ['upArrow']);
 }
 
+function stepDown(value, step, min, max) {
+    return test(value,step, min, max, ['downArrow']);
+}
+
 input.type = 'time';
 input.focus();
-sendKey('Right');
-debug('Function arguments are (value, step, {min or max}, [stepCount]).');
+keyDown('rightArrow');
+debug('Function arguments are (value, step, min, max, [keySequence]).');
 debug('Normal cases');
-shouldBe('stepUp("07:13", null, null)', '"07:14"');
-shouldBe('stepDown("07:13", null, null)', '"07:12"');
-shouldBe('stepUp("07:13", null, null, 10)', '"07:23"');
-shouldBe('stepDown("07:13", null, null, 11)', '"07:02"');
+shouldBeEqualToString('stepUp("07:13", null, null, null)', '07:14');
+shouldBeEqualToString('stepDown("07:13", null, null, null)', '07:12');
+shouldBeEqualToString('test("07:13", null, null, null, ["upArrow", "upArrow", "upArrow"])', '07:16');
+shouldBeEqualToString('test("07:13", null, null, null, ["downArrow", "downArrow", "downArrow"])', '07:10');
+
+debug('Milliseconds');
+input.step = 0.001;
+keyDown('rightArrow');
+keyDown('rightArrow');
+shouldBeEqualToString('stepUp("07:13:00.000", 0.001, null, null)', '07:13:00.001');
+shouldBeEqualToString('stepDown("07:13:00.001", 0.001, null, null)', '07:13');
+shouldBeEqualToString('stepUp("07:13:00.999", 0.001, null, null)', '07:13');
+shouldBeEqualToString('stepDown("07:13:00.000", 0.001, null, null)', '07:13:00.999');
+shouldBeEqualToString('stepUp("07:13:00.000", 0.250, null, null)', '07:13:00.250');
+shouldBeEqualToString('stepDown("07:13:00.500", 0.250, null, null)', '07:13:00.250');
+shouldBeEqualToString('stepUp("07:13:00.750", 0.250, null, null)', '07:13');
+shouldBeEqualToString('stepDown("07:13:00.000", 0.250, null, null)', '07:13:00.750');
+shouldBeEqualToString('stepUp("07:13:00.099", 0.100, null, null)', '07:13:00.100');
+shouldBeEqualToString('stepDown("07:13:00.101", 0.100, null, null)', '07:13:00.100');
+shouldBeEqualToString('stepUp("07:13:00.500", 0.0001, null, null)', '07:13:00.501');
+shouldBeEqualToString('stepDown("07:13:00.500", 0.0001, null, null)', '07:13:00.499');
+shouldBeEqualToString('stepUp("07:13:00.500", 0, null, null)', '07:13:00.501');
+shouldBeEqualToString('stepDown("07:13:00.500", 0, null, null)', '07:13:00.499');
+shouldBeEqualToString('stepUp("07:13:00.500", 0.100, "00:00:00.050", null)', '07:13:00.550');
+shouldBeEqualToString('stepDown("07:13:00.500", 0.100, "00:00:00.050", null)', '07:13:00.450');
+shouldBeEqualToString('test("07:13:00.500", 0.100, null, null, ["delete", "upArrow"])', '07:13');
+shouldBeEqualToString('test("07:13:00.500", 0.100, null, null, ["delete", "downArrow"])', '07:13:00.900');
+shouldBeEqualToString('test("07:13:00.500", 0.100, "00:00:00.050", null, ["delete", "upArrow"])', '07:13:00.050');
+shouldBeEqualToString('test("07:13:00.500", 0.100, "00:00:00.050", null, ["delete", "downArrow"])', '07:13:00.950');
+
 debug('');
 document.body.removeChild(input);
 </script>

Modified: trunk/Source/WebCore/ChangeLog (137560 => 137561)


--- trunk/Source/WebCore/ChangeLog	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/Source/WebCore/ChangeLog	2012-12-13 03:02:04 UTC (rev 137561)
@@ -1,3 +1,32 @@
+2012-12-12  Kunihiko Sakamoto  <ksakam...@chromium.org>
+
+        Milliseconds field of date/time input UI should respect step attribute
+        https://bugs.webkit.org/show_bug.cgi?id=104628
+
+        Reviewed by Kent Tamura.
+
+        This patch makes step-up/-down UI of the milliseconds fields respect step attribute
+        in a special case when the step is divisible by 1000 milliseconds.
+
+        Test: fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html
+
+        * html/shadow/DateTimeEditElement.cpp:
+        (WebCore::DateTimeEditBuilder::visitField):
+        If step of the element (in milliseconds) is divisible by 1000, use it as the step of the milliseconds field. Otherwise, the millisecond field has step 1.
+        * html/shadow/DateTimeFieldElements.cpp:
+        (WebCore::DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement): Add step and stepBase arguments.
+        (WebCore::DateTimeMillisecondFieldElement::create): Ditto.
+        * html/shadow/DateTimeFieldElements.h:
+        (DateTimeMillisecondFieldElement): Ditto.
+        * html/shadow/DateTimeNumericFieldElement.cpp:
+        (WebCore::DateTimeNumericFieldElement::DateTimeNumericFieldElement): Ditto.
+        (WebCore::DateTimeNumericFieldElement::stepDown): Changed to compute next allowed value using roundDown().
+        (WebCore::DateTimeNumericFieldElement::stepUp): Changed to compute next allowed value using roundUp().
+        (WebCore::DateTimeNumericFieldElement::roundDown): Added.
+        (WebCore::DateTimeNumericFieldElement::roundUp): Added.
+        * html/shadow/DateTimeNumericFieldElement.h:
+        (DateTimeNumericFieldElement): Add m_step and m_stepBase fields.
+
 2012-12-12  Julien Chaffraix  <jchaffr...@webkit.org>
 
         [CSS Grid Layout] Include paddings and borders into the grid element's logical height / width

Modified: trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp (137560 => 137561)


--- trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/Source/WebCore/html/shadow/DateTimeEditElement.cpp	2012-12-13 03:02:04 UTC (rev 137561)
@@ -213,7 +213,16 @@
     }
 
     case DateTimeFormat::FieldTypeFractionalSecond: {
-        RefPtr<DateTimeNumericFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement);
+        ASSERT(!m_parameters.stepRange.step().isZero());
+        int step = 1;
+        int stepBase = 0;
+        const Decimal decimalMsPerSecond(static_cast<int>(msPerSecond));
+
+        if (decimalMsPerSecond.remainder(m_parameters.stepRange.step()).isZero() && m_parameters.stepRange.step().remainder(Decimal(1)).isZero()) {
+            step = static_cast<int>(m_parameters.stepRange.step().toDouble());
+            stepBase = static_cast<int>(m_parameters.stepRange.stepBase().remainder(decimalMsPerSecond).toDouble());
+        }
+        RefPtr<DateTimeNumericFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement, step, stepBase);
         m_editElement.addField(field);
         if (shouldMillisecondFieldReadOnly()) {
             field->setValueAsDate(m_dateValue);

Modified: trunk/Source/WebCore/html/shadow/DateTimeFieldElements.cpp (137560 => 137561)


--- trunk/Source/WebCore/html/shadow/DateTimeFieldElements.cpp	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/Source/WebCore/html/shadow/DateTimeFieldElements.cpp	2012-12-13 03:02:04 UTC (rev 137561)
@@ -217,15 +217,15 @@
 
 // ----------------------------
 
-DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement(Document* document, FieldOwner& fieldOwner)
-    : DateTimeNumericFieldElement(document, fieldOwner, 0, 999, "---")
+DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement(Document* document, FieldOwner& fieldOwner, int step, int stepBase)
+    : DateTimeNumericFieldElement(document, fieldOwner, 0, 999, "---", step, stepBase)
 {
 }
 
-PassRefPtr<DateTimeMillisecondFieldElement> DateTimeMillisecondFieldElement::create(Document* document, FieldOwner& fieldOwner)
+PassRefPtr<DateTimeMillisecondFieldElement> DateTimeMillisecondFieldElement::create(Document* document, FieldOwner& fieldOwner, int step, int stepBase)
 {
     DEFINE_STATIC_LOCAL(AtomicString, millisecondPsuedoId, ("-webkit-datetime-edit-millisecond-field", AtomicString::ConstructFromLiteral));
-    RefPtr<DateTimeMillisecondFieldElement> field = adoptRef(new DateTimeMillisecondFieldElement(document, fieldOwner));
+    RefPtr<DateTimeMillisecondFieldElement> field = adoptRef(new DateTimeMillisecondFieldElement(document, fieldOwner, step, stepBase));
     field->initialize(millisecondPsuedoId, AXMillisecondFieldText());
     return field.release();
 }

Modified: trunk/Source/WebCore/html/shadow/DateTimeFieldElements.h (137560 => 137561)


--- trunk/Source/WebCore/html/shadow/DateTimeFieldElements.h	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/Source/WebCore/html/shadow/DateTimeFieldElements.h	2012-12-13 03:02:04 UTC (rev 137561)
@@ -91,10 +91,10 @@
     WTF_MAKE_NONCOPYABLE(DateTimeMillisecondFieldElement);
 
 public:
-    static PassRefPtr<DateTimeMillisecondFieldElement> create(Document*, FieldOwner&);
+    static PassRefPtr<DateTimeMillisecondFieldElement> create(Document*, FieldOwner&, int step, int stepBase);
 
 private:
-    DateTimeMillisecondFieldElement(Document*, FieldOwner&);
+    DateTimeMillisecondFieldElement(Document*, FieldOwner&, int step, int stepBase);
 
     // DateTimeFieldElement functions.
     virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL;

Modified: trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp (137560 => 137561)


--- trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp	2012-12-13 03:02:04 UTC (rev 137561)
@@ -59,14 +59,18 @@
 
 // ----------------------------
 
-DateTimeNumericFieldElement::DateTimeNumericFieldElement(Document* document, FieldOwner& fieldOwner, int minimum, int maximum, const String& placeholder)
+DateTimeNumericFieldElement::DateTimeNumericFieldElement(Document* document, FieldOwner& fieldOwner, int minimum, int maximum, const String& placeholder, int step, int stepBase)
     : DateTimeFieldElement(document, fieldOwner)
     , m_lastDigitCharTime(0)
     , m_placeholder(placeholder)
     , m_range(minimum, maximum)
     , m_value(0)
     , m_hasValue(false)
+    , m_step(step)
+    , m_stepBase(stepBase)
 {
+    ASSERT(m_step);
+
     // We show a direction-neutral string such as "--" as a placeholder. It
     // should follow the direction of numeric values.
     if (localeForOwner().isRTL()) {
@@ -182,18 +186,18 @@
 
 void DateTimeNumericFieldElement::stepDown()
 {
-    if (m_hasValue)
-        setValueAsInteger(m_value == m_range.minimum ? m_range.maximum : clampValue(m_value - 1), DispatchEvent);
-    else
-        setValueAsInteger(defaultValueForStepDown(), DispatchEvent);
+    int newValue = roundDown(m_hasValue ? m_value - 1 : defaultValueForStepDown());
+    if (!m_range.isInRange(newValue))
+        newValue = roundDown(m_range.maximum);
+    setValueAsInteger(newValue, DispatchEvent);
 }
 
 void DateTimeNumericFieldElement::stepUp()
 {
-    if (m_hasValue)
-        setValueAsInteger(m_value == m_range.maximum ? m_range.minimum : clampValue(m_value + 1), DispatchEvent);
-    else
-        setValueAsInteger(defaultValueForStepUp(), DispatchEvent);
+    int newValue = roundUp(m_hasValue ? m_value + 1 : defaultValueForStepUp());
+    if (!m_range.isInRange(newValue))
+        newValue = roundUp(m_range.minimum);
+    setValueAsInteger(newValue, DispatchEvent);
 }
 
 String DateTimeNumericFieldElement::value() const
@@ -211,6 +215,26 @@
     return m_hasValue ? value() : m_placeholder;
 }
 
+int DateTimeNumericFieldElement::roundDown(int n) const
+{
+    n -= m_stepBase;
+    if (n >= 0)
+        n = n / m_step * m_step;
+    else
+        n = -((-n + m_step - 1) / m_step * m_step);
+    return n + m_stepBase;
+}
+
+int DateTimeNumericFieldElement::roundUp(int n) const
+{
+    n -= m_stepBase;
+    if (n >= 0)
+        n = (n + m_step - 1) / m_step * m_step;
+    else
+        n = -(-n / m_step * m_step);
+    return n + m_stepBase;
+}
+
 } // namespace WebCore
 
 #endif

Modified: trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h (137560 => 137561)


--- trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h	2012-12-13 02:49:54 UTC (rev 137560)
+++ trunk/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h	2012-12-13 03:02:04 UTC (rev 137561)
@@ -51,7 +51,7 @@
         int minimum;
     };
 
-    DateTimeNumericFieldElement(Document*, FieldOwner&, int minimum, int maximum, const String& placeholder);
+    DateTimeNumericFieldElement(Document*, FieldOwner&, int minimum, int maximum, const String& placeholder, int step = 1, int stepBase = 0);
 
     int clampValue(int value) const { return m_range.clampValue(value); }
     virtual int clampValueForHardLimits(int) const;
@@ -78,12 +78,16 @@
     virtual String value() const OVERRIDE FINAL;
 
     String formatValue(int) const;
+    int roundUp(int) const;
+    int roundDown(int) const;
 
     DOMTimeStamp m_lastDigitCharTime;
     const String m_placeholder;
     const Range m_range;
     int m_value;
     bool m_hasValue;
+    int m_step;
+    int m_stepBase;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to