mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1286182 - Implement the layout for <input type=date>. r=mconley,smaug
--HG-- rename : dom/html/test/forms/test_input_time_focus_blur_events.html => dom/html/test/forms/test_input_datetime_focus_blur_events.html
This commit is contained in:
parent
764b557d1e
commit
556aae19f0
@ -124,14 +124,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
|
||||
"Peaches", {"string": "linkAbbr"}, "Plums", {"string": "linkAbbr"},
|
||||
{"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"},
|
||||
@ -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" />
|
||||
|
@ -2763,7 +2763,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;
|
||||
}
|
||||
}
|
||||
@ -3215,7 +3216,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) {
|
||||
@ -3524,7 +3526,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();
|
||||
@ -3551,7 +3554,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();
|
||||
@ -3882,7 +3886,7 @@ HTMLInputElement::GetEventTargetParent(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) {
|
||||
@ -4002,7 +4006,8 @@ HTMLInputElement::GetEventTargetParent(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 ||
|
||||
@ -7112,13 +7117,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;
|
||||
|
@ -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 ||
|
||||
|
@ -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]
|
||||
|
228
dom/html/test/forms/test_input_date_key_events.html
Normal file
228
dom/html/test/forms/test_input_date_key_events.html
Normal file
@ -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>
|
@ -4,7 +4,7 @@
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
|
||||
-->
|
||||
<head>
|
||||
<title>Test focus/blur behaviour for <input type='time'></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>
|
||||
|
@ -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>
|
@ -4,7 +4,7 @@
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
|
||||
-->
|
||||
<head>
|
||||
<title>Test tabindex attribute for <input type='time'></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>
|
||||
|
@ -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>
|
@ -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');
|
||||
@ -138,6 +139,7 @@ function* runTest()
|
||||
]
|
||||
},
|
||||
{
|
||||
mobileOnly: true,
|
||||
type: 'date',
|
||||
validData: [
|
||||
'0001-01-01',
|
||||
@ -155,6 +157,28 @@ function* runTest()
|
||||
'1000-12-99',
|
||||
]
|
||||
},
|
||||
{
|
||||
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: [
|
||||
@ -213,6 +237,10 @@ function* runTest()
|
||||
for (test of data) {
|
||||
gCurrentTest = test;
|
||||
|
||||
if (gCurrentTest.mobileOnly && isDesktop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
input.type = test.type;
|
||||
gValidData = test.validData;
|
||||
gInvalidData = test.invalidData;
|
||||
|
@ -3664,13 +3664,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),
|
||||
|
@ -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);
|
||||
|
@ -776,6 +776,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 */
|
||||
details > summary:first-of-type,
|
||||
details > summary:-moz-native-anonymous {
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user