- Revision
- 138417
- Author
- [email protected]
- Date
- 2012-12-23 01:28:26 -0800 (Sun, 23 Dec 2012)
Log Message
Merge 138365
> Fix typing zero into multiple field input
> https://bugs.webkit.org/show_bug.cgi?id=105501
>
> Reviewed by Kent Tamura.
>
> Source/WebCore:
>
> We have a couple of problems when handling zero in a multiple fields
> element.
> 1. Typing '02' into a month field will set '12'.
> 2. Typing '0' into 12 hour hour field will set '12' and move to the
> focus to the next field.
> This change adds a type ahead buffer so we can handle these cases
> properly. If the value in the type ahead buffer is valid we set it so a
> change event will fire.
>
> Added tests to *-multiple-fields-keyboard-events.html.
>
> * html/shadow/DateTimeNumericFieldElement.cpp:
> (WebCore::DateTimeNumericFieldElement::didBlur): Clear the type ahead
> buffer. handleKeyboardEvent() won't set the type ahead value if it is
> not in range, so we set the value here.
> (WebCore::DateTimeNumericFieldElement::handleKeyboardEvent):
> (WebCore::DateTimeNumericFieldElement::setEmptyValue): Clear type ahead buffer.
> (WebCore::DateTimeNumericFieldElement::setValueAsInteger):
> (WebCore::DateTimeNumericFieldElement::stepDown): Clear type ahead buffer.
> (WebCore::DateTimeNumericFieldElement::stepUp): Clear type ahead buffer.
> (WebCore::DateTimeNumericFieldElement::typeAheadValue): Returns integer
> value for the type ahead characters.
> (WebCore):
> (WebCore::DateTimeNumericFieldElement::visibleValue): If we have type
> ahead characters, show that.
> * html/shadow/DateTimeNumericFieldElement.h:
> (DateTimeNumericFieldElement):
>
> LayoutTests:
>
> * fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events-expected.txt:
> * fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events.html:
> * fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-keyboard-events-expected.txt:
> * fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-keyboard-events.html:
> * fast/forms/month-multiple-fields/month-multiple-fields-keyboard-events-expected.txt:
> * fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events-expected.txt:
> * fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html:
> * fast/forms/week-multiple-fields/week-multiple-fields-keyboard-events-expected.txt:
> * fast/forms/week-multiple-fields/week-multiple-fields-keyboard-events.html:
>
[email protected]
BUG=crbug.com/167020
Review URL: https://codereview.chromium.org/11665021
Modified Paths
Diff
Modified: branches/chromium/1312/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events-expected.txt (138416 => 138417)
--- branches/chromium/1312/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events-expected.txt 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events-expected.txt 2012-12-23 09:28:26 UTC (rev 138417)
@@ -14,6 +14,10 @@
== Digit keys ==
PASS input.value is "0012-09-20"
+== Digit keys starting with zero ==
+PASS input.value is "0044-02-03"
+== Digit keys and backspace key ==
+PASS input.value is "0008-05-06"
== Left/Right keys ==
PASS input.value is "2012-09-06"
PASS document.activeElement.id is "input"
Modified: branches/chromium/1312/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events.html (138416 => 138417)
--- branches/chromium/1312/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events.html 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-keyboard-events.html 2012-12-23 09:28:26 UTC (rev 138417)
@@ -54,6 +54,29 @@
keyDown('A'); // Ignored.
shouldBeEqualToString('input.value', '0012-09-20');
+beginTest('Digit keys starting with zero');
+keyDown('0'); // -> [00]/dd/yyyy
+keyDown('2'); // -> 02/[dd]/yyyy
+keyDown('0'); // -> 02/[00]/yyyy
+keyDown('3'); // -> 02/03/[yyyy]
+keyDown('0'); // -> 02/03/[0000]
+keyDown('0'); // -> 02/03/[0000]
+keyDown('0'); // -> 02/03/[0000]
+keyDown('4'); // -> 02/03/[0004]
+keyDown('4'); // -> 02/03/[0044]
+shouldBeEqualToString('input.value', '0044-02-03');
+
+beginTest('Digit keys and backspace key');
+keyDown('1'); // -> [01]/dd/yyyy
+keyDown("\b"); // -> [mm]/20/2012
+keyDown('5'); // -> 05/[dd]/yyyy
+keyDown('6'); // -> 05/06/[yyyy]
+keyDown("\b"); // -> 05/06/[yyyy]
+keyDown('7'); // -> 05/06/[0007]
+keyDown("\b"); // -> 05/06/[yyyy]
+keyDown('8'); // -> 05/06/[0008]
+shouldBeEqualToString('input.value', '0008-05-06');
+
// FIXME: We should test type ahead time out. When event.leapForward() affects
// keyboard event time stamp, we can uncomment this fragment.
/*
Modified: branches/chromium/1312/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-keyboard-events-expected.txt (138416 => 138417)
--- branches/chromium/1312/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-keyboard-events-expected.txt 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/LayoutTests/fast/forms/month-multiple-fields/month-multiple-fields-keyboard-events-expected.txt 2012-12-23 09:28:26 UTC (rev 138417)
@@ -13,7 +13,7 @@
Backspace - Make value empty
== Digit keys ==
-FAIL input.value should be 0012-09. Was 0112-09.
+PASS input.value is "0012-09"
== Left/Right keys ==
FAIL input.value should be 0005-06. Was 0005-09.
PASS document.activeElement.id is "input"
Modified: branches/chromium/1312/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events-expected.txt (138416 => 138417)
--- branches/chromium/1312/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events-expected.txt 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events-expected.txt 2012-12-23 09:28:26 UTC (rev 138417)
@@ -14,6 +14,10 @@
== Digit keys ==
PASS input.value is "07:56"
+== Digit keys starting with zero ==
+PASS input.value is "14:03"
+== Digit keys and backspace key ==
+PASS input.value is "17:06"
== Left/Right keys ==
PASS input.value is "06:05"
PASS document.activeElement.id is "input"
Modified: branches/chromium/1312/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html (138416 => 138417)
--- branches/chromium/1312/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-keyboard-events.html 2012-12-23 09:28:26 UTC (rev 138417)
@@ -48,6 +48,23 @@
keyDown('A');
shouldBeEqualToString('input.value', '07:56');
+beginTest('Digit keys starting with zero');
+keyDown('0'); // -> [00]:-- --
+keyDown('2'); // -> 02:[--] --
+keyDown('0'); // -> 02:[00] --
+keyDown('3'); // -> 02:03 [--]
+keyDown('P'); // -> 02:03 [PM]
+shouldBeEqualToString('input.value', '14:03');
+
+beginTest('Digit keys and backspace key','01:01');
+keyDown('0'); // -> [00]:-- --
+keyDown('\b'); // -> [--]:-- --
+keyDown('5'); // -> 05:[--] --
+keyDown('6'); // -> 05:06 [--]
+keyDown('\b'); // -> 05:06 [--]
+keyDown('P'); // -> 05:06 [PM]
+shouldBeEqualToString('input.value', '17:06');
+
// FIXME: We should test type ahead time out. When event.leapForward() affects
// keyboard event time stamp, we can uncomment this fragment.
/*
Modified: branches/chromium/1312/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp (138416 => 138417)
--- branches/chromium/1312/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp 2012-12-23 09:28:26 UTC (rev 138417)
@@ -104,7 +104,10 @@
void DateTimeNumericFieldElement::didBlur()
{
- m_lastDigitCharTime = 0;
+ int value = typeAheadValue();
+ m_typeAheadBuffer.clear();
+ if (value >= 0)
+ setValueAsInteger(value, DispatchEvent);
DateTimeFieldElement::didBlur();
}
@@ -127,23 +130,28 @@
return;
UChar charCode = static_cast<UChar>(keyboardEvent->charCode());
- if (charCode < ' ')
- return;
-
- DOMTimeStamp delta = keyboardEvent->timeStamp() - m_lastDigitCharTime;
- m_lastDigitCharTime = 0;
-
String number = localeForOwner().convertFromLocalizedNumber(String(&charCode, 1));
const int digit = number[0] - '0';
if (digit < 0 || digit > 9)
return;
+ DOMTimeStamp delta = keyboardEvent->timeStamp() - m_lastDigitCharTime;
+ m_lastDigitCharTime = keyboardEvent->timeStamp();
+
+ if (delta > typeAheadTimeout)
+ m_typeAheadBuffer.clear();
+ m_typeAheadBuffer.append(number);
+
+ int newValue = typeAheadValue();
+ if (m_range.isInRange(newValue))
+ setValueAsInteger(newValue, DispatchEvent);
+ else
+ updateVisibleValue(DispatchEvent);
+
+ if (m_typeAheadBuffer.length() >= DateTimeNumericFieldElement::formatValue(m_range.maximum).length() || newValue * 10 > m_range.maximum)
+ focusOnNextField();
+
keyboardEvent->setDefaultHandled();
- setValueAsInteger(m_hasValue && delta < typeAheadTimeout ? m_value * 10 + digit : digit, DispatchEvent);
- if (m_value * 10 > m_range.maximum)
- focusOnNextField();
- else
- m_lastDigitCharTime = keyboardEvent->timeStamp();
}
bool DateTimeNumericFieldElement::hasValue() const
@@ -163,13 +171,12 @@
void DateTimeNumericFieldElement::setEmptyValue(EventBehavior eventBehavior)
{
- m_lastDigitCharTime = 0;
-
if (isReadOnly())
return;
m_hasValue = false;
m_value = 0;
+ m_typeAheadBuffer.clear();
updateVisibleValue(eventBehavior);
}
@@ -178,11 +185,11 @@
m_value = clampValueForHardLimits(value);
m_hasValue = true;
updateVisibleValue(eventBehavior);
- m_lastDigitCharTime = 0;
}
void DateTimeNumericFieldElement::stepDown()
{
+ m_typeAheadBuffer.clear();
if (m_hasValue)
setValueAsInteger(m_value == m_range.minimum ? m_range.maximum : clampValue(m_value - 1), DispatchEvent);
else
@@ -191,6 +198,7 @@
void DateTimeNumericFieldElement::stepUp()
{
+ m_typeAheadBuffer.clear();
if (m_hasValue)
setValueAsInteger(m_value == m_range.maximum ? m_range.minimum : clampValue(m_value + 1), DispatchEvent);
else
@@ -207,8 +215,17 @@
return m_hasValue ? m_value : -1;
}
+int DateTimeNumericFieldElement::typeAheadValue() const
+{
+ if (m_typeAheadBuffer.length())
+ return m_typeAheadBuffer.toString().toInt();
+ return -1;
+}
+
String DateTimeNumericFieldElement::visibleValue() const
{
+ if (m_typeAheadBuffer.length())
+ return formatValue(typeAheadValue());
return m_hasValue ? value() : m_placeholder;
}
Modified: branches/chromium/1312/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h (138416 => 138417)
--- branches/chromium/1312/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h 2012-12-23 08:53:25 UTC (rev 138416)
+++ branches/chromium/1312/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h 2012-12-23 09:28:26 UTC (rev 138417)
@@ -78,12 +78,14 @@
virtual String value() const OVERRIDE FINAL;
String formatValue(int) const;
+ int typeAheadValue() const;
DOMTimeStamp m_lastDigitCharTime;
const String m_placeholder;
const Range m_range;
int m_value;
bool m_hasValue;
+ mutable StringBuilder m_typeAheadBuffer;
};
} // namespace WebCore