--- a/toolkit/content/widgets/datetimebox.xml
+++ b/toolkit/content/widgets/datetimebox.xml
@@ -45,17 +45,16 @@
this.mDayPageUpDownInterval = 7;
this.mYearPageUpDownInterval = 10;
this.buildEditFields();
if (this.mInputElement.value) {
this.setFieldsFromInputValue();
}
- this.updateResetButtonVisibility();
]]>
</constructor>
<method name="buildEditFields">
<body>
<![CDATA[
const HTML_NS = "http://www.w3.org/1999/xhtml";
let root =
@@ -112,37 +111,33 @@
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", "");
+ this.clearFieldValue(this.mMonthField);
}
if (this.mDayField && !this.mDayField.disabled &&
!this.mDayField.readOnly) {
- this.mDayField.value = "";
- this.mDayField.setAttribute("typeBuffer", "");
+ this.clearFieldValue(this.mDayField);
}
if (this.mYearField && !this.mYearField.disabled &&
!this.mYearField.readOnly) {
- this.mYearField.value = "";
- this.mYearField.setAttribute("typeBuffer", "");
+ this.clearFieldValue(this.mYearField);
+ this.mYearField.size = this.mYearLength;
}
if (!aFromInputElement) {
this.mInputElement.setUserInput("");
}
-
- this.updateResetButtonVisibility();
]]>
</body>
</method>
<method name="setFieldsFromInputValue">
<body>
<![CDATA[
let value = this.mInputElement.value;
@@ -174,24 +169,25 @@
]]>
</body>
</method>
<method name="isFieldInvalid">
<parameter name="aField"/>
<body>
<![CDATA[
- if (this.isEmpty(aField.value)) {
+ let value = this.getFieldValue(aField);
+ if (this.isEmpty(value)) {
return true;
}
let min = Number(aField.getAttribute("min"));
let max = Number(aField.getAttribute("max"));
- if (Number(aField.value) < min || Number(aField.value) > max) {
+ if (value < min || value > max) {
return true;
}
return false;
]]>
</body>
</method>
@@ -208,26 +204,29 @@
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;
-
+ let { year, month, day } = this.getCurrentValue();
if (day > this.getDaysInMonth(month, year)) {
// Don't set invalid date, otherwise input element's value will be
// set to empty.
return;
}
+ // Convert to a valid date string according to:
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-date-string
+ year = year.toString().padStart(this.mYearLength, "0");
+ month = (month < 10) ? ("0" + month) : month;
+ day = (day < 10) ? ("0" + day) : day;
+
let date = [year, month, day].join("-");
this.log("setInputValueFromFields: " + date);
this.mInputElement.setUserInput(date);
]]>
</body>
</method>
@@ -265,17 +264,16 @@
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);
@@ -284,47 +282,45 @@
</body>
</method>
<method name="incrementFieldValue">
<parameter name="aTargetField"/>
<parameter name="aTimes"/>
<body>
<![CDATA[
- let value;
+ let value = this.getFieldValue(aTargetField);
// Use current date if field is empty.
- if (this.isEmpty(aTargetField.value)) {
+ if (this.isEmpty(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[
@@ -350,112 +346,100 @@
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 year = this.getFieldValue(this.mYearField);
+ let month = this.getFieldValue(this.mMonthField);
+ let day = this.getFieldValue(this.mDayField);
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[
+ if (!aField || !aField.classList.contains("numeric")) {
+ return;
+ }
+
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) {
+ if (value < min) {
value = min;
- } else if (aValue > max) {
+ } else if (value > 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;
- }
+ aField.setAttribute("rawValue", value);
- if (value.toString().length > this.mYearLength &&
- value.toString().length <= this.mMaxYear.toString().length) {
- this.mYearField.size = value.toString().length;
- }
+ // Display formatted value based on locale.
+ let minDigits = (aField == this.mYearField ? this.mYearLength
+ : aField.size);
+ let formatted = value.toLocaleString(this.mLocales, {
+ minimumIntegerDigits: minDigits,
+ useGrouping: false
+ });
+
+ if (aField == this.mYearField) {
+ this.mYearField.size = formatted.length;
}
- aField.value = value;
+ aField.value = formatted;
+ if (document.activeElement == this.mInputElement &&
+ this.mLastFocusedField && this.mLastFocusedField == aField) {
+ aField.select();
+ }
this.updateResetButtonVisibility();
]]>
</body>
</method>
<method name="isAnyValueAvailable">
<parameter name="aForPicker"/>
<body>
<![CDATA[
- return !this.isEmpty(this.mMonthField.value) ||
- !this.isEmpty(this.mDayField.value) ||
- !this.isEmpty(this.mYearField.value);
+ let { year, month, day } = this.getCurrentValue();
+
+ return !this.isEmpty(year) || !this.isEmpty(month) ||
+ !this.isEmpty(day);
]]>
</body>
</method>
</implementation>
</binding>
<binding id="time-input"
@@ -505,17 +489,16 @@
this.mHourPageUpDownInterval = 3;
this.mMinSecPageUpDownInterval = 10;
this.buildEditFields();
if (this.mInputElement.value) {
this.setFieldsFromInputValue();
}
- this.updateResetButtonVisibility();
]]>
</constructor>
<method name="getInputElementValues">
<body>
<![CDATA[
let value = this.mInputElement.value;
if (value.length === 0) {
@@ -1144,16 +1127,17 @@
this.mMin = this.mInputElement.min;
this.mMax = this.mInputElement.max;
this.mStep = this.mInputElement.step;
this.mIsPickerOpen = false;
this.mResetButton =
document.getAnonymousElementByAttribute(this, "anonid", "reset-button");
+ this.mResetButton.style.visibility = "hidden";
this.EVENTS.forEach((eventName) => {
this.addEventListener(eventName, this, { mozSystemGroup: true });
});
// Handle keypress separately since we need to catch it on capturing.
this.addEventListener("keypress", this, {
capture: true,
mozSystemGroup: true