summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-02-14 14:41:19 +0100
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-02-14 14:41:19 +0100
commit8a15fd8d24e4373f462046b46fbe8558f57f3403 (patch)
tree9c485d6b346a2fed8aaa14fbb154046296d22b7a
parent34125a031ed9c7814d2145070294ead44b7504b3 (diff)
downloadUXP-8a15fd8d24e4373f462046b46fbe8558f57f3403.tar
UXP-8a15fd8d24e4373f462046b46fbe8558f57f3403.tar.gz
UXP-8a15fd8d24e4373f462046b46fbe8558f57f3403.tar.lz
UXP-8a15fd8d24e4373f462046b46fbe8558f57f3403.tar.xz
UXP-8a15fd8d24e4373f462046b46fbe8558f57f3403.zip
Bug 1286182: Implement the layout for <input type=date>
-rw-r--r--accessible/tests/mochitest/jsat/test_output.html9
-rw-r--r--dom/html/HTMLInputElement.cpp23
-rw-r--r--dom/html/nsIFormControl.h2
-rw-r--r--dom/html/test/forms/mochitest.ini6
-rw-r--r--dom/html/test/forms/test_input_date_key_events.html228
-rw-r--r--dom/html/test/forms/test_input_datetime_focus_blur.html28
-rw-r--r--dom/html/test/forms/test_input_datetime_focus_blur_events.html90
-rw-r--r--dom/html/test/forms/test_input_datetime_tabindex.html47
-rw-r--r--dom/html/test/forms/test_input_time_focus_blur_events.html82
-rw-r--r--dom/html/test/forms/test_input_typing_sanitization.html28
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp4
-rw-r--r--layout/forms/nsDateTimeControlFrame.cpp3
-rw-r--r--layout/style/res/html.css5
-rw-r--r--toolkit/components/satchel/test/test_form_autocomplete.html12
-rw-r--r--toolkit/content/widgets/datetimebox.xml420
15 files changed, 846 insertions, 141 deletions
diff --git a/accessible/tests/mochitest/jsat/test_output.html b/accessible/tests/mochitest/jsat/test_output.html
index ec2b289be..525642607 100644
--- a/accessible/tests/mochitest/jsat/test_output.html
+++ b/accessible/tests/mochitest/jsat/test_output.html
@@ -125,14 +125,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
{"string": "listAbbr"},
{"string": "cellInfoAbbr", "args": [ 1, 1]}]]
}, {
- accOrElmOrID: "date",
- expectedUtterance: [[{"string": "textInputType_date"},
- {"string": "entry"}, "2011-09-29"], ["2011-09-29",
- {"string": "textInputType_date"}, {"string": "entry"}]],
- expectedBraille: [[{"string": "textInputType_date"},
- {"string": "entryAbbr"}, "2011-09-29"], ["2011-09-29",
- {"string": "textInputType_date"}, {"string": "entryAbbr"}]]
- }, {
accOrElmOrID: "email",
expectedUtterance: [[{"string": "textInputType_email"},
{"string": "entry"}, "test@example.com"], ["test@example.com",
@@ -619,7 +611,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
<label for="password">Secret Password</label><input id="password" type="password"></input>
<label for="radio_unselected">any old radio button</label><input id="radio_unselected" type="radio"></input>
<label for="radio_selected">a unique radio button</label><input id="radio_selected" type="radio" checked></input>
- <input id="date" type="date" value="2011-09-29" />
<input id="email" type="email" value="test@example.com" />
<input id="search" type="search" value="This is a search" />
<input id="tel" type="tel" value="555-5555" />
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index 78f74ae0c..dc755cd02 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2832,7 +2832,8 @@ HTMLInputElement::GetOwnerDateTimeControl()
HTMLInputElement::FromContentOrNull(
GetParent()->GetParent()->GetParent()->GetParent());
if (ownerDateTimeControl &&
- ownerDateTimeControl->mType == NS_FORM_INPUT_TIME) {
+ (ownerDateTimeControl->mType == NS_FORM_INPUT_TIME ||
+ ownerDateTimeControl->mType == NS_FORM_INPUT_DATE)) {
return ownerDateTimeControl;
}
}
@@ -3282,7 +3283,8 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, uint32_t aFlags)
if (frame) {
frame->UpdateForValueChange();
}
- } else if (mType == NS_FORM_INPUT_TIME &&
+ } else if ((mType == NS_FORM_INPUT_TIME ||
+ mType == NS_FORM_INPUT_DATE) &&
!IsExperimentalMobileType(mType)) {
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
@@ -3591,7 +3593,8 @@ HTMLInputElement::Blur(ErrorResult& aError)
}
}
- if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType)) {
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
+ !IsExperimentalMobileType(mType)) {
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
frame->HandleBlurEvent();
@@ -3618,7 +3621,8 @@ HTMLInputElement::Focus(ErrorResult& aError)
}
}
- if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType)) {
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
+ !IsExperimentalMobileType(mType)) {
nsDateTimeControlFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
frame->HandleFocusEvent();
@@ -3956,7 +3960,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
}
}
- if (mType == NS_FORM_INPUT_TIME &&
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
!IsExperimentalMobileType(mType) &&
aVisitor.mEvent->mMessage == eFocus &&
aVisitor.mEvent->mOriginalTarget == this) {
@@ -4083,7 +4087,8 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
// Stop the event if the related target's first non-native ancestor is the
// same as the original target's first non-native ancestor (we are moving
// inside of the same element).
- if (mType == NS_FORM_INPUT_TIME && !IsExperimentalMobileType(mType) &&
+ if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
+ !IsExperimentalMobileType(mType) &&
(aVisitor.mEvent->mMessage == eFocus ||
aVisitor.mEvent->mMessage == eFocusIn ||
aVisitor.mEvent->mMessage == eFocusOut ||
@@ -7161,13 +7166,15 @@ HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t*
if (mType == NS_FORM_INPUT_FILE ||
mType == NS_FORM_INPUT_NUMBER ||
- mType == NS_FORM_INPUT_TIME) {
+ mType == NS_FORM_INPUT_TIME ||
+ mType == NS_FORM_INPUT_DATE) {
if (aTabIndex) {
// We only want our native anonymous child to be tabable to, not ourself.
*aTabIndex = -1;
}
if (mType == NS_FORM_INPUT_NUMBER ||
- mType == NS_FORM_INPUT_TIME) {
+ mType == NS_FORM_INPUT_TIME ||
+ mType == NS_FORM_INPUT_DATE) {
*aIsFocusable = true;
} else {
*aIsFocusable = defaultFocusable;
diff --git a/dom/html/nsIFormControl.h b/dom/html/nsIFormControl.h
index aaa92146c..e07f7c829 100644
--- a/dom/html/nsIFormControl.h
+++ b/dom/html/nsIFormControl.h
@@ -270,8 +270,8 @@ nsIFormControl::IsSingleLineTextControl(bool aExcludePassword, uint32_t aType)
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
// On Android/B2G, date/time input appears as a normal text box.
aType == NS_FORM_INPUT_TIME ||
-#endif
aType == NS_FORM_INPUT_DATE ||
+#endif
aType == NS_FORM_INPUT_MONTH ||
aType == NS_FORM_INPUT_WEEK ||
aType == NS_FORM_INPUT_DATETIME_LOCAL ||
diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini
index 35955b189..6fceefd98 100644
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -30,8 +30,12 @@ skip-if = os == "android" # up/down arrow keys not supported on android
skip-if = android_version == '18' # Android, bug 1147974
[test_input_color_picker_update.html]
skip-if = android_version == '18' # Android, bug 1147974
+[test_input_date_key_events.html]
+skip-if = os == "android"
[test_input_datetime_focus_blur.html]
skip-if = os == "android"
+[test_input_datetime_focus_blur_events.html]
+skip-if = os == "android"
[test_input_datetime_tabindex.html]
skip-if = os == "android"
[test_input_defaultValue.html]
@@ -61,8 +65,6 @@ skip-if = os == "android"
[test_input_textarea_set_value_no_scroll.html]
[test_input_time_key_events.html]
skip-if = os == "android"
-[test_input_time_focus_blur_events.html]
-skip-if = os == "android"
[test_input_types_pref.html]
[test_input_typing_sanitization.html]
[test_input_untrusted_key_events.html]
diff --git a/dom/html/test/forms/test_input_date_key_events.html b/dom/html/test/forms/test_input_date_key_events.html
new file mode 100644
index 000000000..cd974e505
--- /dev/null
+++ b/dom/html/test/forms/test_input_date_key_events.html
@@ -0,0 +1,228 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1286182
+-->
+<head>
+ <title>Test key events for time control</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1286182">Mozilla Bug 1286182</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="date">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+// Turn off Spatial Navigation because it hijacks arrow keydown events:
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
+ test();
+ SimpleTest.finish();
+ });
+});
+
+var testData = [
+ /**
+ * keys: keys to send to the input element.
+ * initialVal: initial value set to the input element.
+ * expectedVal: expected value of the input element after sending the keys.
+ */
+ {
+ // Type 11222016, default order is month, day, year.
+ keys: ["11222016"],
+ initialVal: "",
+ expectedVal: "2016-11-22"
+ },
+ {
+ // Type 3 in the month field will automatically advance to the day field,
+ // then type 5 in the day field will automatically advance to the year
+ // field.
+ keys: ["352016"],
+ initialVal: "",
+ expectedVal: "2016-03-05"
+ },
+ {
+ // Type 13 in the month field will set it to the maximum month, which is
+ // 12.
+ keys: ["13012016"],
+ initialVal: "",
+ expectedVal: "2016-12-01"
+ },
+ {
+ // Type 00 in the month field will set it to the minimum month, which is 1.
+ keys: ["00012016"],
+ initialVal: "",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // Type 33 in the day field will set it to the maximum day, which is 31.
+ keys: ["12332016"],
+ initialVal: "",
+ expectedVal: "2016-12-31"
+ },
+ {
+ // Type 00 in the day field will set it to the minimum day, which is 1.
+ keys: ["12002016"],
+ initialVal: "",
+ expectedVal: "2016-12-01"
+ },
+ {
+ // Type 275769 in the year field will set it to the maximum year, which is
+ // 275760.
+ keys: ["0101275769"],
+ initialVal: "",
+ expectedVal: "275760-01-01"
+ },
+ {
+ // Type 000000 in the year field will set it to the minimum year, which is
+ // 0001.
+ keys: ["0101000000"],
+ initialVal: "",
+ expectedVal: "0001-01-01"
+ },
+ {
+ // Advance to year field and decrement.
+ keys: ["VK_TAB", "VK_TAB", "VK_DOWN"],
+ initialVal: "2016-11-25",
+ expectedVal: "2015-11-25"
+ },
+ {
+ // Right key should do the same thing as TAB key.
+ keys: ["VK_RIGHT", "VK_RIGHT", "VK_DOWN"],
+ initialVal: "2016-11-25",
+ expectedVal: "2015-11-25"
+ },
+ {
+ // Advance to day field then back to month field and decrement.
+ keys: ["VK_RIGHT", "VK_LEFT", "VK_DOWN"],
+ initialVal: "2000-05-01",
+ expectedVal: "2000-04-01"
+ },
+ {
+ // Focus starts on the first field, month in this case, and increment.
+ keys: ["VK_UP"],
+ initialVal: "2000-03-01",
+ expectedVal: "2000-04-01"
+ },
+ {
+ // Advance to day field and decrement.
+ keys: ["VK_TAB", "VK_DOWN"],
+ initialVal: "1234-01-01",
+ expectedVal: "1234-01-31"
+ },
+ {
+ // Advance to day field and increment.
+ keys: ["VK_TAB", "VK_UP"],
+ initialVal: "1234-01-01",
+ expectedVal: "1234-01-02"
+ },
+ {
+ // PageUp on month field increments month by 3.
+ keys: ["VK_PAGE_UP"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-04-01"
+ },
+ {
+ // PageDown on month field decrements month by 3.
+ keys: ["VK_PAGE_DOWN"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-10-01"
+ },
+ {
+ // PageUp on day field increments day by 7.
+ keys: ["VK_TAB", "VK_PAGE_UP"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-01-08"
+ },
+ {
+ // PageDown on day field decrements day by 7.
+ keys: ["VK_TAB", "VK_PAGE_DOWN"],
+ initialVal: "1999-01-01",
+ expectedVal: "1999-01-25"
+ },
+ {
+ // PageUp on year field increments year by 10.
+ keys: ["VK_TAB", "VK_TAB", "VK_PAGE_UP"],
+ initialVal: "1999-01-01",
+ expectedVal: "2009-01-01"
+ },
+ {
+ // PageDown on year field decrements year by 10.
+ keys: ["VK_TAB", "VK_TAB", "VK_PAGE_DOWN"],
+ initialVal: "1999-01-01",
+ expectedVal: "1989-01-01"
+ },
+ {
+ // Home key on month field sets it to the minimum month, which is 01.
+ keys: ["VK_HOME"],
+ initialVal: "2016-06-01",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // End key on month field sets it to the maximum month, which is 12.
+ keys: ["VK_END"],
+ initialVal: "2016-06-01",
+ expectedVal: "2016-12-01"
+ },
+ {
+ // Home key on day field sets it to the minimum day, which is 01.
+ keys: ["VK_TAB", "VK_HOME"],
+ initialVal: "2016-01-10",
+ expectedVal: "2016-01-01"
+ },
+ {
+ // End key on day field sets it to the maximum day, which is 31.
+ keys: ["VK_TAB", "VK_END"],
+ initialVal: "2016-01-10",
+ expectedVal: "2016-01-31"
+ },
+ {
+ // Home key on year field sets it to the minimum year, which is 0001.
+ keys: ["VK_TAB", "VK_TAB", "VK_HOME"],
+ initialVal: "2016-01-01",
+ expectedVal: "0001-01-01"
+ },
+ {
+ // End key on year field sets it to the maximum year, which is 275760.
+ keys: ["VK_TAB", "VK_TAB", "VK_END"],
+ initialVal: "2016-01-01",
+ expectedVal: "275760-01-01"
+ },
+];
+
+function sendKeys(aKeys) {
+ for (let i = 0; i < aKeys.length; i++) {
+ let key = aKeys[i];
+ if (key.startsWith("VK")) {
+ synthesizeKey(key, {});
+ } else {
+ sendString(key);
+ }
+ }
+}
+
+function test() {
+ var elem = document.getElementById("input");
+
+ for (let { keys, initialVal, expectedVal } of testData) {
+ elem.focus();
+ elem.value = initialVal;
+ sendKeys(keys);
+ elem.blur();
+ is(elem.value, expectedVal,
+ "Test with " + keys + ", result should be " + expectedVal);
+ elem.value = "";
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_focus_blur.html b/dom/html/test/forms/test_input_datetime_focus_blur.html
index 5b8d95b25..85f7b4bb4 100644
--- a/dom/html/test/forms/test_input_datetime_focus_blur.html
+++ b/dom/html/test/forms/test_input_datetime_focus_blur.html
@@ -4,7 +4,7 @@
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
-->
<head>
- <title>Test focus/blur behaviour for &lt;input type='time'&gt;</title>
+ <title>Test focus/blur behaviour for date/time input types</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
@@ -12,7 +12,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
<p id="display"></p>
<div id="content">
- <input id="input" type="time">
+ <input id="input_time" type="time">
+ <input id="input_date" type="date">
</div>
<pre id="test">
<script type="application/javascript">
@@ -30,15 +31,15 @@ SimpleTest.waitForFocus(function() {
SimpleTest.finish();
});
-function test() {
- let time = document.getElementById("input");
- time.focus();
+function testFocusBlur(type) {
+ let input = document.getElementById("input_" + type);
+ input.focus();
- // The active element returns the input type=time.
+ // The active element returns the date/time input element.
let activeElement = document.activeElement;
- is(activeElement, time, "activeElement should be the time element");
+ is(activeElement, input, "activeElement should be the date/time input element");
is(activeElement.localName, "input", "activeElement should be an input element");
- is(activeElement.type, "time", "activeElement should be of type time");
+ is(activeElement.type, type, "activeElement should be of type " + type);
// Use FocusManager to check that the actual focus is on the anonymous
// text control.
@@ -48,10 +49,17 @@ function test() {
is(focusedElement.localName, "input", "focusedElement should be an input element");
is(focusedElement.type, "text", "focusedElement should be of type text");
- time.blur();
- isnot(document.activeElement, time, "activeElement should no longer be the time element");
+ input.blur();
+ isnot(document.activeElement, input, "activeElement should no longer be the datetime input element");
}
+function test() {
+ let inputTypes = ["time", "date"];
+
+ for (let i = 0; i < inputTypes.length; i++) {
+ testFocusBlur(inputTypes[i]);
+ }
+}
</script>
</pre>
</body>
diff --git a/dom/html/test/forms/test_input_datetime_focus_blur_events.html b/dom/html/test/forms/test_input_datetime_focus_blur_events.html
new file mode 100644
index 000000000..873dda627
--- /dev/null
+++ b/dom/html/test/forms/test_input_datetime_focus_blur_events.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
+-->
+<head>
+<title>Test for Bug 1301306</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
+<p id="display"></p>
+<div id="content">
+<input type="time" id="input_time" onfocus="++focusEvents[0]"
+ onblur="++blurEvents[0]" onfocusin="++focusInEvents[0]"
+ onfocusout="++focusOutEvents[0]">
+<input type="date" id="input_date" onfocus="++focusEvents[1]"
+ onblur="++blurEvents[1]" onfocusin="++focusInEvents[1]"
+ onfocusout="++focusOutEvents[1]">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ * Test for Bug 1301306.
+ * This test checks that when moving inside the time input element, e.g. jumping
+ * through the inner text boxes, does not fire extra focus/blur events.
+ **/
+
+var inputTypes = ["time", "date"];
+var focusEvents = [0, 0];
+var focusInEvents = [0, 0];
+var focusOutEvents = [0, 0];
+var blurEvents = [0, 0];
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ for (var i = 0; i < inputTypes.length; i++) {
+ var input = document.getElementById("input_" + inputTypes[i]);
+
+ input.focus();
+ is(focusEvents[i], 1, inputTypes[i] + " input element should have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ // Move around inside the input element's input box.
+ synthesizeKey("VK_TAB", {});
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " time input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_RIGHT", {});
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_LEFT", {});
+ is(focusEvents[i], 1,inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_RIGHT", {});
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 0, inputTypes[i] + " input element should not have dispatched focusout event.");
+ is(blurEvents[i], 0, inputTypes[i] + " input element should not have dispatched blur event.");
+
+ input.blur();
+ is(focusEvents[i], 1, inputTypes[i] + " input element should not have dispatched focus event.");
+ is(focusInEvents[i], 1, inputTypes[i] + " input element should not have dispatched focusin event.");
+ is(focusOutEvents[i], 1, inputTypes[i] + " input element should have dispatched focusout event.");
+ is(blurEvents[i], 1, inputTypes[i] + " input element should have dispatched blur event.");
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_tabindex.html b/dom/html/test/forms/test_input_datetime_tabindex.html
index fb7c9b2f1..8023ccf9b 100644
--- a/dom/html/test/forms/test_input_datetime_tabindex.html
+++ b/dom/html/test/forms/test_input_datetime_tabindex.html
@@ -4,7 +4,7 @@
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
-->
<head>
- <title>Test tabindex attribute for &lt;input type='time'&gt;</title>
+ <title>Test tabindex attribute for date/time input types</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
@@ -16,13 +16,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
<input id="time1" type="time" tabindex="0">
<input id="time2" type="time" tabindex="-1">
<input id="time3" type="time" tabindex="0">
+ <input id="date1" type="date" tabindex="0">
+ <input id="date2" type="date" tabindex="-1">
+ <input id="date3" type="date" tabindex="0">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Test for Bug 1288591.
- * This test checks whether date/time input types' tabindex attribute works
+ * This test checks whether date/time input types tabindex attribute works
* correctly.
**/
SimpleTest.waitForExplicitFinish();
@@ -31,41 +34,49 @@ SimpleTest.waitForFocus(function() {
SimpleTest.finish();
});
-function test() {
- let time1 = document.getElementById("time1");
- let time2 = document.getElementById("time2");
- let time3 = document.getElementById("time3");
+function testTabindex(type) {
+ let input1 = document.getElementById(type + "1");
+ let input2 = document.getElementById(type + "2");
+ let input3 = document.getElementById(type + "3");
- time1.focus();
- is(document.activeElement, time1,
+ input1.focus();
+ is(document.activeElement, input1,
"input element with tabindex=0 is focusable");
- // Advance to time1 minute field
+ // Advance to next inner field
synthesizeKey("VK_TAB", {});
- is(document.activeElement, time1,
+ is(document.activeElement, input1,
"input element with tabindex=0 is tabbable");
- // Advance to time1 AM/PM field
+ // Advance to next inner field
synthesizeKey("VK_TAB", {});
- is(document.activeElement, time1,
+ is(document.activeElement, input1,
"input element with tabindex=0 is tabbable");
// Advance to next element
synthesizeKey("VK_TAB", {});
- is(document.activeElement, time3,
+ is(document.activeElement, input3,
"input element with tabindex=-1 is not tabbable");
- time2.focus();
- is(document.activeElement, time2,
+ input2.focus();
+ is(document.activeElement, input2,
"input element with tabindex=-1 is still focusable");
// Changing the tabindex attribute dynamically.
- time3.setAttribute("tabindex", "-1");
- synthesizeKey("VK_TAB", {}); // need only one TAB since time2 is not tabbable
- isnot(document.activeElement, time3,
+ input3.setAttribute("tabindex", "-1");
+ synthesizeKey("VK_TAB", {}); // need only one TAB since input2 is not tabbable
+ isnot(document.activeElement, input3,
"element with tabindex changed to -1 should not be tabbable");
}
+function test() {
+ let inputTypes = ["time", "date"];
+
+ for (let i = 0; i < inputTypes.length; i++) {
+ testTabindex(inputTypes[i]);
+ }
+}
+
</script>
</pre>
</body>
diff --git a/dom/html/test/forms/test_input_time_focus_blur_events.html b/dom/html/test/forms/test_input_time_focus_blur_events.html
deleted file mode 100644
index 483741477..000000000
--- a/dom/html/test/forms/test_input_time_focus_blur_events.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
--->
-<head>
-<title>Test for Bug 1301306</title>
-<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
-<p id="display"></p>
-<div id="content">
-<input type="time" id="input_time" onfocus="++focusEvent" onblur="++blurEvent"
- onfocusin="++focusInEvent" onfocusout="++focusOutEvent">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/**
- * Test for Bug 1301306.
- * This test checks that when moving inside the time input element, e.g. jumping
- * through the inner text boxes, does not fire extra focus/blur events.
- **/
-
-var focusEvent = 0;
-var focusInEvent = 0;
-var focusOutEvent = 0;
-var blurEvent = 0;
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- test();
- SimpleTest.finish();
-});
-
-function test() {
- var time = document.getElementById("input_time");
- time.focus();
- is(focusEvent, 1, "time input element should have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- // Move around inside the input element's input box.
- synthesizeKey("VK_TAB", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- synthesizeKey("VK_RIGHT", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- synthesizeKey("VK_LEFT", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- synthesizeKey("VK_RIGHT", {});
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
- is(blurEvent, 0, "time input element should not have dispatched blur event.");
-
- time.blur();
- is(focusEvent, 1, "time input element should not have dispatched focus event.");
- is(focusInEvent, 1, "time input element should have dispatched focusin event.");
- is(focusOutEvent, 1, "time input element should not have dispatched focusout event.");
- is(blurEvent, 1, "time input element should have dispatched blur event.");
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/dom/html/test/forms/test_input_typing_sanitization.html b/dom/html/test/forms/test_input_typing_sanitization.html
index 0896f19df..eee300b33 100644
--- a/dom/html/test/forms/test_input_typing_sanitization.html
+++ b/dom/html/test/forms/test_input_typing_sanitization.html
@@ -26,6 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=765772
* This test checks that when a user types in some input types, it will not be
* in a state where the value will be un-sanitized and usable (by a script).
*/
+const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
var input = document.getElementById('i');
var form = document.getElementById('f');
@@ -143,6 +144,7 @@ function runTest()
]
},
{
+ mobileOnly: true,
type: 'date',
validData: [
'0001-01-01',
@@ -161,6 +163,28 @@ function runTest()
]
},
{
+ mobileOnly: true,
+ type: 'time',
+ validData: [
+ '00:00',
+ '09:09:00',
+ '08:23:23.1',
+ '21:43:56.12',
+ '23:12:45.100',
+ ],
+ invalidData: [
+ '00:',
+ '00:00:',
+ '25:00',
+ '-00:00',
+ '00:00:00.',
+ '00:60',
+ '10:58:99',
+ ':19:10',
+ '23:08:09.1012',
+ ]
+ },
+ {
type: 'month',
validData: [
'0001-01',
@@ -218,6 +242,10 @@ function runTest()
for (test of data) {
gCurrentTest = test;
+ if (gCurrentTest.mobileOnly && isDesktop) {
+ continue;
+ }
+
input.type = test.type;
gValidData = test.validData;
gInvalidData = test.invalidData;
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index a118c38f9..f8c7f52a9 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3658,13 +3658,13 @@ nsCSSFrameConstructor::FindInputData(Element* aElement,
nsCSSAnonBoxes::buttonContent) },
// TODO: this is temporary until a frame is written: bug 635240.
SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame),
- // TODO: this is temporary until a frame is written: bug 888320.
- SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame),
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
// On Android/B2G, date/time input appears as a normal text box.
SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewTextControlFrame),
+ SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame),
#else
SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewDateTimeControlFrame),
+ SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewDateTimeControlFrame),
#endif
// TODO: this is temporary until a frame is written: bug 888320
SIMPLE_INT_CREATE(NS_FORM_INPUT_MONTH, NS_NewTextControlFrame),
diff --git a/layout/forms/nsDateTimeControlFrame.cpp b/layout/forms/nsDateTimeControlFrame.cpp
index df2e43986..fa22dceba 100644
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -372,7 +372,8 @@ nsDateTimeControlFrame::AttributeChanged(int32_t aNameSpaceID,
auto contentAsInputElem = static_cast<dom::HTMLInputElement*>(mContent);
// If script changed the <input>'s type before setting these attributes
// then we don't need to do anything since we are going to be reframed.
- if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME) {
+ if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME ||
+ contentAsInputElem->GetType() == NS_FORM_INPUT_DATE) {
if (aAttribute == nsGkAtoms::value) {
nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
do_QueryInterface(mInputAreaContent);
diff --git a/layout/style/res/html.css b/layout/style/res/html.css
index a779461de..bc3f08210 100644
--- a/layout/style/res/html.css
+++ b/layout/style/res/html.css
@@ -774,6 +774,11 @@ input[type="time"] > xul|datetimebox {
-moz-binding: url("chrome://global/content/bindings/datetimebox.xml#time-input");
}
+input[type="date"] > xul|datetimebox {
+ display: flex;
+ -moz-binding: url("chrome://global/content/bindings/datetimebox.xml#date-input");
+}
+
/* details & summary */
/* Need to revert Bug 1259889 Part 2 when removing details preference. */
@supports -moz-bool-pref("dom.details_element.enabled") {
diff --git a/toolkit/components/satchel/test/test_form_autocomplete.html b/toolkit/components/satchel/test/test_form_autocomplete.html
index 4cf09117a..d2c22a3db 100644
--- a/toolkit/components/satchel/test/test_form_autocomplete.html
+++ b/toolkit/components/satchel/test/test_form_autocomplete.html
@@ -172,7 +172,7 @@ function setupFormHistory(aCallback) {
{ op : "add", fieldname : "field8", value : "value" },
{ op : "add", fieldname : "field9", value : "value" },
{ op : "add", fieldname : "field10", value : "42" },
- { op : "add", fieldname : "field11", value : "2010-10-10" },
+ { op : "add", fieldname : "field11", value : "2010-10-10" }, // not used, since type=date doesn't have autocomplete currently
{ op : "add", fieldname : "field12", value : "21:21" }, // not used, since type=time doesn't have autocomplete currently
{ op : "add", fieldname : "field13", value : "32" }, // not used, since type=range doesn't have a drop down menu
{ op : "add", fieldname : "field14", value : "#ffffff" }, // not used, since type=color doesn't have autocomplete currently
@@ -899,15 +899,13 @@ function runTest() {
input = $_(14, "field11");
restoreForm();
- expectPopup();
- doKey("down");
+ waitForMenuChange(0);
break;
case 405:
- checkMenuEntries(["2010-10-10"]);
- doKey("down");
- doKey("return");
- checkForm("2010-10-10");
+ checkMenuEntries([]); // type=date with it's own control frame does not
+ // have a drop down menu for now
+ checkForm("");
input = $_(15, "field12");
restoreForm();
diff --git a/toolkit/content/widgets/datetimebox.xml b/toolkit/content/widgets/datetimebox.xml
index 21cc6c1bd..677d3fc21 100644
--- a/toolkit/content/widgets/datetimebox.xml
+++ b/toolkit/content/widgets/datetimebox.xml
@@ -10,6 +10,405 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
+ <binding id="date-input"
+ extends="chrome://global/content/bindings/datetimebox.xml#datetime-input-base">
+ <resources>
+ <stylesheet src="chrome://global/content/textbox.css"/>
+ <stylesheet src="chrome://global/skin/textbox.css"/>
+ <stylesheet src="chrome://global/content/bindings/datetimebox.css"/>
+ </resources>
+
+ <implementation>
+ <constructor>
+ <![CDATA[
+ // TODO: Bug 1320227 - [DateTimeInput] localization for
+ // <input type=date> input box
+ this.mMonthPlaceHolder = "mm";
+ this.mDayPlaceHolder = "dd";
+ this.mYearPlaceHolder = "yyyy";
+ this.mSeparatorText = "/";
+ this.mMinMonth = 1;
+ this.mMaxMonth = 12;
+ this.mMinDay = 1;
+ this.mMaxDay = 31;
+ this.mMinYear = 1;
+ // Maximum year limited by ECMAScript date object range, year <= 275760.
+ this.mMaxYear = 275760;
+ this.mMonthDayLength = 2;
+ this.mYearLength = 4;
+ this.mMonthPageUpDownInterval = 3;
+ this.mDayPageUpDownInterval = 7;
+ this.mYearPageUpDownInterval = 10;
+
+ // Default to en-US, month-day-year order.
+ this.mMonthField =
+ document.getAnonymousElementByAttribute(this, "anonid", "input-one");
+ this.mDayField =
+ document.getAnonymousElementByAttribute(this, "anonid", "input-two");
+ this.mYearField =
+ document.getAnonymousElementByAttribute(this, "anonid", "input-three");
+ this.mYearField.size = this.mYearLength;
+ this.mYearField.maxLength = this.mMaxYear.toString().length;
+
+ this.mMonthField.placeholder = this.mMonthPlaceHolder;
+ this.mDayField.placeholder = this.mDayPlaceHolder;
+ this.mYearField.placeholder = this.mYearPlaceHolder;
+
+ this.mMonthField.setAttribute("min", this.mMinMonth);
+ this.mMonthField.setAttribute("max", this.mMaxMonth);
+ this.mMonthField.setAttribute("pginterval",
+ this.mMonthPageUpDownInterval);
+ this.mDayField.setAttribute("min", this.mMinDay);
+ this.mDayField.setAttribute("max", this.mMaxDay);
+ this.mDayField.setAttribute("pginterval", this.mDayPageUpDownInterval);
+ this.mYearField.setAttribute("min", this.mMinYear);
+ this.mYearField.setAttribute("max", this.mMaxYear);
+ this.mYearField.setAttribute("pginterval",
+ this.mYearPageUpDownInterval);
+
+ this.mDaySeparator =
+ document.getAnonymousElementByAttribute(this, "anonid", "sep-first");
+ this.mDaySeparator.textContent = this.mSeparatorText;
+ this.mYearSeparator =
+ document.getAnonymousElementByAttribute(this, "anonid", "sep-second");
+ this.mYearSeparator.textContent = this.mSeparatorText;
+
+ if (this.mInputElement.value) {
+ this.setFieldsFromInputValue();
+ }
+ ]]>
+ </constructor>
+
+ <method name="clearInputFields">
+ <parameter name="aFromInputElement"/>
+ <body>
+ <![CDATA[
+ this.log("clearInputFields");
+
+ if (this.isDisabled() || this.isReadonly()) {
+ return;
+ }
+
+ if (this.mMonthField && !this.mMonthField.disabled &&
+ !this.mMonthField.readOnly) {
+ this.mMonthField.value = "";
+ this.mMonthField.setAttribute("typeBuffer", "");
+ }
+
+ if (this.mDayField && !this.mDayField.disabled &&
+ !this.mDayField.readOnly) {
+ this.mDayField.value = "";
+ this.mDayField.setAttribute("typeBuffer", "");
+ }
+
+ if (this.mYearField && !this.mYearField.disabled &&
+ !this.mYearField.readOnly) {
+ this.mYearField.value = "";
+ this.mYearField.setAttribute("typeBuffer", "");
+ }
+
+ if (!aFromInputElement) {
+ this.mInputElement.setUserInput("");
+ }
+ ]]>
+ </body>
+ </method>
+
+ <method name="setFieldsFromInputValue">
+ <body>
+ <![CDATA[
+ let value = this.mInputElement.value;
+ if (!value) {
+ this.clearInputFields(true);
+ return;
+ }
+
+ this.log("setFieldsFromInputValue: " + value);
+ let [year, month, day] = value.split("-");
+
+ this.setFieldValue(this.mYearField, year);
+ this.setFieldValue(this.mMonthField, month);
+ this.setFieldValue(this.mDayField, day);
+
+ this.notifyPicker();
+ ]]>
+ </body>
+ </method>
+
+ <method name="getDaysInMonth">
+ <parameter name="aMonth"/>
+ <parameter name="aYear"/>
+ <body>
+ <![CDATA[
+ // Javascript's month is 0-based, so this means last day of the
+ // previous month.
+ return new Date(aYear, aMonth, 0).getDate();
+ ]]>
+ </body>
+ </method>
+
+ <method name="isFieldInvalid">
+ <parameter name="aField"/>
+ <body>
+ <![CDATA[
+ if (this.isEmpty(aField.value)) {
+ return true;
+ }
+
+ let min = Number(aField.getAttribute("min"));
+ let max = Number(aField.getAttribute("max"));
+
+ if (Number(aField.value) < min || Number(aField.value) > max) {
+ return true;
+ }
+
+ return false;
+ ]]>
+ </body>
+ </method>
+
+ <method name="setInputValueFromFields">
+ <body>
+ <![CDATA[
+ if (this.isFieldInvalid(this.mYearField) ||
+ this.isFieldInvalid(this.mMonthField) ||
+ this.isFieldInvalid(this.mDayField)) {
+ // We still need to notify picker in case any of the field has
+ // changed. If we can set input element value, then notifyPicker
+ // will be called in setFieldsFromInputValue().
+ this.notifyPicker();
+ return;
+ }
+
+ let year = this.mYearField.value;
+ let month = this.mMonthField.value;
+ let day = this.mDayField.value;
+
+ if (day > this.getDaysInMonth(month, year)) {
+ // Don't set invalid date, otherwise input element's value will be
+ // set to empty.
+ return;
+ }
+
+ let date = [year, month, day].join("-");
+
+ this.log("setInputValueFromFields: " + date);
+ this.mInputElement.setUserInput(date);
+ ]]>
+ </body>
+ </method>
+
+ <method name="setFieldsFromPicker">
+ <body>
+ <![CDATA[
+ // TODO: Bug 1320225 - [DateTimeInput] Integration of input type=date
+ // input box with picker.
+ ]]>
+ </body>
+ </method>
+
+ <method name="handleKeypress">
+ <parameter name="aEvent"/>
+ <body>
+ <![CDATA[
+ if (this.isDisabled() || this.isReadonly()) {
+ return;
+ }
+
+ let targetField = aEvent.originalTarget;
+ let key = aEvent.key;
+
+ if (targetField.classList.contains("numeric") && key.match(/[0-9]/)) {
+ let buffer = targetField.getAttribute("typeBuffer") || "";
+
+ buffer = buffer.concat(key);
+ this.setFieldValue(targetField, buffer);
+ targetField.select();
+
+ let n = Number(buffer);
+ let max = targetField.getAttribute("max");
+ if (buffer.length >= targetField.maxLength || n * 10 > max) {
+ buffer = "";
+ this.advanceToNextField();
+ }
+ targetField.setAttribute("typeBuffer", buffer);
+ }
+ ]]>
+ </body>
+ </method>
+
+ <method name="incrementFieldValue">
+ <parameter name="aTargetField"/>
+ <parameter name="aTimes"/>
+ <body>
+ <![CDATA[
+ let value;
+
+ // Use current date if field is empty.
+ if (this.isEmpty(aTargetField.value)) {
+ let now = new Date();
+
+ if (aTargetField == this.mYearField) {
+ value = now.getFullYear();
+ } else if (aTargetField == this.mMonthField) {
+ value = now.getMonth() + 1;
+ } else if (aTargetField == this.mDayField) {
+ value = now.getDate();
+ } else {
+ this.log("Field not supported in incrementFieldValue.");
+ return;
+ }
+ } else {
+ value = Number(aTargetField.value);
+ }
+
+ let min = Number(aTargetField.getAttribute("min"));
+ let max = Number(aTargetField.getAttribute("max"));
+
+ value += Number(aTimes);
+ if (value > max) {
+ value -= (max - min + 1);
+ } else if (value < min) {
+ value += (max - min + 1);
+ }
+ this.setFieldValue(aTargetField, value);
+ aTargetField.select();
+ ]]>
+ </body>
+ </method>
+
+ <method name="handleKeyboardNav">
+ <parameter name="aEvent"/>
+ <body>
+ <![CDATA[
+ if (this.isDisabled() || this.isReadonly()) {
+ return;
+ }
+
+ let targetField = aEvent.originalTarget;
+ let key = aEvent.key;
+
+ switch (key) {
+ case "ArrowUp":
+ this.incrementFieldValue(targetField, 1);
+ break;
+ case "ArrowDown":
+ this.incrementFieldValue(targetField, -1);
+ break;
+ case "PageUp": {
+ let interval = targetField.getAttribute("pginterval");
+ this.incrementFieldValue(targetField, interval);
+ break;
+ }
+ case "PageDown": {
+ let interval = targetField.getAttribute("pginterval");
+ this.incrementFieldValue(targetField, 0 - interval);
+ break;
+ }
+ case "Home":
+ let min = targetField.getAttribute("min");
+ this.setFieldValue(targetField, min);
+ targetField.select();
+ break;
+ case "End":
+ let max = targetField.getAttribute("max");
+ this.setFieldValue(targetField, max);
+ targetField.select();
+ break;
+ }
+ this.setInputValueFromFields();
+ ]]>
+ </body>
+ </method>
+
+ <method name="getCurrentValue">
+ <body>
+ <![CDATA[
+ let year;
+ if (!this.isEmpty(this.mYearField.value)) {
+ year = Number(this.mYearField.value);
+ }
+
+ let month;
+ if (!this.isEmpty(this.mMonthField.value)) {
+ month = Number(this.mMonthField.value);
+ }
+
+ let day;
+ if (!this.isEmpty(this.mDayField.value)) {
+ day = Number(this.mDayField.value);
+ }
+
+ let date = { year, month, day };
+
+ this.log("getCurrentValue: " + JSON.stringify(date));
+ return date;
+ ]]>
+ </body>
+ </method>
+
+ <method name="setFieldValue">
+ <parameter name="aField"/>
+ <parameter name="aValue"/>
+ <body>
+ <![CDATA[
+ let value = Number(aValue);
+ if (isNaN(value)) {
+ this.log("NaN on setFieldValue!");
+ return;
+ }
+
+ if (aValue.length == aField.maxLength) {
+ let min = Number(aField.getAttribute("min"));
+ let max = Number(aField.getAttribute("max"));
+
+ if (aValue < min) {
+ value = min;
+ } else if (aValue > max) {
+ value = max;
+ }
+ }
+
+ if (aField == this.mMonthField ||
+ aField == this.mDayField) {
+ // prepend zero
+ if (value < 10) {
+ value = "0" + value;
+ }
+ } else {
+ // prepend zeroes
+ if (value < 10) {
+ value = "000" + value;
+ } else if (value < 100) {
+ value = "00" + value;
+ } else if (value < 1000) {
+ value = "0" + value;
+ }
+
+ if (value.toString().length > this.mYearLength &&
+ value.toString().length <= this.mMaxYear.toString().length) {
+ this.mYearField.size = value.toString().length;
+ }
+ }
+
+ aField.value = value;
+ ]]>
+ </body>
+ </method>
+
+ <method name="isValueAvailable">
+ <body>
+ <![CDATA[
+ return !this.isEmpty(this.mMonthField.value) ||
+ !this.isEmpty(this.mDayField.value) ||
+ !this.isEmpty(this.mYearField.value);
+ ]]>
+ </body>
+ </method>
+
+ </implementation>
+ </binding>
+
<binding id="time-input"
extends="chrome://global/content/bindings/datetimebox.xml#datetime-input-base">
<resources>
@@ -745,6 +1144,12 @@
</body>
</method>
+ <method name="getCurrentValue">
+ <body>
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+ </body>
+ </method>
+
<method name="notifyPicker">
<body>
<![CDATA[
@@ -791,7 +1196,7 @@
break;
}
case "blur": {
- this.setInputValueFromFields();
+ this.onBlur(aEvent);
break;
}
case "copy":
@@ -822,6 +1227,19 @@
</body>
</method>
+ <method name="onBlur">
+ <parameter name="aEvent"/>
+ <body>
+ <![CDATA[
+ this.log("onBlur originalTarget: " + aEvent.originalTarget);
+
+ let target = aEvent.originalTarget;
+ target.setAttribute("typeBuffer", "");
+ this.setInputValueFromFields();
+ ]]>
+ </body>
+ </method>
+
<method name="onKeyPress">
<parameter name="aEvent"/>
<body>